如何向Pytest发送结构化日志并向控制台输出美观日志?
Pytest + Structlog 实现双日志流:美化控制台输出 + 结构化JSON报告
要同时实现Structlog的美观控制台输出和机器可读的JSON日志报告,核心是让Structlog分流日志事件到两个独立的处理器链,分别处理不同的输出格式和目标,互不干扰。
核心方案:用TeeProcessor分流日志
Structlog的TeeProcessor可以将同一条日志事件发送给多个处理器,我们可以分别配置:
- 一个处理器链负责控制台输出:用
ConsoleRenderer生成带颜色、简化格式的日志 - 另一个处理器链负责JSON报告:用
JSONRenderer生成完整结构化的JSON日志,输出到文件或Pytest插件指定的流
1. Structlog配置代码
import structlog from structlog.processors import ( JSONRenderer, ConsoleRenderer, TimeStamper, add_log_level, format_exc_info, TeeProcessor, FileRenderer, ) import sys def setup_structlog(): # 控制台处理器链:美化输出,省略冗余结构化字段,带颜色 console_chain = [ add_log_level, format_exc_info, ConsoleRenderer( colors=True, omit_event_id=True, # 自定义控制台格式,比如去掉时间戳 format="%(levelname)s: %(message)s" ) ] # JSON报告处理器链:保留所有结构化数据,包括时间戳 json_chain = [ add_log_level, TimeStamper(fmt="iso", utc=True, key="timestamp"), format_exc_info, JSONRenderer() ] structlog.configure( processors=[ # 通用预处理:添加日志级别、异常信息 add_log_level, format_exc_info, # 分流到两个处理器链 TeeProcessor( # 控制台输出到stdout structlog.stdlib.ProcessorFormatter.wrap_for_formatter( processors=console_chain, formatter=structlog.stdlib.ProcessorFormatter(processor=ConsoleRenderer()) ), # JSON输出到文件(可指定为Pytest插件需要的路径) FileRenderer( file_path="./test_logs.json", renderer=JSONRenderer() ) ) ], logger_factory=structlog.stdlib.LoggerFactory(), )
2. 配合Pytest配置
在conftest.py中初始化Structlog,并将JSON日志路径传递给插件:
import structlog def pytest_configure(config): # 初始化Structlog配置 setup_structlog() # 将JSON日志文件路径告知Pytest(根据插件需求调整) config.addinivalue_line("json_log_path", "./test_logs.json") def pytest_sessionfinish(session, exitstatus): # 可选:测试结束后处理JSON日志文件(比如传给插件生成报告) pass
3. 关键细节
- 时间戳分离:控制台日志通过
ConsoleRenderer的format参数自定义格式,省略时间戳;JSON日志通过TimeStamper添加标准时间戳,互不影响。 - 输出隔离:控制台输出到
stdout,JSON输出到独立文件,避免Pytest捕获控制台的美化输出,保证JSON报告的机器可读性。 - 字段过滤:如果需要在控制台隐藏某些结构化字段,可以在控制台处理器链中添加
structlog.processors.RemoveProcessor,比如移除key、more_than_strings这类字段,只保留日志消息和级别。
内容的提问来源于stack exchange,提问作者roegra
相关产品推荐
相关产品推荐

