Reputation: 1333
I am using the following logging snippet in my Django settings.py file. As seen in image below, all the logs are being captured twice.
The reason I kept root object as I wanted to capture logger.info() in console as well as log file
settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simple': {
'format': '[%(asctime)s] %(levelname)s|%(name)s|%(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
},
'handlers': {
'applogfile': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(BASE_DIR, 'django_blend.log'),
'backupCount': 10,
'formatter': 'simple',
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple'
}
},
'root': { # this tells to capture logger.info() to console as well as in log file
'handlers': ['console', 'applogfile'],
'level': 'INFO',
},
'loggers': {
'django': {
'handlers': ['applogfile', 'console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
}
}
}
django.log
Upvotes: 8
Views: 2338
Reputation: 14255
It's worth reading the documentation for logging.Logger.propagate carefully. It offers a very clear explanation of the propagation mechanism. There's also a note in there that says:
Note: If you attach a handler to a logger and one or more of its ancestors, it may emit the same record multiple times. In general, you should not need to attach a handler to more than one logger - if you just attach it to the appropriate logger which is highest in the logger hierarchy, then it will see all events logged by all descendant loggers, provided that their propagate setting is left set to True. A common scenario is to attach handlers only to the root logger, and to let propagation take care of the rest.
(my emphasis)
The OP's example has duplicate handlers for the root
and django
loggers, so removing the duplicated handlers from the django
logger should work.
If you need specific handlers for specific modules, you can add them explicitly and set propagate=False
there, as explained e.g. here.
Upvotes: 2
Reputation: 1349
Add 'propagate': False loggers.
'loggers': {
'django': {
'handlers': ['applogfile', 'console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
# prevent duplicate log in console
'propagate': False,
}
}
Upvotes: 8
Reputation: 77
I tested your code in Django 3.2.7 if remove the root object it works fine and you also don't have the duplicate lines.
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simple': {
'format': '[%(asctime)s] %(levelname)s|%(name)s|%(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
},
'handlers': {
'applogfile': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(BASE_DIR, 'django_blend.log'),
'backupCount': 10,
'formatter': 'simple',
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple'
}
},
'loggers': {
'django': {
'handlers': ['applogfile', 'console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
},
},
}
Upvotes: 0