Skip to content

fix: incorrect metrics for active connections - #3122

Merged
Noroth merged 10 commits into
mainfrom
ludwig/router-560-router-reused-graph-muxes-dont-count-into-active_connections
Jul 31, 2026
Merged

fix: incorrect metrics for active connections#3122
Noroth merged 10 commits into
mainfrom
ludwig/router-560-router-reused-graph-muxes-dont-count-into-active_connections

Conversation

@Noroth

@Noroth Noroth commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Bug Fixes
    • Improved active_connections metric accuracy across router configuration hot reloads, including correct handling when subgraphs are added or removed.
    • Ensured connection-metrics are correctly created, reused, and shut down during graph server transitions to prevent stale readings.
    • Updated max-connection metric recording to use safe snapshots of per-subgraph limits.
  • Reliability
    • Added safeguards to prevent connection-metric initialization during router shutdown races.
  • Tests
    • Added hot-reload coverage for active_connections, plus lifetime tests for connection-metric store behavior across server swaps and shutdowns.

Checklist

Open Source AI Manifesto

This project follows the principles of the Open Source AI Manifesto. Please ensure your contribution aligns with its principles.

@Noroth
Noroth requested a review from a team as a code owner July 28, 2026 12:38

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

Claude Code Review is paused for this repository. To reconnect it, an admin of this repository's GitHub organization (or the account owner, for personal repositories) who can also manage your Claude organization's Code Review settings needs to re-link GitHub in Code Review settings. This is a one-time step.

Tip: disable this comment in your organization's Code Review settings.

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

Router image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-0cef48e7287b990e4d1468091a186c7a94388b5e

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Changes

Connection metrics lifecycle

Layer / File(s) Summary
Synchronized connection statistics access
router/pkg/metric/connection_pool_stats.go, router/pkg/metric/connection_metric_store.go, router/pkg/metric/oltp_connection_metric_store.go, router/pkg/metric/prom_connection_metric_store.go
Maximum connection counts now use mutex-protected storage, cloned accessor snapshots, and recording across both metric providers.
Router-scoped metric store lifecycle
router/core/router.go, router/core/graph_server.go, router/core/graph_server_test.go
Trace dialers and connection metric stores are cached on Router, guarded during shutdown, reused across graph-server swaps, and shut down centrally.
Hot-reload connection metric validation
router-tests/telemetry/connection_metrics_hot_reload_test.go
Adds manual-reader telemetry tests and reload helpers that verify mux reuse, mux shutdown, and per-subgraph active connection gauges.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is clearly related to the main change: fixing incorrect active connection metrics.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

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

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.32258% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.16%. Comparing base (cb6d98d) to head (3a4477a).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
router/core/router.go 90.00% 2 Missing and 2 partials ⚠️
router/core/graph_server.go 60.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            main    #3122       +/-   ##
==========================================
+ Coverage   1.58%   62.16%   +60.57%     
==========================================
  Files        327      262       -65     
  Lines      45805    30978    -14827     
  Branches     485        0      -485     
==========================================
+ Hits         728    19258    +18530     
+ Misses     44763    10199    -34564     
- Partials     314     1521     +1207     
Files with missing lines Coverage Δ
router/pkg/metric/connection_metric_store.go 72.41% <100.00%> (ø)
router/pkg/metric/connection_pool_stats.go 93.54% <100.00%> (ø)
router/pkg/metric/oltp_connection_metric_store.go 63.33% <ø> (ø)
router/pkg/metric/prom_connection_metric_store.go 73.33% <ø> (ø)
router/core/graph_server.go 85.35% <60.00%> (ø)
router/core/router.go 70.53% <90.00%> (ø)

... and 583 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
router-tests/telemetry/connection_metrics_hot_reload_test.go (1)

355-372: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Feature-flag configs alias the base config's subgraph messages.

