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 日志

纯文本日志需要 grok/正则解析,容易出错;JSON 日志是结构化的,日志平台可以直接提取字段做检索和聚合,不需要写解析规则。

观测云对照

观测云 DataKit 采集 JSON 格式日志后,Pipeline 可直接提取顶层字段,无需编写 grok 模式;日志在日志查看器中按字段检索,监控器按字段值配置告警。

常见问题(FAQ)

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

Q:已有大量纯文本日志怎么办?
A:观测云 Pipeline 的 grok 函数可以解析纯文本日志提取字段;逐步迁移到 JSON 格式,新代码直接用结构化日志。

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

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

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

立即开始

选择观测云版本

代码托管平台