Python工程在持续迭代中难免出现运行时异常或业务逻辑错误,能否快速定位问题往往取决于日志是否规范。统一的日志追踪规范可以串联一次请求在多个模块中的执行轨迹,让排查从盲目翻找变为按图索骥。

为什么需要日志追踪规范
当系统由多个服务或模块组成时,单条错误日志无法说明请求从何处来、经过了哪些处理。缺乏规范的日志会带来以下困扰:
- 不同模块日志格式不一,难以自动化解析
- 错误信息中没有请求唯一标识,无法串联调用链
- 关键变量未输出,复现问题成本较高
核心规范建议
1. 使用结构化日志格式
推荐采用 JSON 格式输出日志,便于后续采集系统识别字段。Python 标准库 logging 配合自定义 Formatter 即可实现。
import logging
import json
class JsonFormatter(logging.Formatter):
def format(self, record):
log_data = {
"time": self.formatTime(record),
"level": record.levelname,
"module": record.module,
"message": record.getMessage()
}
return json.dumps(log_data, ensure_ascii=False)
logger = logging.getLogger("app")
handler = logging.StreamHandler()
handler.setFormatter(JsonFormatter())
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.info("服务启动完成")
2. 注入请求追踪标识
在 Web 请求入口生成 trace_id,并通过上下文变量传递到各层函数,使同一次请求的所有日志可关联。
import uuid
import logging
from contextvars import ContextVar
trace_id_var = ContextVar("trace_id", default="-")
def get_logger():
logger = logging.getLogger("app")
old_factory = logging.getLogRecordFactory()
def record_factory(*args, **kwargs):
record = old_factory(*args, **kwargs)
record.trace_id = trace_id_var.get()
return record
logging.setLogRecordFactory(record_factory)
return logger
def handle_request():
trace_id_var.set(uuid.uuid4().hex)
log = get_logger()
log.info("收到用户请求")
# 业务处理...
log.info("请求处理结束")
3. 记录关键上下文而非仅记错误
问题定位时,仅记录异常堆栈往往不够。应在日志中包含输入参数、用户标识与分支判断值。使用 extra 参数可附加结构化字段。
logger.info("订单创建", extra={"user_id": 1001, "order_amount": 59.9})
日志层级使用约定
| 级别 | 使用场景 |
|---|---|
| DEBUG | 开发期详细流程与变量快照 |
| INFO | 正常关键节点,如服务启动、请求进入 |
| WARNING | 可恢复异常,如重试成功 |
| ERROR | 导致功能失败的异常,需告警 |
小结
规范的 Python 工程日志追踪并不复杂,重点在于格式统一、上下文完整与请求标识串联。团队在落地时可将上述实践封装为公共库,要求所有新模块接入,从而显著降低线上问题定位成本。