Reputation: 21436
In built-in python's logging module you create a logger and log messages:
import logging
log = logging.getLogger('mylogger')
log.info('starting!')
You can also pass extras to the log message that will be used later by the formatter:
user = 'john doe'
log.info('starting!', extra={'user': 'john doe'})
However it's quite tedious to do it explicitly with every message. Is it possible to set extras for the whole logger, so they would be passed with every log?
Something like:
log = logging.getLogger('mylogger')
log.extras = {'user': 'john doe'}
log.info('starting!')
Currently the only way it seems is to monkey patch log()
method:
def patch_default_extras(logger, extras):
original_log = logger.log
def log_with_extras(level, msg, *args, **kwargs):
kwargs['extra'] = {**extras, **kwargs.get('extra', {})}
return original_log(level, msg, *args, **kwargs)
logger.log = log_with_extras
mylog = logging.getLogger('mylogger')
patch_default_extras(mylog, {'user': 'john doe'})
mylog = logging.getLogger('mylogger')
mylog.log(logging.ERROR, 'hello')
Which is rather ugly, but unless I'm missing something ‒ it's the only way?
Upvotes: 10
Views: 7114
Reputation: 5185
The builtin way to do this is using a logging adapter. A filter would also work but for your described use-case adapters are perfect.
import logging
logging.basicConfig(level=logging.DEBUG, format='user: %(user)s - message: %(msg)s')
logger = logging.getLogger()
logger_with_user = logging.LoggerAdapter(logger, {'user': 'jane doe'})
logger_with_user.info('test') # user: jane doe - message: test
Upvotes: 20