如何使用structlog

时间:2019-02-25 18:21:46

标签: structlog

使用python标准日志记录模块,可以使用以下命令添加始发日志调用的行号:%(lineno)s.

如何使用structlog做到这一点?

2 个答案:

答案 0 :(得分:1)

我最终创建了一个custom processor

我被告知what structlog does输出模块和行号,当它们被告知“假装” 以与logging库兼容的格式进行格式化时(含义:当它使用常规stdlib.LoggerFactory时,我从中发现了灵感。单词在哪里的关键...

  

通过使用structlog的structlog.stdlib.LoggerFactory,还可以确保以您的日志格式正确扩展函数名称和行号之类的变量。

...来自this documentation page

似乎一直在寻找执行框架,直到找到与日志无关的模块中的框架为止。

我在名为structlog的模块中拥有my_libs.util.logger的所有设置,因此我想获得不在该模块中的第一帧,因此我告诉它添加与日志记录相关的{{ 1}}排除在外。这就是下面的代码中的my_libs.util.logger

在此示例中,为清楚起见,我在排除列表中硬编码了模块的名称(additional_ignores),但如果设置类似,则最好改用'my_libs.util.logger'

一旦找到 right 框架,提取任何类型的信息(模块名称,函数名称,行号...)都是非常容易的,尤其是使用inspect module时。我选择输出模块名称和行号,但是可以添加更多字段。

__name__

这将产生如下输出:

# file my_libs/util/logger.py
from structlog._frames import _find_first_app_frame_and_name

def show_module_info_processor(logger, _, event_dict):
    # If by any chance the record already contains a `modline` key,
    # (very rare) move that into a 'modline_original' key
    if 'modline' in event_dict:
        event_dict['modline_original'] = event_dict['modline']
    f, name = _find_first_app_frame_and_name(additional_ignores=[
        "logging",
        'my_libs.util.logger',  # could just be __name__
    ])
    if not f:
        return event_dict
    frameinfo = inspect.getframeinfo(f)
    if not frameinfo:
        return event_dict
    module = inspect.getmodule(f)
    if not module:
        return event_dict
    if frameinfo and module:
        event_dict['modline'] = '{}:{}'.format(
            module.__name__,
            frameinfo.lineno,
        )
    return event_dict

def setup_structlog(env=None):
    # . . . 
    ch.setFormatter(logging.Formatter('%(message)s'))

    logging.getLogger().handlers = [ch]

    processors = [
        structlog.stdlib.add_logger_name,
        structlog.stdlib.add_log_level,
        # . . . more . . . 
        show_module_info_processor,  # THIS!!!
        structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S"),
        structlog.processors.format_exc_info,
        structlog.processors.StackInfoRenderer(),
        # . . . more . . . 
    ]

    # . . . more . . . 
    structlog.configure_once(
        logger_factory=structlog.stdlib.LoggerFactory(),
        wrapper_class=structlog.stdlib.BoundLogger,
        context_class=structlog.threadlocal.wrap_dict(dict),
        processors=processors,
    )

答案 1 :(得分:0)

看看这个关于如何获得行号的更普遍问题的答案。 https://stackoverflow.com/a/3056270/5909155 不能使用log.bind(...)将其绑定到记录器,因为每次登录时都必须对其进行评估。因此,您应该添加这样的键值对

logger.log(..., lineno=inspect.getframeinfo(inspect.currentframe()).lineno)

每次。也许可以将其包装在一个函数中,例如:https://stackoverflow.com/a/20372465/5909155 别忘了

import inspect