Skip to content

fix(streamable_http): emit telemetry on SSE handler registration - #217

Merged
zoedsoupe merged 4 commits into
zoedsoupe:mainfrom
fypm-labs:pr/streamable-http-sse-register-telemetry
Jul 16, 2026
Merged

zoedsoupe merged 4 commits into
zoedsoupe:mainfrom
fypm-labs:pr/streamable-http-sse-register-telemetry

Conversation

@BobbieBarker

Copy link
Copy Markdown
Contributor

Problem

The Streamable HTTP transport has telemetry for transport init/connect/disconnect/terminate but no signal for the moment a client (re)attaches an SSE handler to a session. That reconnect point is exactly where hosts need a hook -- e.g. to observe standalone GET/SSE stream churn, or to react when a client reconnects after a zero-handler gap.

Solution

  • Add Anubis.Telemetry.event_transport_sse_handler_registered/0 returning [:transport, :sse_handler, :registered] (namespaced to [:anubis_mcp, ...] by Telemetry.execute/3).
  • Emit it from the {:register_sse_handler, ...} handler after the handler is monitored and recorded.
  • Metadata: %{transport: :streamable_http, server: term(), session_id: String.t(), handler_pid: pid(), handler_count: non_neg_integer()}, where handler_count is the number of SSE handlers connected after this registration. Measurements: %{count: 1, system_time: System.system_time()}.

Purely additive: no change to the register flow, keepalive, or reply.

Rationale

Not spec-mandated; this is a library observability affordance for the Streamable HTTP transport's SSE-stream lifecycle. It fills the one gap in the existing transport telemetry family (there are connect/disconnect/terminate events but nothing for per-handler re-attach), and it pairs naturally with Last-Event-ID resumability by exposing the reconnect trigger.

Tests

Adds a transport test that attaches a :telemetry handler and asserts the event fires once on registration with the documented metadata shape and a handler_count reflecting the connected set.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@zoedsoupe, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 56 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a91376a7-dd4c-4a62-945d-d28a092dad40

📥 Commits

Reviewing files that changed from the base of the PR and between 0558b10 and eff1c08.

📒 Files selected for processing (3)
  • lib/anubis/server/transport/streamable_http.ex
  • lib/anubis/telemetry.ex
  • test/anubis/server/transport/streamable_http_test.exs
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The Streamable HTTP transport has telemetry for transport
init/connect/disconnect/terminate but no signal for the moment a client
(re)attaches an SSE handler to a session. That reconnect point is exactly
where hosts need a hook -- e.g. to observe standalone GET/SSE stream
churn, or to react when a client reconnects after a zero-handler gap.

Emit `[:anubis_mcp, :transport, :sse_handler, :registered]` from the
`{:register_sse_handler, ...}` handler after the handler is monitored and
recorded. Metadata: %{transport, server, session_id, handler_pid,
handler_count}, where handler_count is the number of SSE handlers
connected after this registration. Measurements: %{count: 1,
system_time: System.system_time()}.

Purely additive: no change to the register flow, keepalive, or reply.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@BobbieBarker
BobbieBarker force-pushed the pr/streamable-http-sse-register-telemetry branch from 611268e to 5ccd9d5 Compare July 15, 2026 02:29
Comment thread lib/anubis/server/transport/streamable_http.ex Outdated
@zoedsoupe zoedsoupe changed the title feat(streamable_http): emit telemetry on SSE handler registration fix(streamable_http): emit telemetry on SSE handler registration Jul 16, 2026
@zoedsoupe
zoedsoupe merged commit ff13a96 into zoedsoupe:main Jul 16, 2026
12 checks passed
@zoedsoupe zoedsoupe mentioned this pull request Jul 16, 2026
zoedsoupe added a commit that referenced this pull request Jul 16, 2026
## Problem

The Streamable HTTP transport has telemetry for transport
init/connect/disconnect/terminate but no signal for the moment a client
(re)attaches an SSE handler to a session. That reconnect point is
exactly where hosts need a hook -- e.g. to observe standalone GET/SSE
stream churn, or to react when a client reconnects after a zero-handler
gap.

## Solution

- Add `Anubis.Telemetry.event_transport_sse_handler_registered/0`
returning `[:transport, :sse_handler, :registered]` (namespaced to
`[:anubis_mcp, ...]` by `Telemetry.execute/3`).
- Emit it from the `{:register_sse_handler, ...}` handler after the
handler is monitored and recorded.
- Metadata: `%{transport: :streamable_http, server: term(), session_id:
String.t(), handler_pid: pid(), handler_count: non_neg_integer()}`,
where `handler_count` is the number of SSE handlers connected after this
registration. Measurements: `%{count: 1, system_time:
System.system_time()}`.

Purely additive: no change to the register flow, keepalive, or reply.

## Rationale

Not spec-mandated; this is a library observability affordance for the
Streamable HTTP transport's SSE-stream lifecycle. It fills the one gap
in the existing transport telemetry family (there are
connect/disconnect/terminate events but nothing for per-handler
re-attach), and it pairs naturally with `Last-Event-ID` resumability by
exposing the reconnect trigger.

## Tests

Adds a transport test that attaches a `:telemetry` handler and asserts
the event fires once on registration with the documented metadata shape
and a `handler_count` reflecting the connected set.

---------

Co-authored-by: zoey <zoey.spessanha@zeetech.io>
@zoedsoupe zoedsoupe mentioned this pull request Jul 16, 2026
zoedsoupe added a commit that referenced this pull request Jul 16, 2026
🚀 Want to release this?
---


##
[1.9.0](v1.8.0...v1.9.0)
(2026-07-16)


### Features

* **streamable_http:** add spec resumability (Last-Event-ID replay)
([#216](#216))
([78e33b4](78e33b4))
* support pre_initialized sessions for cross-pod restore
([#187](#187))
([13be0d7](13be0d7))


### Bug Fixes

* **session:** return encodable JSON-RPC errors when init/2 fails
([#211](#211))
([f9af7cc](f9af7cc))
* **streamable_http:** emit telemetry on SSE handler registration
([#217](#217))
([4a4c528](4a4c528))
* **streamable_http:** restore session from store on notif/resp registry
miss ([#221](#221))
([d757b39](d757b39))
* **streamable_http:** return correct JSON-RPC error codes for parse
failures ([#222](#222))
([1867994](1867994))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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.

2 participants