GenAI Utils | Add agent metrics, and events #4329
Conversation
d1959e6 to
8f2f3e1
Compare
| attributes[error_attributes.ERROR_TYPE] = error_type | ||
|
|
||
| if duration_seconds is not None: | ||
| self._duration_histogram.record( |
There was a problem hiding this comment.
We might need to emit gen_ai.agent.duration metric to capture the agent duration and operation duration might not suffice. Is gen_ai.agent.duration part of the sem conv?
| tool_definitions: list[dict[str, Any]] | None = None | ||
|
|
||
| # Span kind: CLIENT for remote agents, INTERNAL for in-process agents | ||
| is_remote: bool = True |
There was a problem hiding this comment.
Why is the default value True? Are we assuming the invoke agents will be a remote agent call by default and not an in-process agent?
Also, SpanContext already has a field to check for is remote - https://opentelemetry.io/docs/specs/otel/trace/api/#isremote. Maybe we can use that
|
This PR has been automatically marked as stale because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 days of this comment. |
|
This PR has been automatically marked as stale because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 days of this comment. |
There was a problem hiding this comment.
Pull request overview
This PR extends the opentelemetry-util-genai utility package to cover agent lifecycle telemetry by introducing first-class agent invocation types and wiring them into TelemetryHandler, including duration/token metrics and detailed inference-operation log events.
Changes:
- Add
AgentCreationandAgentInvocationinvocation types with span attribute population, metrics recording, and event emission. - Add
TelemetryHandlerfactory methods and context managers forcreate_agentand local/remoteinvoke_agent. - Add agent-focused unit tests and update the util changelog.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| util/opentelemetry-util-genai/tests/test_handler_agent.py | Adds unit tests for agent creation/invocation spans, metrics, and (intended) events. |
| util/opentelemetry-util-genai/src/opentelemetry/util/genai/invocation.py | Re-exports AgentCreation/AgentInvocation as part of the public invocation surface. |
| util/opentelemetry-util-genai/src/opentelemetry/util/genai/handler.py | Adds handler factory methods + context managers for agent operations. |
| util/opentelemetry-util-genai/src/opentelemetry/util/genai/_content.py | Introduces shared content-serialization helper used by invocation types. |
| util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py | Implements invoke_agent spans/metrics/events for local and remote agent calls. |
| util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_creation.py | Implements create_agent spans/metrics/events for agent creation. |
| util/opentelemetry-util-genai/CHANGELOG.md | Notes the new agent invocation types and handler methods. |
| from opentelemetry.util.genai._agent_creation import AgentCreation | ||
| from opentelemetry.util.genai._agent_invocation import AgentInvocation |
There was a problem hiding this comment.
The handler imports AgentCreation/AgentInvocation from private modules (_agent_creation/_agent_invocation) even though they are now publicly re-exported from opentelemetry.util.genai.invocation (as done for EmbeddingInvocation/InferenceInvocation/etc.). Prefer importing them from the public invocation module to keep private modules internal and keep handler imports consistent.
| from opentelemetry.util.genai._agent_creation import AgentCreation | ||
| from opentelemetry.util.genai._agent_invocation import AgentInvocation |
There was a problem hiding this comment.
Since AgentCreation/AgentInvocation are now part of this module’s public re-export surface, the usage example in the module docstring (the import list) should be updated to include them; otherwise the docstring is misleading for users relying on this file for the canonical import path.
| def test_invoke_agent_emits_event(self, _mock_exp, _mock_emit): | ||
| inv = self.handler.start_invoke_local_agent( | ||
| "openai", request_model="gpt-4" | ||
| ) | ||
| inv.agent_name = "Event Agent" | ||
| inv.stop() | ||
|
|
||
| # The logger.emit was called — verify via span attributes at minimum | ||
| spans = self.span_exporter.get_finished_spans() | ||
| assert len(spans) == 1 | ||
| assert spans[0].attributes[GenAI.GEN_AI_AGENT_NAME] == "Event Agent" | ||
|
|
There was a problem hiding this comment.
These tests patch should_emit_event/is_experimental_mode but don’t actually assert that a log event was emitted (or validate its event_name/attributes). Consider wiring a LoggerProvider with an InMemoryLogExporter (similar to existing event tests) and asserting that exactly one log record was produced with event_name="gen_ai.client.inference.operation.details" and expected agent attributes.
|
Closing this PR — the |
Description
Adds
gen_ai.client.operation.durationandgen_ai.client.token.usagehistogram metrics along withgen_ai.client.inference.operation.detailslog events for agent lifecycle operations (create_agent, invoke_agent).Demo app PR: #4343
Sample metrics output:
Sample events output:
Fixes # (issue)
Type of change
Does This PR Require a Core Repo Change?
Checklist:
See contributing.md for styleguide, changelog guidelines, and more.