使用python标准日志记录模块,可以使用以下命令添加始发日志调用的行号:%(lineno)s.
如何使用structlog做到这一点?
答案 0 :(得分:1)
我最终创建了一个custom processor
我被告知what structlog
does输出模块和行号,当它们被告知“假装” 以与logging
库兼容的格式进行格式化时(含义:当它使用常规stdlib.LoggerFactory
时,我从中发现了灵感。单词在哪里的关键...
通过使用structlog的structlog.stdlib.LoggerFactory,还可以确保以您的日志格式正确扩展函数名称和行号之类的变量。
似乎一直在寻找执行框架,直到找到与日志无关的模块中的框架为止。
我在名为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