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

Python logging输出JSON日志message为null问题及格式配置方案

问题原因
  • pythonjsonlogger 存在默认处理逻辑:当你直接给日志输出方法(如info()/debug())传入字典类型作为唯一位置参数时,这个字典会被判定为额外扩展字段,所有键值对会直接平铺到最终输出的JSON根结构下,不会被自动赋值给message字段。
  • 这种传参方式没有给日志传入标准的字符串类型消息内容,message字段找不到对应填充值,就会输出null。
调整方案

自定义继承JsonFormatter的格式化类,重写字段添加逻辑,自动识别传入的字典类型日志内容,按要求包装到message字段的数组中,同时清理根节点下重复平铺的业务字段,无需修改每一处日志调用代码即可实现目标结构。

可直接运行的调整后代码如下:

import logging
from datetime import datetime
from pythonjsonlogger import jsonlogger


class TargetJsonFormatter(jsonlogger.JsonFormatter):
    def add_fields(self, log_record, record, message_dict):
        super().add_fields(log_record, record, message_dict)
        # 识别传入的字典类型日志内容
        if isinstance(record.msg, dict):
            processed_content = {}
            # 自动处理datetime等无法直接序列化的类型
            for key, value in record.msg.items():
                if isinstance(value, datetime):
                    processed_content[key] = value.isoformat()
                else:
                    processed_content[key] = value
            # 按要求给message赋值为包裹内容的数组
            log_record["message"] = [processed_content]
            # 清理根节点下被平铺的重复业务字段
            for dup_key in processed_content.keys():
                if dup_key in log_record:
                    del log_record[dup_key]


def setup_logging(log_level):
    logger = logging.getLogger()
    logger.setLevel(log_level)
    # 避免重复添加日志处理器
    if logger.handlers:
        logger.handlers.clear()
    json_handler = logging.StreamHandler()
    formatter = TargetJsonFormatter(
        fmt="%(asctime)s %(levelname)s %(name)s %(message)s"
    )
    json_handler.setFormatter(formatter)
    logger.addHandler(json_handler)


setup_logging(logging.DEBUG)
logger = logging.getLogger()

StartTime = datetime.now()
message_dictionary = {
    "ApplicationName": "Application ABC",
    "StartTime": StartTime,
}

logger.info(message_dictionary)

运行上述代码后,输出日志结构完全匹配要求:

{
  "asctime": "2022-06-29 12:08:27,059",
  "levelname": "INFO",
  "name": "root",
  "message": [
    {
      "ApplicationName": "Application ABC",
      "StartTime": "2022-06-29T12:08:27.059175"
    }
  ]
}

补充:如果只是单次日志需要输出该结构,不需要全局统一配置,也可以直接在调用日志方法时手动构造消息:logger.info("", extra={"message": [message_dictionary]}),但这种方式需要修改每一处日志调用,维护成本更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:39:14