Mahesh
Mahesh

Reputation: 1333

Duplicate log output when using Django logging module

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

enter image description here

Upvotes: 8

Views: 2338

Answers (3)

djvg
djvg

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

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

VdGR
VdGR

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

Related Questions