Count TCP server connections in the public stats#219
Merged
gophergogo merged 2 commits intomainfrom Apr 20, 2026
Merged
Conversation
added 2 commits
April 20, 2026 12:59
server_stats_.connections_active and connections_total are supposed to track accepted connections on the server, but ConnectionImpl only raises ConnectionEvent::Connected on the client-side connect-completion path, never for server-accepted sockets. The per-connection lifecycle adapter therefore never fired the Connected branch of onConnectionLifecycleEvent, and the counters stayed at 0 on connect. The matching decrement on RemoteClose/LocalClose still ran, so after the first client disconnect connections_active wrapped the uint64 to UINT64_MAX. Bump the counters directly in onNewConnection, which is the server-side checkpoint where the socket is accepted, the filter chain is built, and the call runs on the dispatcher thread. The symmetric decrement in onConnectionLifecycleEvent also runs on that thread, so the stats stay consistent without extra synchronization. Remove the dead Connected/ConnectedZeroRtt increment branch from onConnectionLifecycleEvent to keep one canonical increment site -- otherwise a future change that did raise Connected for server connections would quietly double-count. The stdio path is unaffected: McpConnectionManager still raises Connected through ServerProtocolCallbacks::onConnectionEvent, which routes to the separate McpServer::onConnectionEvent handler and keeps its own increment.
Pin the accept-side stat counters with an integration test that opens three raw TCP clients, asserts connections_active grew by 3 (baseline-relative, since the SetUp readiness probe can also land as an accepted connection), then drains them via server shutdown and asserts connections_active returns to zero while connections_total stays at baseline+3. Shutdown-driven drain rather than client-initiated close is deliberate: a raw TCP client that never sent any application bytes does not reliably drive the server-side HTTP filter chain to observe the peer FIN, and coupling this stat test to that behavior would make it flaky. The drain path is dispatcher- driven and deterministic. Also adds a small waitForConnectionStatsIdle helper so SetUp can let any in-flight probe accepts settle before a test snapshots the baseline.
1044e06 to
8d5ade3
Compare
caleb2h
approved these changes
Apr 20, 2026
gophergogo
pushed a commit
that referenced
this pull request
Apr 20, 2026
server_stats_.connections_active and connections_total are supposed to track accepted connections on the server, but ConnectionImpl only raises ConnectionEvent::Connected on the client-side connect-completion path, never for server-accepted sockets. The per-connection lifecycle adapter therefore never fired the Connected branch of onConnectionLifecycleEvent, and the counters stayed at 0 on connect. The matching decrement on RemoteClose/LocalClose still ran, so after the first client disconnect connections_active wrapped the uint64 to UINT64_MAX. Bump the counters directly in onNewConnection, which is the server-side checkpoint where the socket is accepted, the filter chain is built, and the call runs on the dispatcher thread. The symmetric decrement in onConnectionLifecycleEvent also runs on that thread, so the stats stay consistent without extra synchronization. Remove the dead Connected/ConnectedZeroRtt increment branch from onConnectionLifecycleEvent to keep one canonical increment site -- otherwise a future change that did raise Connected for server connections would quietly double-count. The stdio path is unaffected: McpConnectionManager still raises Connected through ServerProtocolCallbacks::onConnectionEvent, which routes to the separate McpServer::onConnectionEvent handler and keeps its own increment.
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
McpServer's publicconnections_total/connections_activecounters never moved on TCP accepts.ConnectionImplraisesConnectedonly on the client-side connect-completion path, so the existing increment in the server'sonConnectionEvent/onConnectionLifecycleEventConnected branch was dead code for server sockets — the counters stayed at zero while real traffic landed, thenRemoteClosedecrements could wrap them intoUINT64_MAX.McpServer::onNewConnection, the server-side equivalent checkpoint (dispatcher thread, fully-assembled connection). The dead Connected branch inonConnectionLifecycleEventhas been simplified to a plain return so it can't silently drift back in.test_mcp_server_connection_lifecycle.cc: three concurrent TCP accepts pushconnections_activeup by 3 (baseline-relative), and the server-side drain path brings it back to zero whileconnections_totalstays at baseline+3.Test plan
ctest -R 'McpServerConnectionLifecycleTest|McpClientInitializeRoutingTest|McpInitializeRequestTest|McpServerResponsesTest'./tests/test_mcp_server_connection_lifecycle— 3 tests pass