Files
kami_spider_monorepo/middleware/trace_context.py
danial 0e41e7acce feat(core): 初始化核心配置和部署文件
- 添加 .env.example 环境变量配置示例
- 添加 .gitignore 忽略文件配置
- 添加 core/config.py 配置管理模块
- 添加 deployments/k8s/configmap.yaml Kubernetes 配置
- 添加 core/database.py 数据库连接管理模块
- 添加 core/dependencies.py 全局依赖模块
- 添加 DEPENDENCIES_UPDATED.md 依赖更新记录
- 添加 deployments/k8s/deployment.yaml Kubernetes 部署配置- 添加 deployments/swarm/docker-compose.swarm.yml Docker Swarm 部署配置
- 添加 deployments/docker/docker-compose.yml Docker 部署配置
- 添加 deployments/docker/Dockerfile 应用镜像构建文件
- 添加 middleware/error_handler.py 全局异常处理中间件
2025-11-01 14:32:29 +08:00

106 lines
3.0 KiB
Python

"""
TraceID injection middleware with W3C Trace Context support.
Extracts or generates trace IDs and propagates them through the request lifecycle.
"""
import uuid
from typing import Callable
from fastapi import Request, Response
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.types import ASGIApp
from observability.logging import set_trace_id
class TraceContextMiddleware(BaseHTTPMiddleware):
"""
Middleware for trace context management.
Extracts trace ID from W3C Trace Context headers or generates a new one.
Adds trace ID to request state and response headers.
"""
def __init__(self, app: ASGIApp):
"""
Initialize middleware.
Args:
app: ASGI application
"""
super().__init__(app)
async def dispatch(self, request: Request, call_next: Callable) -> Response:
"""
Process request and inject trace context.
Args:
request: Incoming request
call_next: Next middleware or route handler
Returns:
Response: Response with trace ID header
"""
# Extract trace ID from W3C Trace Context header (traceparent)
# Format: 00-{trace_id}-{parent_id}-{flags}
trace_id = self._extract_trace_id(request)
# Generate new trace ID if not present
if not trace_id:
trace_id = str(uuid.uuid4())
# Store trace ID in request state
request.state.trace_id = trace_id
# Set trace ID in logging context
set_trace_id(trace_id)
# Process request
response = await call_next(request)
# Add trace ID to response headers
response.headers["X-Trace-ID"] = trace_id
return response
def _extract_trace_id(self, request: Request) -> str:
"""
Extract trace ID from request headers.
Supports:
- W3C Trace Context (traceparent header)
- X-Trace-ID custom header
Args:
request: Incoming request
Returns:
str: Trace ID or empty string if not found
"""
# Try X-Trace-ID header first (custom header)
trace_id = request.headers.get("X-Trace-ID", "")
if trace_id:
return trace_id
# Try W3C Trace Context traceparent header
# Format: 00-{trace_id}-{parent_id}-{flags}
traceparent = request.headers.get("traceparent", "")
if traceparent:
parts = traceparent.split("-")
if len(parts) >= 2:
# Extract trace_id (second part)
return parts[1]
return ""
def get_trace_id_from_request(request: Request) -> str:
"""
Get trace ID from request state.
Args:
request: FastAPI request
Returns:
str: Trace ID or empty string
"""
return getattr(request.state, "trace_id", "")