Why do my log messages appear in root logging file twice? - python

I have script.py file in which I import requests module. I have noticed that by using root logger at the level DEBUG, I can log all GET requests which is nice.
But I would like to have another log file to log other messages at INFO level. So I did this:
# root logger to log all GET requests
import logging
logging.basicConfig(filename= "allrequests.log", level=logging.DEBUG,
format='%(asctime)s: %(levelname)s: %(message)s')
# second logger to log only INFO
formatter = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s')
handler = logging.FileHandler('onlyinfo.log')
info_logger = logging.getLogger('second_logger')
info_logger.setLevel(logging.INFO)
info_logger.addHandler(handler)
the problem is now, whenever I use:
info_logger.info('my message')
it will log it twice in the first log file and once in the second file.
It would be fine, if it only logs info messages once in each file.
In other words I would like to log all messages (DEBUG and INFO level messages) in one log file and only INFO messages in another log file. How can I do this?

Related

Python logger is not creating log file despite a FileHandler being specified

I've been using a logger to log messages to a file and also output them to the console. I don't believe I did anything wrong, but the log file hasn't been being created for a few of the runs that I did.
The code I have is:
log_msg_format = '[%(asctime)s - %(levelname)s - %(filename)s: %(lineno)d] %(message)s'
handlers = [logging.FileHandler(filename=args.log_filename), logging.StreamHandler()]
logging.basicConfig(format=log_msg_format,
level=logging.INFO,
handlers=handlers)
When I check the logging level for each of the handlers, they are both NOTSET. I thought that this might be the problem, but the script is still outputting log messages to the console which means that this shouldn't be a problem.
What might be going wrong?

Python Logging is failing

Just started to look up on the logging module and created a dummy program to understand the logger, handler and formatter. Here is the code
# logging_example.py
import logging
from datetime import datetime
import os
extension = datetime.now().strftime("%d-%b-%Y_%H_%M_%S_%p")
logfile = os.path.join("logs", f"demo_logging_{extension}.txt")
logger = logging.getLogger(__name__)
ch = logging.StreamHandler()
fh = logging.FileHandler(logfile)
ch.setLevel(logging.DEBUG)
fh.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
ch.setFormatter(formatter)
fh.setFormatter(formatter)
logger.addHandler(ch)
logger.addHandler(fh)
logger.info("Hello World")
When i execute the program the logs directory has the files but content is empty and nothing gets printed on the screen to. I am pretty sure I am missing something basic but am not able to catch it though :( .
I would appreciate any help.
Thank you
You have added log-level to the handlers but not to the logger. Which means, handler would have logged the message had the logger passed it. But since the logger threshold is higher it got dropped.
See this link
Add log-level to the logger also.
After adding the handlers:
logger.setLevel(logging.DEBUG)

Flask logging handler information

I have two logging handlers configured in my flask app. How to get the handler name which is in use by the app so according to that I will handle the logging.
logging.basicConfig(filename=’<yourfilename>.log‘, level=logging.DEBUG, format=’%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s’)
in this
%(asctime)s—A timestamp as a string.
%(levelname)s—The logging level as a string.
%(threadName)s—The thread name as a string.
%(message)s’—The log message.
-->> %(name)s—The logger name as a string.
here is the reference for the same

logging.StreamHandler.setLevel(logging.DEBUG) <--- doesn't work

I don't know why it can't log that message, i think everything is correctly set.
And logging.DEBUG is defined under logging module
import logging
import sys
logger = logging.getLogger('collega_GUI')
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s %(levelname)s --file: %(module)s --riga: %(lineno)d, %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.debug('def __init__')
But if i try to run this one, it works:
logger.warning('def __init__')
Where is the problem with this level variable?
The problem is that the debug level message was filtered out by the logger before it ever got to the handler. The problem is fixed by changing handler.setLevel(logging.DEBUG) to logger.setLevel(logging.DEBUG).
You can filter by log level in several different places as a log message is passed down the chain. By default, loggers only pass INFO and above and handlers accept everything. Allowing handlers to use different log levels is useful if you want different levels of logging to go to different places. For example, you could set your logger to DEBUG and then create one handler that logs to the screen at WARN and above, and another handler that logs to a file at DEBUG and above. The user gets a little info and the log file is chatty.

How do I format warnings captured with logging.captureWarnings?

I have used the following code to get warnings to be logged:
import logging
logging.captureWarnings(True)
formatter = logging.Formatter('%(asctime)s\t%(levelname)s\t%(message)s')
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(formatter)
This works, however, my logging formatter is not applied, and the warnings come out looking like this:
WARNING:py.warnings:/home/joakim/.virtualenvs/masterload/local/lib/python2.7/site-packages/MySQL_python-1.2.3c1-py2.7-linux-x86_64.egg/MySQLdb/cursors.py:100: Warning:
InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
instead of the expected format:
2012-11-12 18:19:44,421 INFO START updating products
How can I apply my normal formatting to captured warning messages?
You created a handler, but never configured the logging module to use it:
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(formatter)
You need to add this handler to a logger; the root logger for example:
logging.getLogger().addHandler(console_handler)
Alternatively, you can add the handler to the warnings logger only; the captureWarnings() documentation states that it uses py.warnings for captured warnings:
logging.getLogger('py.warnings').addHandler(console_handler)
Instead of creating a handler and formatter explicitly, you can also just call basicConfig() to configure the root logger:
logging.basicConfig(format='%(asctime)s\t%(levelname)s\t%(message)s', level=logging.DEBUG)
The above basic configuration is the moral equivalent of the handler configuration you set up.
logging.captureWarnings logs to a logger named py.warnings, so you need to add your handler to that logger:
import logging
logging.captureWarnings(True)
formatter = logging.Formatter('%(asctime)s\t%(levelname)s\t%(message)s')
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(formatter)
py_warnings_logger = logging.getLogger('py.warnings')
py_warnings_logger.addHandler(console_handler)
The documentation says that If capture is True, warnings issued by the warnings module will be redirected to the logging system. Specifically, a warning will be formatted using warnings.formatwarning() and the resulting string logged to a logger named 'py.warnings' with a severity of WARNING.
Therefore I would try to
# get the 'py.warnings' logger
log = logging.getLogger('py.warnings')
# assign the handler to it
log.addHandler(console_handler)

Categories

Resources