Subgraphs: next.GetSubgraphs() hands the same []*Subgraph pointers to every feature-flag config and to the base graph. It is read-only in this test today, but any future mutation (e.g. per-flag routing URL overrides) would silently affect all muxes. Cloning per flag, as done for EngineConfig, keeps the fixtures independent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@router-tests/telemetry/connection_metrics_hot_reload_test.go` around lines
355 - 372, Update reloadConfigPoller.configWithFeatureFlags so each feature-flag
configuration receives an independently cloned Subgraphs slice and messages
instead of reusing next.GetSubgraphs(). Preserve the existing base configuration
and per-flag EngineConfig cloning, ensuring mutations to one flag’s subgraphs
cannot affect the base graph or other feature-flag configs.
router/core/graph_server.go (1)

272-277: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Re-seed max-connections on each graph server build router/core/graph_server.go:272-277

connectionMetricStore is cached for the router lifetime, so startInitMetrics only emits router.http.client.max_connections once. Reloads that add subgraphs or change max_conns_per_host update ConnectionPoolStats, but the gauge never gets re-emitted. Consider adding a small SeedMaxConnections helper on the shared store and calling it after each graph server builds its transports.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@router/core/graph_server.go` around lines 272 - 277, The cached connection
metric store does not re-emit max-connection gauges after graph server rebuilds.
Add a small SeedMaxConnections helper to the shared connection metric store that
refreshes gauges from current ConnectionPoolStats, then call it after
connectionMetricStore succeeds in the graph server build flow before assigning
s.connectionMetrics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@router-tests/telemetry/connection_metrics_hot_reload_test.go`:
- Around line 227-263: Update activeConnections and its call from
requireActiveConnections to use the EventuallyWithT callback’s *assert.CollectT
(or another assert.TestingT) for collection and type assertions instead of the
outer *testing.T, ensuring no require.FailNow operation runs on the background
goroutine.

---

Nitpick comments:
In `@router-tests/telemetry/connection_metrics_hot_reload_test.go`:
- Around line 355-372: Update reloadConfigPoller.configWithFeatureFlags so each
feature-flag configuration receives an independently cloned Subgraphs slice and
messages instead of reusing next.GetSubgraphs(). Preserve the existing base
configuration and per-flag EngineConfig cloning, ensuring mutations to one
flag’s subgraphs cannot affect the base graph or other feature-flag configs.

In `@router/core/graph_server.go`:
- Around line 272-277: The cached connection metric store does not re-emit
max-connection gauges after graph server rebuilds. Add a small
SeedMaxConnections helper to the shared connection metric store that refreshes
gauges from current ConnectionPoolStats, then call it after
connectionMetricStore succeeds in the graph server build flow before assigning
s.connectionMetrics.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 55d6bc38-7693-451b-a981-0695545fad79

📥 Commits

Reviewing files that changed from the base of the PR and between b9dd6b2 and 05e0019.

📒 Files selected for processing (7)
  • router-tests/telemetry/connection_metrics_hot_reload_test.go
  • router/core/graph_server.go
  • router/core/graph_server_test.go
  • router/core/router.go
  • router/pkg/metric/connection_pool_stats.go
  • router/pkg/metric/oltp_connection_metric_store.go
  • router/pkg/metric/prom_connection_metric_store.go

Comment thread router-tests/telemetry/connection_metrics_hot_reload_test.go
Comment thread router/core/router.go Outdated
Comment thread router/core/router.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@router/core/router.go`:
- Line 2654: Serialize initialization of connectionTraceDialer in newServer so
concurrent calls from buildExecutionConfigWatcher and buildManifestConfigWatcher
cannot race on the nil check. Guard the initialization with connectionStatsLock
or sync.Once, ensuring every reload path reuses the same dialer.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0117f5c1-8448-4f13-aed7-e3179618cc5c

📥 Commits

Reviewing files that changed from the base of the PR and between f00f610 and 84e33b8.

📒 Files selected for processing (2)
  • router/core/graph_server_test.go
  • router/core/router.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • router/core/graph_server_test.go

Comment thread router/core/router.go
Comment thread router/pkg/metric/oltp_connection_metric_store.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@router/pkg/metric/connection_metric_store.go`:
- Around line 81-94: Update ConnectionMetrics.RecordMaxConnections to merge
c.baseAttributes into the per-record attributes before constructing the metric
option, while retaining the optional subgraph attribute. Ensure both OTLP and
Prometheus MeasureMaxConnections calls receive the combined base and subgraph
attributes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e1efd1ff-1738-4b4f-8851-287a2ed7d7a5

📥 Commits

Reviewing files that changed from the base of the PR and between 84e33b8 and 494f02b.

📒 Files selected for processing (6)
  • router/core/graph_server.go
  • router/core/graph_server_test.go
  • router/core/router.go
  • router/pkg/metric/connection_metric_store.go
  • router/pkg/metric/oltp_connection_metric_store.go
  • router/pkg/metric/prom_connection_metric_store.go
💤 Files with no reviewable changes (2)
  • router/pkg/metric/prom_connection_metric_store.go
  • router/pkg/metric/oltp_connection_metric_store.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • router/core/router.go
  • router/core/graph_server_test.go
  • router/core/graph_server.go

Comment thread router/pkg/metric/connection_metric_store.go
Comment thread router/pkg/metric/connection_metric_store.go

@SkArchon SkArchon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm

@Noroth
Noroth merged commit e7d6208 into main Jul 31, 2026
36 checks passed
@Noroth
Noroth deleted the ludwig/router-560-router-reused-graph-muxes-dont-count-into-active_connections branch July 31, 2026 07:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants