Python 中如何以 JSON 格式输出日志?

Python 输出 JSON 格式日志的方法:json-logging 库、python-json-logger 库、或自定义 logging.Formatter。本文对比三种方案及各自的适用场景。

最佳实践
Python 中如何以 JSON 格式输出日志?封面

三种主流方式:json-logging 库(最简单,一行初始化)、python-json-logger 库(formatter 替换,灵活)、自定义 logging.Formatter(无第三方依赖,完全可控)。

方法一:json-logging 库

pip install json-logging
import logging, json_logging

json_logging.init_non_web(enable_json=True)
logging.info("这是一条 JSON 日志")

Web 框架用对应的初始化函数:json_logging.init_flask()、init_sanic() 等。

方法二:python-json-logger 库

pip install python-json-logger
import logging
from pythonjsonlogger import jsonlogger

handler = logging.StreamHandler()
handler.setFormatter(jsonlogger.JsonFormatter(
    '%(asctime)s %(name)s %(levelname)s %(message)s'
))

logger = logging.getLogger()
logger.addHandler(handler)
logger.setLevel(logging.INFO)

logger.info("用户登录", extra={"user_id": 42, "ip": "1.2.3.4"})

extra 传入的字段会成为 JSON 的顶层字段。

方法三:自定义 Formatter(无依赖)

import logging, json
from datetime import datetime, timezone

class JsonFormatter(logging.Formatter):
    def format(self, record):
        log = {
            "time": datetime.now(timezone.utc).isoformat(),
            "level": record.levelname,
            "logger": record.name,
            "message": record.getMessage(),
        }
        if record.exc_info:
            log["exception"] = self.formatException(record.exc_info)
        return json.dumps(log, ensure_ascii=False)

handler = logging.StreamHandler()
handler.setFormatter(JsonFormatter())
logging.getLogger().addHandler(handler)

为什么要用 JSON 日志

JSON 明确区分字段和值,可减少从文本猜测字段边界的工作。接入观测云时,可按 DataKit 日志采集文档启用 json_as_fields 提取顶层字段,再用一条测试日志核对数字类型、时间和级别;嵌套字段及重命名仍需配置解析。

常见问题(FAQ)

Q:JSON 日志里如何包含调用位置(文件名、行号)?
A:自定义 Formatter 中 record.filename、record.lineno、record.funcName 可获取。

Q:已有大量纯文本日志怎么办?
A:保留匹配现有格式的解析规则,先让新代码输出 JSON,再按服务逐步迁移;用相同样本比较关键字段,避免切换格式后查询失效。

Q:性能有差异吗?
A:JSON 序列化比字符串拼接略慢,但对日志场景影响可忽略。高频日志可用 orjson 替代标准 json。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台