The logging package offers the "extra" keyword argument in Logger.log to add user-defined attributes to the log record. LoggerAdaptors make it easy to use extras that are constant for a given logger; then simply use logger.debug, logger.info, ecc. But this won't support variable extra arguments.
The present recipe makes it easy to use "extra" attributes that are not constant but variables passed to the (modified) logging methods ('debug', 'info', ...)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #!/usr/bin/env python
import logging
def processArgs(self, *args):
msg = args[-1]
args = args[:-1]
# the following allows logging even in case of problems!
if not (len(args) == len(self.extras)):
noArgs = len(self.extras)
l = list(' ' * noArgs)
l[:len(args)] = args[:len(l)]
print "WARNING: wrong number of logging arguments"
args = l
extras = dict(zip(self.extras, args))
return (msg, extras)
def myLog(self, level, *args):
if self.isEnabledFor(level):
msg, extras = self.processArgs(*args)
self._log(level, msg, [], extra=extras)
def myDebug(self, *args):
self.log(logging.DEBUG, *args)
def myInfo(self, *args):
self.log(logging.INFO, *args)
def myWarning(self, *args):
self.log(logging.WARNING, *args)
def myError(self, *args):
self.log(logging.ERROR, *args)
def myCritical(self, *args):
self.log(logging.CRITICAL, *args)
def setLoggerExtras(logger, extras):
logger.extras = extras
logger.__class__.processArgs = processArgs
logger.__class__.log = myLog
logger.__class__.debug = myDebug
logger.__class__.info = myInfo
logger.__class__.warning = myWarning
logger.__class__.error = myError
logger.__class__.critical = myCritical
#-------------------------------------------------
if __name__ == '__main__':
import logging.handlers
def getRotFileLogger(name, filePath, maxBytes, maxCount,
logLevel=logging.DEBUG, format=None):
format = format or '%(asctime)s - %(levelname)s - %(message)s'
my_logger = logging.getLogger(name)
my_logger.setLevel(logLevel)
# Add the log message handler to the logger
handler = logging.handlers.RotatingFileHandler(
filePath, maxBytes=maxBytes, backupCount=maxCount)
formatter = logging.Formatter(format)
handler.setFormatter(formatter)
my_logger.addHandler(handler)
return my_logger
format = '%(asctime)s - %(levelname)s - %(extra1)s - %(extra2)s - %(message)s'
logger = getRotFileLogger('test', 'test.log', 1000, 10, format=format)
# simply set the extras
setLoggerExtras(logger, ['extra1', 'extra2'])
# and then log without explicit "extra" dict
logger.debug('xx1', 'xx2', 'debug')
logger.info('xx1', 'info') #missing arg
logger.warning('xx1', 'xx2', 'xx3', 'hello, a warning') #too many args
logger.error('some error')
logger.critical('some critical')
|