Skip to content

Commit 9ae367e

Browse files
committed
fix(openai-agents): apply content tracing flag to content
1 parent 0fc7340 commit 9ae367e

File tree

5 files changed

+63
-15
lines changed

5 files changed

+63
-15
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ npm-debug.log
3333
yarn-error.log
3434
testem.log
3535
/typings
36+
.tool-versions
3637

3738
# System Files
3839
.DS_Store

CONTRIBUTING.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,35 @@ Thanks for taking the time to contribute! 😃 🚀
44

55
Please refer to our [Contributing Guide](https://traceloop.com/docs/openllmetry/contributing/overview) for instructions on how to contribute.
66

7+
## Local Testing and Linting in this Repo
8+
9+
A few steps to set up this repo locally.
10+
11+
Run the following at repo root to setup the yarn dependencies.
12+
```shell
13+
npm ci
14+
```
15+
16+
Install `poetry` (version 2) at the system-level (e.g. using `pipx` or `brew`).
17+
18+
For setting up and testing an individual package, run the following from repo root.
19+
20+
```shell
21+
npx nx run opentelemetry-instrumentation-openai:install --with dev,test
22+
npx nx run opentelemetry-instrumentation-openai:lint
23+
npx nx run opentelemetry-instrumentation-openai:test
24+
```
25+
26+
Or you can run the following to automatically set up all affected packages.
27+
```shell
28+
npx nx affected -t install --with dev,test
29+
npx nx affected -t lint
30+
npx nx affected -t test
31+
```
32+
33+
## Build Errors
34+
35+
If encountering local build errors in environment setup, try a lower python version, e.g. 3.11.
36+
There are `.python-version` files in individual package directories, but poetry may not reliably respect it.
37+
Depending on your python installation, you may need to set your python version accordingly at repo root (e.g. with a `.python-version` or `.tool-versions`).
38+
The `.venv` dir within each package must be deleted before you retry the poetry/nx command, as it will not clear the existing venv and pick up the updated, lower version specified until the existing venv has been deleted manually.

packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Hook-based instrumentation for OpenAI Agents using the SDK's native callback system."""
22

3-
from typing import Dict, Any
3+
from typing import Dict, Any, Final
44
import json
55
import time
66
from collections import OrderedDict
@@ -11,7 +11,7 @@
1111
gen_ai_attributes as GenAIAttributes
1212
)
1313
from agents.tracing.processors import TracingProcessor
14-
from .utils import dont_throw
14+
from .utils import dont_throw, should_send_prompts
1515

1616
try:
1717
# Attempt to import once, so that we aren't looking for it repeatedly.
@@ -239,6 +239,7 @@ def on_span_end(self, span):
239239
if span in self._otel_spans:
240240
otel_span = self._otel_spans[span]
241241
span_data = getattr(span, 'span_data', None)
242+
should_trace_content: Final[bool] = should_send_prompts()
242243
if span_data and (
243244
type(span_data).__name__ == 'ResponseSpanData' or isinstance(
244245
span_data,
@@ -304,7 +305,7 @@ def on_span_end(self, span):
304305
otel_span.set_attribute(f"{prefix}.role", role)
305306

306307
# Set content attribute
307-
if content is not None:
308+
if should_trace_content and content is not None:
308309
if not isinstance(content, str):
309310
content = json.dumps(content)
310311
otel_span.set_attribute(f"{prefix}.content", content)
@@ -405,7 +406,7 @@ def on_span_end(self, span):
405406
if hasattr(response, 'output') and response.output:
406407
for i, output in enumerate(response.output):
407408
# Handle different output types
408-
if hasattr(output, 'content') and output.content:
409+
if should_trace_content and hasattr(output, 'content') and output.content:
409410
# Text message with content array (ResponseOutputMessage)
410411
content_text = ""
411412
for content_item in output.content:
@@ -436,7 +437,7 @@ def on_span_end(self, span):
436437
otel_span.set_attribute(
437438
f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.tool_calls.0.id", tool_call_id)
438439

439-
elif hasattr(output, 'text'):
440+
elif should_trace_content and hasattr(output, 'text'):
440441
# Direct text content
441442
otel_span.set_attribute(f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content", output.text)
442443
otel_span.set_attribute(
@@ -472,7 +473,7 @@ def on_span_end(self, span):
472473
elif span_data:
473474
# Extract prompt data from input and add to response span (legacy support)
474475
input_data = getattr(span_data, 'input', [])
475-
if input_data:
476+
if should_trace_content and input_data:
476477
for i, message in enumerate(input_data):
477478
if hasattr(message, 'role') and hasattr(message, 'content'):
478479
otel_span.set_attribute(f"gen_ai.prompt.{i}.role", message.role)
@@ -514,7 +515,7 @@ def on_span_end(self, span):
514515
if hasattr(response, 'output') and response.output:
515516
for i, output in enumerate(response.output):
516517
# Handle different output types
517-
if hasattr(output, 'content') and output.content:
518+
if should_trace_content and hasattr(output, 'content') and output.content:
518519
# Text message with content array (ResponseOutputMessage)
519520
content_text = ""
520521
for content_item in output.content:
@@ -545,7 +546,7 @@ def on_span_end(self, span):
545546
otel_span.set_attribute(
546547
f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.tool_calls.0.id", tool_call_id)
547548

548-
elif hasattr(output, 'text'):
549+
elif should_trace_content and hasattr(output, 'text'):
549550
# Direct text content
550551
otel_span.set_attribute(f"{GenAIAttributes.GEN_AI_COMPLETION}.{i}.content", output.text)
551552
otel_span.set_attribute(

packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/utils.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import traceback
77
from opentelemetry import context as context_api
88

9+
_TRACELOOP_TRACE_CONTENT = "TRACELOOP_TRACE_CONTENT"
10+
911

1012
def set_span_attribute(span, name, value):
1113
if value is not None:
@@ -18,10 +20,14 @@ def _is_truthy(value):
1820
return str(value).strip().lower() in ("true", "1", "yes", "on")
1921

2022

21-
def should_send_prompts():
22-
env_setting = os.getenv("TRACELOOP_TRACE_CONTENT", "true")
23+
def should_send_prompts() -> bool:
24+
"""Determine if LLM content tracing should be enabled.
25+
26+
Content includes not only prompts, but also responses.
27+
"""
28+
env_setting = os.getenv(_TRACELOOP_TRACE_CONTENT, "true")
2329
override = context_api.get_value("override_enable_content_tracing")
24-
return _is_truthy(env_setting) or bool(override)
30+
return _is_truthy(env_setting) or _is_truthy(override)
2531

2632

2733
class JSONEncoder(json.JSONEncoder):

packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/utils.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,18 @@ def run_async(method):
174174
asyncio.run(method)
175175

176176

177-
def should_send_prompts():
178-
return (
179-
os.getenv(TRACELOOP_TRACE_CONTENT) or "true"
180-
).lower() == "true" or context_api.get_value("override_enable_content_tracing")
177+
def _is_truthy(value):
178+
return str(value).strip().lower() in ("true", "1", "yes", "on")
179+
180+
181+
def should_send_prompts() -> bool:
182+
"""Determine if LLM content tracing should be enabled.
183+
184+
Content includes not only prompts, but also responses.
185+
"""
186+
env_setting = os.getenv(TRACELOOP_TRACE_CONTENT, "true")
187+
override = context_api.get_value("override_enable_content_tracing")
188+
return _is_truthy(env_setting) or _is_truthy(override)
181189

182190

183191
def should_emit_events() -> bool:

0 commit comments

Comments
 (0)