You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用structlog获取多个配置相互独立的日志记录器

问题原因

structlog.configure 修改的是全局默认配置,所有通过 structlog.get_logger() 无参创建的日志实例,默认都会共享这套全局处理器链。你在创建logger2之后调用configure修改全局规则,之前创建的logger1也会读取新的全局配置,自然就会输出JSON格式,不存在配置隔离。

实现方案

不要在代码运行中途修改全局配置,根据你的使用场景二选一即可:


方案1:创建完全独立的日志实例(推荐,适配差异大的双日志需求)

直接用 structlog.wrap_logger 给两类日志分别绑定独立的处理器链、独立的输出目标,完全不依赖全局配置,从根源上避免配置互相影响。

import structlog
from structlog.processors import (
    add_log_level,
    TimeStamper,
    ConsoleRenderer,
    JSONRenderer
)

# 1. 配置面向用户的控制台stderr日志:人类可读格式
console_logger_processors = [
    add_log_level,
    TimeStamper(fmt="%Y-%m-%d %H.%M"),
    ConsoleRenderer(),
]
logger1 = structlog.wrap_logger(
    structlog.PrintLogger(file=open("/dev/stderr", "w", encoding="utf-8")),
    processors=console_logger_processors
)

# 2. 配置统计用JSON日志:输出到指定文件
json_logger_processors = [
    JSONRenderer(),
]
logger2 = structlog.wrap_logger(
    structlog.PrintLogger(file=open("stats_output.json", "a", encoding="utf-8")),
    processors=json_logger_processors
)

# 测试输出
logger1.info('make something that needs to be logged', x=1, y=2, z='abc')
logger2.info('structured_output', a=[1, 2, 3], b={'a': 1})
logger1.info('still no json output, great!')

运行后输出完全符合预期:

  • logger1始终输出带时间戳、日志级别的可读格式到stderr
  • logger2始终输出纯JSON格式到指定统计文件
  • 两个实例的配置完全独立,后续修改任意一方的处理器都不会影响另一方

方案2:全局路由分流(适配大部分日志用统一格式、少数特殊日志用JSON的场景)

如果不想为每个logger单独传配置,可以在程序启动时一次性配置全局处理器,根据logger名称分流到不同的渲染逻辑,后续创建logger时只需要指定不同名称即可。

import structlog
from structlog.processors import (
    add_log_level,
    TimeStamper,
    ConsoleRenderer,
    JSONRenderer
)

# 预定义两类渲染器
console_render_chain = [
    add_log_level,
    TimeStamper(fmt="%Y-%m-%d %H.%M"),
    ConsoleRenderer()
]
json_render = JSONRenderer()

def log_router(logger, method_name, event_dict):
    # 按logger名称分流
    log_name = event_dict.pop("_logger_name", "")
    if log_name == "stats":
        return json_render(logger, method_name, event_dict)
    # 默认走控制台可读格式
    for proc in console_render_chain:
        event_dict = proc(logger, method_name, event_dict)
    return event_dict

# 程序启动阶段只配置一次全局规则,后续禁止修改
structlog.configure(processors=[log_router])

# 按名称创建不同用途的logger
logger1 = structlog.get_logger("user_console")
logger2 = structlog.get_logger("stats")

# 测试输出效果和方案1完全一致
logger1.info('make something that needs to be logged', x=1, y=2, z='abc')
logger2.info('structured_output', a=[1, 2, 3], b={'a': 1})
logger1.info('still no json output, great!')
注意事项
  • 禁止在程序运行中途调用structlog.configure修改全局配置,这是导致日志格式串台的核心原因
  • 如果JSON日志需要输出到文件,不要和控制台日志共用同一个输出流,避免内容混在一起难以解析

内容的提问来源于stack exchange,提问作者Max

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 23:27:35