Skip to content

Commit 57b2772

Browse files
committed
feat(openai-agents): capture prompts, responses, and tool payloads
1 parent 9633585 commit 57b2772

File tree

2 files changed

+391
-5
lines changed
  • instrumentation-genai/opentelemetry-instrumentation-openai-agents/src/opentelemetry/instrumentation/openai_agents

2 files changed

+391
-5
lines changed

instrumentation-genai/opentelemetry-instrumentation-openai-agents/src/opentelemetry/instrumentation/openai_agents/__init__.py

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import importlib
2020
import os
21-
from typing import Collection
21+
from typing import Any, Collection
2222

2323
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
2424
from opentelemetry.semconv._incubating.attributes import (
@@ -28,11 +28,13 @@
2828
from opentelemetry.trace import get_tracer
2929

3030
from .package import _instruments
31-
from .span_processor import _OpenAIAgentsSpanProcessor
31+
from .span_processor import _ContentCaptureMode, _OpenAIAgentsSpanProcessor
3232
from .version import __version__ # noqa: F401
3333

3434
__all__ = ["OpenAIAgentsInstrumentor"]
3535

36+
_CONTENT_CAPTURE_ENV = "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"
37+
3638

3739
def _load_tracing_module():
3840
return importlib.import_module("agents.tracing")
@@ -57,6 +59,47 @@ def _get_registered_processors(provider) -> list:
5759
return list(processors)
5860

5961

62+
def _resolve_content_mode(value: Any) -> _ContentCaptureMode:
63+
if isinstance(value, _ContentCaptureMode):
64+
return value
65+
if isinstance(value, bool):
66+
return (
67+
_ContentCaptureMode.SPAN_AND_EVENT
68+
if value
69+
else _ContentCaptureMode.NO_CONTENT
70+
)
71+
72+
if value is None:
73+
return _ContentCaptureMode.SPAN_AND_EVENT
74+
75+
text = str(value).strip().lower()
76+
if not text:
77+
return _ContentCaptureMode.SPAN_AND_EVENT
78+
79+
mapping = {
80+
"span_only": _ContentCaptureMode.SPAN_ONLY,
81+
"span-only": _ContentCaptureMode.SPAN_ONLY,
82+
"span": _ContentCaptureMode.SPAN_ONLY,
83+
"event_only": _ContentCaptureMode.EVENT_ONLY,
84+
"event-only": _ContentCaptureMode.EVENT_ONLY,
85+
"event": _ContentCaptureMode.EVENT_ONLY,
86+
"span_and_event": _ContentCaptureMode.SPAN_AND_EVENT,
87+
"span-and-event": _ContentCaptureMode.SPAN_AND_EVENT,
88+
"span_and_events": _ContentCaptureMode.SPAN_AND_EVENT,
89+
"all": _ContentCaptureMode.SPAN_AND_EVENT,
90+
"true": _ContentCaptureMode.SPAN_AND_EVENT,
91+
"1": _ContentCaptureMode.SPAN_AND_EVENT,
92+
"yes": _ContentCaptureMode.SPAN_AND_EVENT,
93+
"no_content": _ContentCaptureMode.NO_CONTENT,
94+
"false": _ContentCaptureMode.NO_CONTENT,
95+
"0": _ContentCaptureMode.NO_CONTENT,
96+
"no": _ContentCaptureMode.NO_CONTENT,
97+
"none": _ContentCaptureMode.NO_CONTENT,
98+
}
99+
100+
return mapping.get(text, _ContentCaptureMode.SPAN_AND_EVENT)
101+
102+
60103
class OpenAIAgentsInstrumentor(BaseInstrumentor):
61104
"""Instrumentation that bridges OpenAI Agents tracing to OpenTelemetry spans."""
62105

@@ -81,7 +124,17 @@ def _instrument(self, **kwargs) -> None:
81124
)
82125
system = _resolve_system(system_override)
83126

84-
processor = _OpenAIAgentsSpanProcessor(tracer=tracer, system=system)
127+
content_override = kwargs.get("capture_message_content")
128+
if content_override is None:
129+
content_override = os.getenv(_CONTENT_CAPTURE_ENV)
130+
131+
content_mode = _resolve_content_mode(content_override)
132+
133+
processor = _OpenAIAgentsSpanProcessor(
134+
tracer=tracer,
135+
system=system,
136+
content_mode=content_mode,
137+
)
85138

86139
tracing = _load_tracing_module()
87140
provider = tracing.get_trace_provider()

0 commit comments

Comments
 (0)