8000 fix(telemetry): replace TypeErrors with <replaced> string placeholder… · samhays/sdk-python@98ed211 · GitHub
[go: up one dir, main page]

Skip to content

Commit 98ed211

Browse files
authored
fix(telemetry): replace TypeErrors with <replaced> string placeholder (strands-agents#13)
1 parent a99107f commit 98ed211

File tree

2 files changed

+31
-11
lines changed

2 files changed

+31
-11
lines changed

src/strands/telemetry/tracer.py

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,26 @@
2727
logger = logging.getLogger(__name__)
2828

2929

30+
class JSONEncoder(json.JSONEncoder):
31+
"""Custom JSON encoder that handles non-serializable types."""
32+
33+
def default(self, obj: Any) -> Any:
34+
"""Handle non-serializable types.
35+
36+
Args:
37+
obj: The object to serialize
38+
39+
Returns:
40+
A JSON serializable version of the object
41+
"""
42+
value = ""
43+
try:
44+
value = super().default(obj)
45+
except TypeError:
46+
value = "<replaced>"
47+
return value
48+
49+
3050
class Tracer:
3151
"""Handles OpenTelemetry tracing.
3252
@@ -267,7 +287,7 @@ def start_model_invoke_span(
267287
"gen_ai.system": "strands-agents",
268288
"agent.name": agent_name,
269289
"gen_ai.agent.name": agent_name,
270-
"gen_ai.prompt": json.dumps(messages),
290+
"gen_ai.prompt": json.dumps(messages, cls=JSONEncoder),
271291
}
272292

273293
if model_id:
@@ -290,7 +310,7 @@ def end_model_invoke_span(
290310
error: Optional exception if the model call failed.
291311
"""
292312
attributes: Dict[str, AttributeValue] = {
293-
"gen_ai.completion": json.dumps(message["content"]),
313+
"gen_ai.completion": json.dumps(message["content"], cls=JSONEncoder),
294314
"gen_ai.usage.prompt_tokens": usage["inputTokens"],
295315
"gen_ai.usage.completion_tokens": usage["outputTokens"],
296316
"gen_ai.usage.total_tokens": usage["totalTokens"],
@@ -314,7 +334,7 @@ def start_tool_call_span(
314334
attributes: Dict[str, AttributeValue] = {
315335
"tool.name": tool["name"],
316336
"tool.id": tool["toolUseId"],
317-
"tool.parameters": json.dumps(tool["input"]),
337+
"tool.parameters": json.dumps(tool["input"], cls=JSONEncoder),
318338
}
319339

320340
# Add additional kwargs as attributes
@@ -340,8 +360,8 @@ def end_tool_call_span(
340360

341361
attributes.update(
342362
{
343-
"tool.result": json.dumps(tool_result.get("content")),
344-
"gen_ai.completion": json.dumps(tool_result.get("content")),
363+
"tool.result": json.dumps(tool_result.get("content"), cls=JSONEncoder),
364+
"gen_ai.completion": json.dumps(tool_result.get("content"), cls=JSONEncoder),
345365
"tool.status": status_str,
346366
}
347367
)
@@ -370,7 +390,7 @@ def start_event_loop_cycle_span(
370390
parent_span = parent_span if parent_span else event_loop_kwargs.get("event_loop_parent_span")
371391

372392
attributes: Dict[str, AttributeValue] = {
373-
"gen_ai.prompt": json.dumps(messages),
393+
"gen_ai.prompt": json.dumps(messages, cls=JSONEncoder),
374394
"event_loop.cycle_id": event_loop_cycle_id,
375395
}
376396

@@ -399,11 +419,11 @@ def end_event_loop_cycle_span(
399419
error: Optional exception if the cycle failed.
400420
"""
401421
attributes: Dict[str, AttributeValue] = {
402-
"gen_ai.completion": json.dumps(message["content"]),
422+
"gen_ai.completion": json.dumps(message["content"], cls=JSONEncoder),
403423
}
404424

405425
if tool_result_message:
406-
attributes["tool.result"] = json.dumps(tool_result_message["content"])
426+
attributes["tool.result"] = json.dumps(tool_result_message["content"], cls=JSONEncoder)
407427

408428
self._end_span(span, attributes, error)
409429

@@ -440,7 +460,7 @@ def start_agent_span(
440460
attributes["gen_ai.request.model"] = model_id
441461

442462
if tools:
443-
tools_json = tools
463+
tools_json = json.dumps(tools, cls=JSONEncoder)
444464
attributes["agent.tools"] = tools_json
445465
attributes["gen_ai.agent.tools"] = tools_json
446466

@@ -472,7 +492,7 @@ def end_agent_span(
472492
if response:
473493
attributes.update(
474494
{
475-
"gen_ai.completion": str(response),
495+
"gen_ai.completion": json.dumps(response, cls=JSONEncoder),
476496
}
477497
)
478498

tests/strands/telemetry/test_tracer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ def test_end_agent_span(mock_span):
369369

370370
tracer.end_agent_span(mock_span, mock_response)
371371

372-
mock_span.set_attribute.assert_any_call("gen_ai.completion", "Agent response")
372+
mock_span.set_attribute.assert_any_call("gen_ai.completion", '"<replaced>"')
373373
mock_span.set_attribute.assert_any_call("gen_ai.usage.prompt_tokens", 50)
374374
mock_span.set_attribute.assert_any_call("gen_ai.usage.completion_tokens", 100)
375375
mock_span.set_attribute.assert_any_call("gen_ai.usage.total_tokens", 150)

0 commit comments

Comments
 (0)
0