如何在structlog中同时使用两个不同的渲染器?
实现structlog多渲染器配置
要分别给控制台和日志文件配置不同的渲染器,核心是借助structlog.stdlib.ProcessorFormatter,让不同的logging handler使用各自的渲染逻辑。以下是修改后的完整配置:
import logging import logging.config import structlog from structlog.stdlib import BoundLogger, ProcessorFormatter # 1. 配置logging handlers和对应的ProcessorFormatter logging.config.dictConfig( { "version": 1, "disable_existing_loggers": False, "formatters": { # 控制台用带颜色的ConsoleRenderer "console_formatter": { "()": ProcessorFormatter, "processor": structlog.dev.ConsoleRenderer(colors=True), # 通用处理器链:和structlog配置里的通用部分一致 "foreign_pre_chain": [ structlog.contextvars.merge_contextvars, structlog.processors.add_log_level, structlog.processors.StackInfoRenderer(), structlog.processors.TimeStamper(fmt="iso"), ], }, # 文件用无颜色的ConsoleRenderer(或换成JSONRenderer更适合文件存储) "file_formatter": { "()": ProcessorFormatter, "processor": structlog.dev.ConsoleRenderer(colors=False), "foreign_pre_chain": [ structlog.contextvars.merge_contextvars, structlog.processors.add_log_level, structlog.processors.StackInfoRenderer(), structlog.processors.TimeStamper(fmt="iso"), ], }, }, "handlers": { "default": { "level": "DEBUG", "class": "logging.StreamHandler", "formatter": "console_formatter", # 绑定控制台格式化器 }, "file": { "level": "INFO", "class": "logging.handlers.WatchedFileHandler", "filename": "/var/tmp/test.log", "formatter": "file_formatter", # 绑定文件格式化器 }, }, "loggers": { "": { "handlers": ["default", "file"], "level": "DEBUG", "propagate": True, }, }, } ) # 2. 配置structlog,只保留通用处理器,最终交给logging的Formatter处理 structlog.stdlib.recreate_defaults(log_level=None) structlog.configure( processors=[ structlog.contextvars.merge_contextvars, structlog.processors.add_log_level, structlog.processors.StackInfoRenderer(), structlog.processors.TimeStamper(fmt="iso"), # 将处理后的事件交给logging的Formatter完成最终渲染 structlog.stdlib.ProcessorFormatter.wrap_for_formatter, ], logger_factory=structlog.stdlib.LoggerFactory(), wrapper_class=BoundLogger, cache_logger_on_first_use=True, )
关键说明:
- ProcessorFormatter:作为structlog和标准logging之间的桥梁,允许我们为每个logging handler单独指定渲染器(
processor参数),同时通过foreign_pre_chain定义通用的日志处理步骤,避免重复代码。 - 控制台渲染器:使用
structlog.dev.ConsoleRenderer(colors=True),输出带颜色的美观日志,仅处理DEBUG及以上级别。 - 文件渲染器:使用
structlog.dev.ConsoleRenderer(colors=False),输出无颜色的纯文本日志,仅处理INFO及以上级别;如果需要更适合日志分析的格式,也可以替换为structlog.processors.JSONRenderer()。 - structlog核心配置:移除了原有的顶层ConsoleRenderer,改用
wrap_for_formatter将事件传递给logging的Formatter完成最终渲染,确保不同handler使用各自的渲染逻辑。
测试示例:
log = structlog.get_logger() log.debug("这是一条DEBUG日志,只会出现在控制台") log.info("这是一条INFO日志,会同时出现在控制台和日志文件")
内容的提问来源于stack exchange,提问作者gbajson
相关产品推荐
相关产品推荐

