python日志格式化程序,显示额外的所有kwargs

时间:2016-10-10 19:56:15

标签: python logging

我希望将以下日志点添加到我的应用程序中,并在控制台上显示extra的完整内容,例如

logger.info('Status', extra={'foo':data})
logger.info('Status', extra={'bar':data})
logger.info('Status', extra={'foo':data, 'bar':data}) 

我希望看到:

2016-10-10 15:28:31,408, INFO, Status, foo=data
2016-10-10 15:38:31,408, INFO, Status, bar=data
2016-10-10 15:48:31,408, INFO, Status, foo=data, bar=data

这甚至可能吗?根据官方日志记录文档,Formatter必须使用期望foobar的格式字符串进行设置,但在我的情况下,我想要的只是转储整个{{1}的kwargs。 1}}事先没有extrafoo

3 个答案:

答案 0 :(得分:1)

现在尝试解决同样的问题。问题是传递给extra的任何东西都被添加为LogRecord的属性,格式化程序无法将其与其他LogRecord属性区分开来。我只想出一种创建虚拟记录并将其与实际记录进行比较的hackish方法:

class ExtraLogFormatter(logging.Formatter):                                                                             
    def format(self, record):                                                                                           
        dummy = logging.LogRecord(None,None,None,None,None,None,None)                                                   
        extra_txt = ''                                                                                                  
        for k,v in record.__dict__.items():                                                                             
            if k not in dummy.__dict__:                                                                                 
                extra_txt += ', {}={}'.format(k,v)                                                                      
        message = super().format(record)                                                                                
        return message + extra_txt 

答案 1 :(得分:1)

格式化程序使用的LogRecord提供您所需的信息:

  • extra在其中被推为structured data
  • 实际消息可作为msg获得。

尽管我不知道可以使用简单的格式化程序配置从此extra打印所有键值的选项,但是可以选择使用自定义格式化程序来打印。

在此示例中,它显示了如何用结构化数据和文本消息的串联替换日志中的文本消息。

import logging


class ExtraFormatter(logging.Formatter):

    def format(self, record: logging.LogRecord) -> str:
        if hasattr(record, "structured_data") and 'user' in record.structured_data:
            # Override message with extra info
            record.msg = "%s %s" % (
                self._join_extra(record.structured_data['user']), 
                record.msg
            )
        return super().format(record)

    @staticmethod
    def _join_extra(extra: dict) -> str:
        return "[%s]" % ", ".join([
            '%s:%s' % (key, value) 
            for (key, value) in extra.items()
        ])

与此配合,使用:

logger.debug("Hello world!", extra={"foo", "bar", "baz": "qux"})

会让您:

[2018-11-26 15:43:33,794] [INFO] [__main__] [foo:bar, baz:qux] Hello world!

答案 2 :(得分:1)

extra传递的对象条目将成为LogRecord的成员变量。

logger.info('Status', extra={'my_params':{'foo':3, 'bar':4}})

然后您可以将其格式化为:

handler.setFormatter(logging.Formatter('%(message)s %(my_params)s'))

这将导致以下日志:

#> Status {'foo':3, 'bar':4}}

这假定您在登录时可以控制“额外”参数。