Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions src/google/adk/telemetry/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
GEN_AI_TOOL_DESCRIPTION = 'gen_ai.tool.description'
GEN_AI_TOOL_NAME = 'gen_ai.tool.name'
GEN_AI_TOOL_TYPE = 'gen_ai.tool.type'

EMPTY_JSON_STRING = '{}'
# Needed to avoid circular imports
if TYPE_CHECKING:
from ..agents.base_agent import BaseAgent
Expand Down Expand Up @@ -140,16 +140,16 @@ def trace_tool_call(

# Setting empty llm request and response (as UI expect these) while not
# applicable for tool_response.
span.set_attribute('gcp.vertex.agent.llm_request', '{}')
span.set_attribute('gcp.vertex.agent.llm_response', '{}')
span.set_attribute('gcp.vertex.agent.llm_request', EMPTY_JSON_STRING)
span.set_attribute('gcp.vertex.agent.llm_response', EMPTY_JSON_STRING)

if _should_add_request_response_to_spans():
span.set_attribute(
'gcp.vertex.agent.tool_call_args',
_safe_json_serialize(args),
)
else:
span.set_attribute('gcp.vertex.agent.tool_call_args', {})
span.set_attribute('gcp.vertex.agent.tool_call_args', EMPTY_JSON_STRING)

# Tracing tool response
tool_call_id = '<not specified>'
Expand Down Expand Up @@ -179,7 +179,7 @@ def trace_tool_call(
_safe_json_serialize(tool_response),
)
else:
span.set_attribute('gcp.vertex.agent.tool_response', {})
span.set_attribute('gcp.vertex.agent.tool_response', EMPTY_JSON_STRING)


def trace_merged_tool_calls(
Expand Down Expand Up @@ -219,13 +219,13 @@ def trace_merged_tool_calls(
function_response_event_json,
)
else:
span.set_attribute('gcp.vertex.agent.tool_response', {})
span.set_attribute('gcp.vertex.agent.tool_response', EMPTY_JSON_STRING)
# Setting empty llm request and response (as UI expect these) while not
# applicable for tool_response.
span.set_attribute('gcp.vertex.agent.llm_request', '{}')
span.set_attribute('gcp.vertex.agent.llm_request', EMPTY_JSON_STRING)
span.set_attribute(
'gcp.vertex.agent.llm_response',
'{}',
EMPTY_JSON_STRING,
)


Expand Down Expand Up @@ -265,7 +265,7 @@ def trace_call_llm(
_safe_json_serialize(_build_llm_request_for_trace(llm_request)),
)
else:
span.set_attribute('gcp.vertex.agent.llm_request', {})
span.set_attribute('gcp.vertex.agent.llm_request', EMPTY_JSON_STRING)
# Consider removing once GenAI SDK provides a way to record this info.
if llm_request.config:
if llm_request.config.top_p:
Expand All @@ -290,7 +290,7 @@ def trace_call_llm(
llm_response_json,
)
else:
span.set_attribute('gcp.vertex.agent.llm_response', {})
span.set_attribute('gcp.vertex.agent.llm_response', EMPTY_JSON_STRING)

if llm_response.usage_metadata is not None:
span.set_attribute(
Expand Down Expand Up @@ -346,7 +346,7 @@ def trace_send_data(
]),
)
else:
span.set_attribute('gcp.vertex.agent.data', {})
span.set_attribute('gcp.vertex.agent.data', EMPTY_JSON_STRING)


def _build_llm_request_for_trace(llm_request: LlmRequest) -> dict[str, Any]:
Expand Down
76 changes: 28 additions & 48 deletions tests/unittests/telemetry/test_spans.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,20 @@ async def _create_invocation_context(
return invocation_context


def _assert_span_attribute_set_to_empty_json(mock_span, attribute_name: str):
"""Helper to assert span attribute is set to empty JSON string '{}'."""
calls = [
call
for call in mock_span.set_attribute.call_args_list
if call.args[0] == attribute_name
]
assert len(calls) == 1, f"Expected '{attribute_name}' to be set exactly once"
assert calls[0].args[1] == '{}', (
f"Expected JSON string '{{}}' for {attribute_name} when content capture"
f' is disabled, got {calls[0].args[1]!r}'
)


@pytest.mark.asyncio
async def test_trace_agent_invocation(mock_span_fixture):
"""Test trace_agent_invocation sets span attributes correctly."""
Expand Down Expand Up @@ -473,24 +487,12 @@ async def test_call_llm_disabling_request_response_content(
# Act
trace_call_llm(invocation_context, 'test_event_id', llm_request, llm_response)

# Assert
assert not any(
arg_name == 'gcp.vertex.agent.llm_request' and arg_value != {}
for arg_name, arg_value in (
call_obj.args
for call_obj in mock_span_fixture.set_attribute.call_args_list
)
), "Attribute 'gcp.vertex.agent.llm_request' was incorrectly set on the span."

assert not any(
arg_name == 'gcp.vertex.agent.llm_response' and arg_value != {}
for arg_name, arg_value in (
call_obj.args
for call_obj in mock_span_fixture.set_attribute.call_args_list
)
), (
"Attribute 'gcp.vertex.agent.llm_response' was incorrectly set on the"
' span.'
# Assert - Check attributes are set to JSON string '{}' not dict {}
_assert_span_attribute_set_to_empty_json(
mock_span_fixture, 'gcp.vertex.agent.llm_request'
)
_assert_span_attribute_set_to_empty_json(
mock_span_fixture, 'gcp.vertex.agent.llm_response'
)


Expand Down Expand Up @@ -536,27 +538,12 @@ def test_trace_tool_call_disabling_request_response_content(
function_response_event=mock_event_fixture,
)

# Assert
assert not any(
arg_name == 'gcp.vertex.agent.tool_call_args' and arg_value != {}
for arg_name, arg_value in (
call_obj.args
for call_obj in mock_span_fixture.set_attribute.call_args_list
)
), (
"Attribute 'gcp.vertex.agent.tool_call_args' was incorrectly set on the"
' span.'
# Assert - Check attributes are set to JSON string '{}' not dict {}
_assert_span_attribute_set_to_empty_json(
mock_span_fixture, 'gcp.vertex.agent.tool_call_args'
)

assert not any(
arg_name == 'gcp.vertex.agent.tool_response' and arg_value != {}
for arg_name, arg_value in (
call_obj.args
for call_obj in mock_span_fixture.set_attribute.call_args_list
)
), (
"Attribute 'gcp.vertex.agent.tool_response' was incorrectly set on the"
' span.'
_assert_span_attribute_set_to_empty_json(
mock_span_fixture, 'gcp.vertex.agent.tool_response'
)


Expand Down Expand Up @@ -584,14 +571,7 @@ def test_trace_merged_tool_disabling_request_response_content(
function_response_event=mock_event_fixture,
)

# Assert
assert not any(
arg_name == 'gcp.vertex.agent.tool_response' and arg_value != {}
for arg_name, arg_value in (
call_obj.args
for call_obj in mock_span_fixture.set_attribute.call_args_list
)
), (
"Attribute 'gcp.vertex.agent.tool_response' was incorrectly set on the"
' span.'
# Assert - Check attribute is set to JSON string '{}' not dict {}
_assert_span_attribute_set_to_empty_json(
mock_span_fixture, 'gcp.vertex.agent.tool_response'
)