Coverage for merco/observability/tracing.py: 0%
37 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 14:04 +0800
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 14:04 +0800
1"""链路追踪"""
3import time
4import uuid
5from contextvars import ContextVar
7# 当前追踪 ID
8current_trace: ContextVar[str] = ContextVar("trace_id", default="")
11class TraceSpan:
12 """追踪跨度"""
14 def __init__(self, operation: str, parent_id: str = None):
15 self.operation = operation
16 self.trace_id = current_trace.get() or str(uuid.uuid4())[:8]
17 self.span_id = str(uuid.uuid4())[:8]
18 self.parent_id = parent_id
19 self.start_time = time.time()
20 self.end_time = None
21 self.attributes: dict = {}
23 def set_attribute(self, key: str, value):
24 """设置属性"""
25 self.attributes[key] = value
27 def end(self):
28 """结束跨度"""
29 self.end_time = time.time()
31 @property
32 def duration(self) -> float:
33 """获取耗时(秒)"""
34 if self.end_time:
35 return self.end_time - self.start_time
36 return time.time() - self.start_time
38 def to_dict(self) -> dict:
39 return {
40 "trace_id": self.trace_id,
41 "span_id": self.span_id,
42 "parent_id": self.parent_id,
43 "operation": self.operation,
44 "duration": self.duration,
45 "attributes": self.attributes,
46 }
49class Tracer:
50 """链路追踪器"""
52 def __init__(self):
53 self._spans: list[TraceSpan] = []
55 def start_span(self, operation: str, parent_id: str = None) -> TraceSpan:
56 """开始新的跨度"""
57 span = TraceSpan(operation, parent_id)
58 current_trace.set(span.trace_id)
59 self._spans.append(span)
60 return span
62 def get_spans(self, trace_id: str = None) -> list[dict]:
63 """获取跨度列表"""
64 spans = self._spans
65 if trace_id:
66 spans = [s for s in spans if s.trace_id == trace_id]
67 return [s.to_dict() for s in spans]