I have spent far too much time on this and I couldn't figure out by myself.
I am writing some code that use some modules, so I want to create a specific logger for my message, not those from the other modules (they are far too many so I don't want to set a different level for each of them).
I have simplified my use case to:
import logging
logger = logging.getLogger('test')
logger.setLevel(level=logging.INFO)
print(logging.Logger.manager.loggerDict)
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')
When I execute the previous code, I would expect to have my info message logged.
Instead I got:
python3 test.py
{'test': <Logger test (INFO)>}
This is a warning message
This is an error message
This is a critical message
Same with DEBUG, it always print warning/error/critical messages, not the debug/info.
If I raise the logging level (let's say ERROR), it works as expected.
python --version
Python 3.9.1
Change the configuration at the package level / root logger (documentation).
logging.basicConfig(level=logging.INFO)
Using the logging module to record the events:
import logging
#Creating an object
logger=logging.getLogger()
#Setting the threshold of logger to DEBUG
logger.setLevel(logging.DEBUG)
#Test messages
logger.debug("Debug Message")
logger.info("An information")
logger.warning("Warning")
logger.error("Error message")
logger.critical("critical Message")
Related
This code snippet, linked here, should be sending a log message to Papertrail, unfortunately, there's nothing happening at all (no error message either). I did replace the "N" and the "XXXXX" with my own values. The environment is Python 3.10.6 and I'm inside of a virtual environment created by Poetry.
I would expect calling an undefined function to log an exception to Papertrail.
Telnet works fine and my other applications work fine as well.
import logging
import socket
from logging.handlers import SysLogHandler
syslog = SysLogHandler(address=('logsN.papertrailapp.com', XXXXX))
format = '%(asctime)s YOUR_APP: %(message)s'
formatter = logging.Formatter(format, datefmt='%b %d %H:%M:%S')
syslog.setFormatter(formatter)
logger = logging.getLogger()
logger.addHandler(syslog)
logger.setLevel(logging.INFO)
def my_handler(type, value, tb):
logger.exception('Uncaught exception: {0}'.format(str(value)))
# Install exception handler
sys.excepthook = my_handler
logger.info('This is a message')
nofunction() #log an uncaught exception
I have this python code:
import logging
LOGGER = logging.getLogger(__name__)
LOGGER.info('test')
It does not get written to the console, so where does this get logged?
This does not get logged anywhere, because you did not configure any logging handlers. Without a handler configured, the log event goes nowhere. When there are no handlers configured, the root logger gets a handler automatically added if an event at WARNING or above is seen, but your event was just at INFO level.
If you put a line like this before, then you will see it logged to terminal:
logging.basicConfig(level=logging.INFO)
Basic config will add a StreamHandler writing to sys.stderr if you don't specify otherwise.
I have the following minimalist example of a logging test based on the Logging Cookbook:
import logging
logger = logging.getLogger('test')
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - '
'%(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
print(logger.handlers)
logger.debug('hello world')
The above produces the following output:
$ python test_log.py
[<StreamHandler <stderr> (DEBUG)>]
As I've defined a handler and set the log level to debug, I was expecting the hello world log message to show up in the sample above.
If a logger's level isn't explicitly set, the system looks up the level of ancestor loggers until it gets to a logger whose level is explicitly set. In this case, it's the root logger which is the parent of the logger named 'test'. Setting the level of either this logger or the root logger to DEBUG will result in the log message being output. See this part of the documentation for the event information flow in Python logging.
So if we call logger.debug('hello world') we are generating a DEBUG event. However the logger acts as first filter before passing the event to the handlers. So if the logger level is at higher severity (like INFO) it will filter the event and the handler won't receive it, even if the event was matching the handler's level (DEBUG).
So the logger's level should be as low as the lowest level of its handlers. If you don't want the rest of the handlers to log DEBUG messages you would need to explicitly set their level higher, instead of leaving it unset and therefor inherited from the logger.
I am trying to add logging to a medium size Python project with minimal disruption. I would like to log from multiple modules to rotating files silently (without printing messages to the terminal). I have tried to modify this example and I almost have the functionality I need except for one issue.
Here is how I am attempting to configure things in my main script:
import logging
import logging.handlers
import my_module
LOG_FILE = 'logs\\logging_example_new.out'
#logging.basicConfig(level=logging.DEBUG)
# Define a Handler which writes messages to rotating log files.
handler = logging.handlers.RotatingFileHandler(LOG_FILE, maxBytes=100000, backupCount=1)
handler.setLevel(logging.DEBUG) # Set logging level.
# Create message formatter.
formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
# Tell the handler to use this format
handler.setFormatter(formatter)
# Add the handler to the root logger
logging.getLogger('').addHandler(handler)
# Now, we can log to the root logger, or any other logger. First the root...
logging.debug('Root debug message.')
logging.info('Root info message.')
logging.warning('Root warning message.')
logging.error('Root error message.')
logging.critical('Root critical message.')
# Use a Logger in another module.
my_module.do_something() # Call function which logs a message.
Here is a sample of what I am trying to do in modules:
import logging
def do_something():
logger = logging.getLogger(__name__)
logger.debug('Module debug message.')
logger.info('Module info message.')
logger.warning('Module warning message.')
logger.error('Module error message.')
logger.critical('Module critical message.')
Now, here is my problem. I currently get the messages logged into rotating files silently. But I only get warning, error, and critical messages. Despite setting handler.setLevel(logging.DEBUG).
If I uncomment logging.basicConfig(level=logging.DEBUG), then I get all the messages in the log files but I also get the messages printed to the terminal.
How do I get all messages above the specified threshold to my log files without outputing them to the terminal?
Thanks!
Update:
Based on this answer, it appears that calling logging.basicConfig(level=logging.DEBUG) automatically adds a StreamHandler to the Root logger and you can remove it. When I did remove it leaving only my RotatingFileHandler, messages no longer printed to the terminal. I am still wondering why I have to use logging.basicConfig(level=logging.DEBUG) to set the message level threshold, when I am setting handler.setLevel(logging.DEBUG). If anyone can shed a little more light on these issues it would still be appreciated.
You need to call set the logging level on the logger itself as well. I believe by default, the logging level on the logger is logging.WARNING
Ex.
root_logger = logging.getLogger('')
root_logger.setLevel(logging.DEBUG)
# Add the handler to the root logger
root_logger.addHandler(handler)
The loggers log level determines what the logger will actually log (i.e what messages will actually get handed to the handlers). The handlers log level determines what it will actually handle (i.e. what messages actually are output to file, stream, etc). So you could potentially have multiple handlers attached to a logger each handling a different log level.
Here's an SO answer that explains the way this works
I can only see warning and error, how can I get info and debug printed out? To clarify, I am starting the tornado app with python app.py. I want the info and debug logs to print out to the console after I run the app.
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write('hello fun fun test world from tornado super')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.debug('debug')
application = tornado.web.Application([(r"/", MainHandler)], debug=True)
You probably need to change the level of the logging module to allow for debug and info messages to be displayed in the console.
logger.setLevel(logging.DEBUG) # this should allow all messages to be displayed
if you don't want to display debug messages then do this:
logger.setLevel(logging.INFO)
And just a quick fyi. Here are the levels in order, so if you set one of them it will display any messages of the types below the set level and it will NOT any messages above the set level.
logging.DEBUG
logging.INFO
logging.WARNING
logging.ERROR
logging.CRITICAL
By calling tornado.options.parse_command_line you register tornado command line flags.
You can use logging command line flag to change logging level from command line.
For more information: https://stackoverflow.com/a/14269208/63097
python helloworld.py --logging=debug
helloworld.py is tornado offical demo
more details about tornado/options.py
Here's the trick: you can directly modify tornados internal access logger:
import logging
import tornado
import tornado.log
tornado.log.access_log.setLevel(logging.DEBUG)