feat(opentelemetry): add streaming span lifecycle and operation metrics by ehsavoie · Pull Request #1236 · a2aproject/a2a-java · GitHub
Skip to content

feat(opentelemetry): add streaming span lifecycle and operation metrics - #1236

Merged
kabir merged 1 commit into
a2aproject:mainfrom
ehsavoie:issue_1216
Oct 21, 2026
Merged

kabir merged 1 commit into
a2aproject:mainfrom
ehsavoie:issue_1216

Conversation

@ehsavoie

@ehsavoie ehsavoie commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator
  • Per-event child spans linked to parent, terminal closing span, and duration histograms (client + server)
  • Extract shared StreamingEventAttributes and OtelSpanMocks test-jar; fix premature inline closing span

Fixes #1216 🦕

@ehsavoie
ehsavoie force-pushed the issue_1216 branch 2 times, most recently from acd33c1 to 3c2318d Compare October 20, 2026 12:44
@ehsavoie
ehsavoie requested a review from kabir October 20, 2026 13:57

@kabir kabir left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found two blocking telemetry gaps:

  1. gRPC client streams never produce the terminal span or duration metric. The new wrapper relies on its errorConsumer being called with null on successful completion, but gRPC EventStreamObserver.onCompleted() is a no-op. Successful gRPC streams therefore omit <method>-end and gen_ai.client.operation.duration. Please signal completion through the callback (or add a completion callback to the client transport contract) and cover it with a gRPC integration test.

  2. gRPC server streams commonly bypass the new terminal instrumentation. The decorator forwards the underlying subscription directly. The gRPC handler cancels that subscription when it sends a final task-status event, then closes the wire stream without invoking the decorator subscriber’s onComplete(). This skips the server <method>-end span and streaming-duration histogram for the normal final-status path, as well as client cancellation. Please intercept Subscription.cancel() or ensure the handler signals completion through the decorated subscriber.

@kabir kabir left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • P1 — REST streams never finish the new client telemetry. OpenTelemetryClientTransport.java:173 relies on errorConsumer.accept(null) to create the closing span and record the duration. RestTransport currently discards its SSE completion callback for both streaming methods, so a normally completed REST stream produces neither the -end span nor gen_ai.client.operation.duration. Update REST completion handlers to signal the listener/consumer with null (as JSON-RPC now does), and add a REST completion test.

- Per-event child spans and terminal closing span for streaming methods
- Duration histograms for client (gen_ai.client.operation.duration) and server (gen_ai.agent.a2a.streaming.duration)
- Signal REST stream completion to terminal consumer for proper span closing

Signed-off-by: Emmanuel Hugonnet <ehugonne@redhat.com>
@ehsavoie
ehsavoie requested a review from kabir October 21, 2026 13:35
@kabir
kabir merged commit c1c9434 into a2aproject:main Oct 21, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Server-side SSE per-event spans are missing

2 participants