ForcePilot/backend/package/yuxi/channel/runtime/trace_ctx.py
Kris d52e9b518d feat(channel/runtime): 新增链路追踪与启动运行时工具集
新增trace_ctx实现链路ID上下文管理与日志注入,添加boot.py启动管理器、startup.py启动任务执行器、backoff.py退避策略工具以及trace.py启动链路追踪模块,完善channel运行时基础能力
2026-05-21 10:28:46 +08:00

52 lines
1.4 KiB
Python

from __future__ import annotations
import contextvars
import logging
import uuid
from collections.abc import Generator
from contextlib import contextmanager
from typing import Any
_trace_id_var: contextvars.ContextVar[str | None] = contextvars.ContextVar(
"channel_trace_id", default=None
)
class TraceIdFilter(logging.Filter):
"""日志过滤器:自动将当前 trace_id 注入 LogRecord 的 trace_id 属性。
配合 logging.Formatter 使用,在日志格式中包含 %(trace_id)s 即可。
"""
def filter(self, record: logging.LogRecord) -> bool:
trace_id = get_trace_id()
record.trace_id = trace_id or "-"
return True
def generate_trace_id() -> str:
return uuid.uuid4().hex[:16]
def get_trace_id() -> str | None:
return _trace_id_var.get()
def set_trace_id(trace_id: str | None) -> None:
_trace_id_var.set(trace_id)
@contextmanager
def trace_context(trace_id: str | None = None, **metadata: Any) -> Generator[str, None, None]:
token = _trace_id_var.set(trace_id or generate_trace_id())
try:
yield _trace_id_var.get()
finally:
_trace_id_var.reset(token)
def install_trace_filter(logger_name: str | None = None) -> None:
root_logger = logging.getLogger(logger_name)
if not any(isinstance(f, TraceIdFilter) for f in root_logger.filters):
root_logger.addFilter(TraceIdFilter())