|
9 | 9 | from agents.tracing import ( |
10 | 10 | Span, |
11 | 11 | Trace, |
| 12 | + TracingProcessor, |
12 | 13 | agent_span, |
13 | 14 | custom_span, |
14 | 15 | function_span, |
15 | 16 | generation_span, |
16 | 17 | handoff_span, |
| 18 | + set_trace_processors, |
17 | 19 | trace, |
18 | 20 | ) |
19 | 21 | from agents.tracing.spans import SpanError |
@@ -410,6 +412,64 @@ def test_trace_and_spans_use_tracing_config_key(): |
410 | 412 | assert span.tracing_api_key == "tracing-key" |
411 | 413 |
|
412 | 414 |
|
| 415 | +def test_trace_metadata_propagates_to_spans(): |
| 416 | + metadata = {"source": "run"} |
| 417 | + with trace(workflow_name="test", metadata=metadata) as current_trace: |
| 418 | + with custom_span(name="direct_child", parent=current_trace) as direct_child: |
| 419 | + assert direct_child.trace_metadata == metadata |
| 420 | + with custom_span(name="parent") as parent: |
| 421 | + assert parent.trace_metadata == metadata |
| 422 | + with custom_span(name="child", parent=parent) as child: |
| 423 | + assert child.trace_metadata == metadata |
| 424 | + |
| 425 | + |
| 426 | +def test_processor_can_lookup_trace_metadata_by_span_trace_id(): |
| 427 | + class MetadataPropagatingProcessor(TracingProcessor): |
| 428 | + def __init__(self) -> None: |
| 429 | + self.trace_metadata_by_id: dict[str, dict[str, Any]] = {} |
| 430 | + self.looked_up_metadata: dict[str, Any] | None = None |
| 431 | + self.span_trace_metadata: dict[str, Any] | None = None |
| 432 | + |
| 433 | + def on_trace_start(self, trace: Trace) -> None: |
| 434 | + trace_metadata = getattr(trace, "metadata", None) |
| 435 | + if trace_metadata: |
| 436 | + self.trace_metadata_by_id[trace.trace_id] = dict(trace_metadata) |
| 437 | + |
| 438 | + def on_trace_end(self, trace: Trace) -> None: |
| 439 | + return None |
| 440 | + |
| 441 | + def on_span_start(self, span: Span[Any]) -> None: |
| 442 | + return None |
| 443 | + |
| 444 | + def on_span_end(self, span: Span[Any]) -> None: |
| 445 | + if span.span_data.type != "agent": |
| 446 | + return |
| 447 | + self.looked_up_metadata = self.trace_metadata_by_id.get(span.trace_id) |
| 448 | + self.span_trace_metadata = span.trace_metadata |
| 449 | + |
| 450 | + def shutdown(self) -> None: |
| 451 | + return None |
| 452 | + |
| 453 | + def force_flush(self) -> None: |
| 454 | + return None |
| 455 | + |
| 456 | + metadata = { |
| 457 | + "user_id": "u_123", |
| 458 | + "chat_type": "support", |
| 459 | + } |
| 460 | + processor = MetadataPropagatingProcessor() |
| 461 | + set_trace_processors([processor]) |
| 462 | + try: |
| 463 | + with trace(workflow_name="workflow", metadata=metadata): |
| 464 | + with agent_span(name="agent"): |
| 465 | + pass |
| 466 | + finally: |
| 467 | + set_trace_processors([SPAN_PROCESSOR_TESTING]) |
| 468 | + |
| 469 | + assert processor.looked_up_metadata == metadata |
| 470 | + assert processor.span_trace_metadata == metadata |
| 471 | + |
| 472 | + |
413 | 473 | def test_trace_to_json_only_includes_tracing_api_key_when_requested(): |
414 | 474 | with trace(workflow_name="test", tracing={"api_key": "secret-key"}) as tr: |
415 | 475 | default_json = tr.to_json() |
|
0 commit comments