如何将自定义字段添加到Python日志格式字符串中?

2024-05-23 18:28:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我当前的格式字符串是:

formatter = logging.Formatter('%(asctime)s : %(message)s')

我想添加一个名为app_name的新字段,它在包含此格式化程序的每个脚本中都有不同的值。

import logging
formatter = logging.Formatter('%(asctime)s %(app_name)s : %(message)s')
syslog.setFormatter(formatter)
logger.addHandler(syslog)

但我不确定如何将该app_name值传递给记录器以插入到格式字符串中。很明显,我可以让它出现在日志消息中,但每次都会传递它,但这很混乱。

我试过:

logging.info('Log message', app_name='myapp')
logging.info('Log message', {'app_name', 'myapp'})
logging.info('Log message', 'myapp')

但没用。


Tags: 字符串name程序info脚本logappmessage
3条回答

您可以使用LoggerAdapter,这样就不必在每次登录调用时传递额外的信息:

import logging
extra = {'app_name':'Super App'}

logger = logging.getLogger(__name__)
syslog = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s %(app_name)s : %(message)s')
syslog.setFormatter(formatter)
logger.setLevel(logging.INFO)
logger.addHandler(syslog)

logger = logging.LoggerAdapter(logger, extra)
logger.info('The sky is so blue')

日志(类似)

2013-07-09 17:39:33,596 Super App : The sky is so blue

Filters也可用于添加上下文信息。

import logging

class AppFilter(logging.Filter):
    def filter(self, record):
        record.app_name = 'Super App'
        return True

logger = logging.getLogger(__name__)
logger.addFilter(AppFilter())
syslog = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s %(app_name)s : %(message)s')
syslog.setFormatter(formatter)
logger.setLevel(logging.INFO)
logger.addHandler(syslog)

logger.info('The sky is so blue')

生成类似的日志记录。

另一种方法是创建自定义LoggerAdapter。当您无法更改格式,或者您的格式与不发送唯一密钥的代码共享时(在您的情况下为app-name),这一点特别有用:

class LoggerAdapter(logging.LoggerAdapter):
    def __init__(self, logger, prefix):
        super(LoggerAdapter, self).__init__(logger, {})
        self.prefix = prefix

    def process(self, msg, kwargs):
        return '[%s] %s' % (self.prefix, msg), kwargs

在您的代码中,您可以像往常一样创建和初始化记录器:

    logger = logging.getLogger(__name__)
    # Add any custom handlers, formatters for this logger
    myHandler = logging.StreamHandler()
    myFormatter = logging.Formatter('%(asctime)s %(message)s')
    myHandler.setFormatter(myFormatter)
    logger.addHandler(myHandler)
    logger.setLevel(logging.INFO)

最后,创建包装器适配器以根据需要添加前缀:

    logger = LoggerAdapter(logger, 'myapp')
    logger.info('The world bores you when you are cool.')

输出将如下所示:

2013-07-09 17:39:33,596 [myapp] The world bores you when you are cool.

您需要将dict作为参数传递给extra才能这样做。

logging.info('Log message', extra={'app_name': 'myapp'})

证明:

>>> import logging
>>> logging.basicConfig(format="%(foo)s - %(message)s")
>>> logging.warning('test', extra={'foo': 'bar'})
bar - test 

另外,需要注意的是,如果您尝试在不传递dict的情况下记录消息,那么它将失败。

>>> logging.warning('test')
Traceback (most recent call last):
  File "/usr/lib/python2.7/logging/__init__.py", line 846, in emit
    msg = self.format(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 723, in format
    return fmt.format(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 467, in format
    s = self._fmt % record.__dict__
KeyError: 'foo'
Logged from file <stdin>, line 1

相关问题 更多 >