Coverage for src/lexigram/web/middleware/tracing.py: 36%
25 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 04:37 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 04:37 +0800
1"""W3C Trace Context (traceparent) utilities for Lexigram Web.
3This module provides utilities for parsing and generating W3C traceparent headers,
4enabling distributed tracing across web services.
5"""
7from __future__ import annotations
9import re
10from typing import TYPE_CHECKING
12from lexigram.contracts.core.trace_context import (
13 span_id_var,
14 trace_flags_var,
15 trace_id_var,
16)
18if TYPE_CHECKING:
19 from lexigram.primitives.context import RequestContext
21# W3C Traceparent Regex: version-traceid-spanid-flags
22# trace-id (32 hex), span-id (16 hex), flags (2 hex)
23TRACEPARENT_REGEX = re.compile(
24 r"^[0-9a-f]{2}-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$",
25)
28def extract_traceparent(header: str) -> dict[str, str] | None:
29 """Parse W3C traceparent header.
31 Returns a dict with trace_id, parent_id, and trace_flags if valid.
32 """
33 match = TRACEPARENT_REGEX.match(header.strip())
34 if match:
35 return {
36 "trace_id": match.group(1),
37 "parent_id": match.group(2),
38 "trace_flags": match.group(3),
39 }
40 return None
43def inject_traceparent() -> str | None:
44 """Generate W3C traceparent header from current core context."""
45 trace_id = trace_id_var.get(None)
46 span_id = span_id_var.get(None)
47 flags = trace_flags_var.get(None) or "01"
49 if trace_id and span_id:
50 return f"00-{trace_id}-{span_id}-{flags}"
51 return None
54def load_trace_to_context(ctx: RequestContext, header: str | None) -> None:
55 """Load trace context from W3C traceparent header into a RequestContext in-memory."""
56 if not header:
57 return
58 data = extract_traceparent(header)
59 if data:
60 ctx.trace_id = data["trace_id"]
61 ctx.trace_flags = data["trace_flags"]
64__all__ = [
65 "TRACEPARENT_REGEX",
66 "extract_traceparent",
67 "inject_traceparent",
68 "load_trace_to_context",
69]