|
14 | 14 |
|
15 | 15 | import json |
16 | 16 | from types import SimpleNamespace |
17 | | -from unittest.mock import Mock |
| 17 | +from unittest.mock import Mock, call |
18 | 18 |
|
19 | 19 | from google.adk.models.llm_request import LlmRequest |
20 | 20 | from google.adk.tools.function_tool import FunctionTool |
21 | 21 |
|
22 | 22 | from veadk.tracing.telemetry.attributes.extractors.llm_attributes_extractors import ( |
23 | 23 | llm_gen_ai_request_functions, |
| 24 | + llm_gen_ai_usage_output_tokens, |
24 | 25 | ) |
| 26 | +from veadk.tracing.telemetry.attributes.extractors.types import ExtractorResponse |
25 | 27 |
|
26 | 28 |
|
27 | 29 | def test_request_functions_reuses_adk_request_declaration(monkeypatch): |
@@ -99,3 +101,35 @@ def test_request_functions_builds_missing_declaration_once(): |
99 | 101 | ) |
100 | 102 | assert parameters == {"type": "object"} |
101 | 103 | get_declaration.assert_called_once_with() |
| 104 | + |
| 105 | + |
| 106 | +def test_missing_output_token_count_is_not_written_to_span(): |
| 107 | + params = SimpleNamespace( |
| 108 | + llm_response=SimpleNamespace( |
| 109 | + usage_metadata=SimpleNamespace(candidates_token_count=None) |
| 110 | + ) |
| 111 | + ) |
| 112 | + response = llm_gen_ai_usage_output_tokens(params) |
| 113 | + span = Mock() |
| 114 | + |
| 115 | + ExtractorResponse.update_span(span, "gen_ai.usage.output_tokens", response) |
| 116 | + |
| 117 | + span.set_attribute.assert_not_called() |
| 118 | + |
| 119 | + |
| 120 | +def test_falsy_attribute_values_are_written_to_span(): |
| 121 | + span = Mock() |
| 122 | + |
| 123 | + ExtractorResponse.update_span(span, "zero", ExtractorResponse(content=0)) |
| 124 | + ExtractorResponse.update_span(span, "false", ExtractorResponse(content=False)) |
| 125 | + |
| 126 | + assert span.set_attribute.call_args_list == [call("zero", 0), call("false", False)] |
| 127 | + |
| 128 | + |
| 129 | +def test_none_values_in_attribute_mappings_are_not_written_to_span(): |
| 130 | + span = Mock() |
| 131 | + response = ExtractorResponse(content=[{"present": 0, "missing": None}]) |
| 132 | + |
| 133 | + ExtractorResponse.update_span(span, "unused", response) |
| 134 | + |
| 135 | + span.set_attribute.assert_called_once_with("present", 0) |
0 commit comments