如何在Django项目中使用structlog记录序列化的回溯信息
解决structlog无法序列化回溯信息的问题
你需要调整structlog的处理器配置,确保traceback对象被转换为可序列化的字符串,同时避免重复的JSON格式化逻辑。以下是修改后的配置和说明:
修改后的logging.py配置
import logging.config import structlog from server.settings.components import BASE_DIR LOGGING = { "version": 1, "disable_existing_loggers": False, "formatters": { "plain": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.dev.ConsoleRenderer(), }, "json": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.processors.JSONRenderer(), }, }, "handlers": { "console": { "class": "logging.StreamHandler", "formatter": "plain", }, "file": { "class": "logging.handlers.RotatingFileHandler", "filename": BASE_DIR.joinpath("logs/structlog.log"), "formatter": "json", }, }, "root": { "level": "INFO", "handlers": ["console", "file"], }, "loggers": { "server": { "handlers": ["console", "file"], "level": "INFO", "propagate": False, }, }, } structlog.configure( processors=[ structlog.stdlib.filter_by_level, structlog.stdlib.add_logger_name, structlog.stdlib.add_log_level, structlog.tracebacks.extract, structlog.stdlib.PositionalArgumentsFormatter(), structlog.processors.TimeStamper(fmt="iso"), structlog.processors.StackInfoRenderer(), # 格式化traceback为可序列化的字符串 structlog.tracebacks.format_exc_info, # 最后交给logging的Formatter处理,移除多余的JSONRenderer structlog.stdlib.ProcessorFormatter.wrap_for_formatter, ], context_class=dict, logger_factory=structlog.stdlib.LoggerFactory(), wrapper_class=structlog.stdlib.BoundLogger, cache_logger_on_first_use=True, ) logging.config.dictConfig(LOGGING)
关键修改点说明
移除重复的JSONRenderer
你之前在structlog.configure中配置了structlog.processors.JSONRenderer(),但已经通过LOGGING的jsonformatter指定了相同的处理器,重复配置会导致traceback对象未被正确处理就被序列化。移除后,由ProcessorFormatter统一将处理后的事件传递给指定的格式化器。使用专门的traceback格式化处理器
替换structlog.processors.format_exc_info为structlog.tracebacks.format_exc_info,这个处理器会将exc_info中的traceback对象转换为包含完整调用栈的字符串,确保JSON序列化时不会出现无法处理的对象引用。保持处理器顺序
traceback格式化逻辑必须在structlog.stdlib.ProcessorFormatter.wrap_for_formatter之前执行,这样当事件传递给logging的格式化器时,所有字段都已经是可序列化的类型。
修改后,日志文件中的回溯信息会变成完整的字符串形式,示例如下:
{"event": "Internal Server Error: /healthcheck/error", "exc_info": "Traceback (most recent call last):\n File \"/path/to/django/core/handlers/exception.py\", line 55, in inner\n response = get_response(request)\n ... 完整的调用栈信息 ...", "level": "error", "logger": "server", "timestamp": "2024-05-20T12:34:56.789012"}
同时控制台的彩色输出依然会正常工作,ConsoleRenderer会自动解析traceback字符串并渲染为友好的格式。
内容的提问来源于stack exchange,提问作者ruslaniv
相关产品推荐
相关产品推荐

