"""TraceID 贯穿:ContextVar + 12-hex 生成 + logging.Filter。 每个 HTTP 请求生成唯一 trace_id,注入 ContextVar,日志通过 TraceFilter 自动带上 trace_id 字段,便于全链路追踪。 """ from __future__ import annotations import logging import random import contextvars # 单请求内贯穿的 trace_id trace_id_var: contextvars.ContextVar[str] = contextvars.ContextVar( "trace_id", default="" ) def new_trace_id() -> str: """生成 12 字符 hex trace_id。 Returns: 12 字符 hex 字符串(如 "a3b5c7d9e1f2") """ return f"{random.getrandbits(48):012x}" def get_trace_id() -> str: """获取当前 ContextVar 中的 trace_id。""" return trace_id_var.get() def set_trace_id(trace_id: str) -> contextvars.Token: """设置 trace_id,返回 Token 供 reset 使用。""" return trace_id_var.set(trace_id) def reset_trace_id(token: contextvars.Token) -> None: """重置 trace_id 到之前的状态。""" trace_id_var.reset(token) class TraceFilter(logging.Filter): """日志 Filter:在每条日志的 extra 中注入 trace_id。 用法: logger.addFilter(TraceFilter()) 日志格式中可用 %(trace_id)s 引用。 """ def filter(self, record: logging.LogRecord) -> bool: record.trace_id = trace_id_var.get() return True