|
24 | 24 | from microsoft_agents_a365.observability.core.constants import ( |
25 | 25 | CHANNEL_LINK_KEY, |
26 | 26 | CHANNEL_NAME_KEY, |
| 27 | + GEN_AI_AGENT_VERSION_KEY, |
| 28 | + GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY, |
| 29 | + GEN_AI_CALLER_AGENT_EMAIL_KEY, |
| 30 | + GEN_AI_CALLER_AGENT_ID_KEY, |
| 31 | + GEN_AI_CALLER_AGENT_NAME_KEY, |
| 32 | + GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY, |
| 33 | + GEN_AI_CALLER_AGENT_USER_ID_KEY, |
| 34 | + GEN_AI_CALLER_AGENT_VERSION_KEY, |
27 | 35 | GEN_AI_INPUT_MESSAGES_KEY, |
28 | 36 | SERVER_ADDRESS_KEY, |
29 | 37 | SERVER_PORT_KEY, |
@@ -92,6 +100,7 @@ def setUpClass(cls): |
92 | 100 | agentic_user_email="agent@contoso.com", |
93 | 101 | tenant_id="tenant-789", |
94 | 102 | agent_platform_id="platform-123", |
| 103 | + agent_version="2.1.0", |
95 | 104 | ) |
96 | 105 |
|
97 | 106 | def setUp(self): |
@@ -271,6 +280,94 @@ def test_span_processor_propagates_server_baggage_for_invoke_agent_span(self): |
271 | 280 | self.assertEqual(span_attributes.get(SERVER_ADDRESS_KEY), server_address) |
272 | 281 | self.assertEqual(span_attributes.get(SERVER_PORT_KEY), str(server_port)) |
273 | 282 |
|
| 283 | + def test_agent_version_set_on_span(self): |
| 284 | + """Test that agent_version from AgentDetails is set on span attributes.""" |
| 285 | + agent_with_version = AgentDetails( |
| 286 | + agent_id="versioned-agent", |
| 287 | + agent_name="Versioned Agent", |
| 288 | + agent_version="1.0.0", |
| 289 | + ) |
| 290 | + scope = InvokeAgentScope.start( |
| 291 | + self.test_request, |
| 292 | + self.invoke_scope_details, |
| 293 | + agent_with_version, |
| 294 | + ) |
| 295 | + if scope is not None: |
| 296 | + scope.dispose() |
| 297 | + |
| 298 | + finished_spans = self.span_exporter.get_finished_spans() |
| 299 | + self.assertTrue(finished_spans, "Expected at least one span") |
| 300 | + span_attributes = getattr(finished_spans[-1], "attributes", {}) or {} |
| 301 | + self.assertEqual(span_attributes.get(GEN_AI_AGENT_VERSION_KEY), "1.0.0") |
| 302 | + |
| 303 | + def test_agent_version_not_set_when_none(self): |
| 304 | + """Test that agent_version is not set on span when it is None.""" |
| 305 | + agent_without_version = AgentDetails( |
| 306 | + agent_id="no-version-agent", |
| 307 | + agent_name="No Version Agent", |
| 308 | + ) |
| 309 | + scope = InvokeAgentScope.start( |
| 310 | + self.test_request, |
| 311 | + self.invoke_scope_details, |
| 312 | + agent_without_version, |
| 313 | + ) |
| 314 | + if scope is not None: |
| 315 | + scope.dispose() |
| 316 | + |
| 317 | + finished_spans = self.span_exporter.get_finished_spans() |
| 318 | + self.assertTrue(finished_spans, "Expected at least one span") |
| 319 | + span_attributes = getattr(finished_spans[-1], "attributes", {}) or {} |
| 320 | + self.assertNotIn(GEN_AI_AGENT_VERSION_KEY, span_attributes) |
| 321 | + |
| 322 | + def test_caller_agent_version_set_on_span(self): |
| 323 | + """Test that caller agent version is emitted on invoke_agent spans.""" |
| 324 | + caller_with_version = CallerDetails( |
| 325 | + user_details=self.user_details, |
| 326 | + caller_agent_details=self.caller_agent_details, |
| 327 | + ) |
| 328 | + scope = InvokeAgentScope.start( |
| 329 | + self.test_request, |
| 330 | + self.invoke_scope_details, |
| 331 | + self.agent_details, |
| 332 | + caller_details=caller_with_version, |
| 333 | + ) |
| 334 | + if scope is not None: |
| 335 | + scope.dispose() |
| 336 | + |
| 337 | + finished_spans = self.span_exporter.get_finished_spans() |
| 338 | + self.assertTrue(finished_spans, "Expected at least one span") |
| 339 | + span_attributes = getattr(finished_spans[-1], "attributes", {}) or {} |
| 340 | + self.assertEqual(span_attributes.get(GEN_AI_CALLER_AGENT_VERSION_KEY), "2.1.0") |
| 341 | + |
| 342 | + def test_caller_agent_details_all_fields_set_on_span(self): |
| 343 | + """Test that all caller agent detail fields are set on span attributes.""" |
| 344 | + caller_with_agent = CallerDetails( |
| 345 | + user_details=self.user_details, |
| 346 | + caller_agent_details=self.caller_agent_details, |
| 347 | + ) |
| 348 | + scope = InvokeAgentScope.start( |
| 349 | + self.test_request, |
| 350 | + self.invoke_scope_details, |
| 351 | + self.agent_details, |
| 352 | + caller_details=caller_with_agent, |
| 353 | + ) |
| 354 | + if scope is not None: |
| 355 | + scope.dispose() |
| 356 | + |
| 357 | + finished_spans = self.span_exporter.get_finished_spans() |
| 358 | + self.assertTrue(finished_spans, "Expected at least one span") |
| 359 | + span_attributes = getattr(finished_spans[-1], "attributes", {}) or {} |
| 360 | + |
| 361 | + self.assertEqual(span_attributes.get(GEN_AI_CALLER_AGENT_NAME_KEY), "Caller Agent") |
| 362 | + self.assertEqual(span_attributes.get(GEN_AI_CALLER_AGENT_ID_KEY), "caller-agent-789") |
| 363 | + self.assertEqual( |
| 364 | + span_attributes.get(GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY), "blueprint-456" |
| 365 | + ) |
| 366 | + self.assertEqual(span_attributes.get(GEN_AI_CALLER_AGENT_USER_ID_KEY), "auid-123") |
| 367 | + self.assertEqual(span_attributes.get(GEN_AI_CALLER_AGENT_EMAIL_KEY), "agent@contoso.com") |
| 368 | + self.assertEqual(span_attributes.get(GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY), "platform-123") |
| 369 | + self.assertEqual(span_attributes.get(GEN_AI_CALLER_AGENT_VERSION_KEY), "2.1.0") |
| 370 | + |
274 | 371 |
|
275 | 372 | if __name__ == "__main__": |
276 | 373 | # Run pytest only on the current file |
|
0 commit comments