Skip to content

Fix two dashboard charts that plotted the wrong data - #416

Open
dpage wants to merge 2 commits into
mainfrom
fix/issue-404-chart-data-defects
Open

Fix two dashboard charts that plotted the wrong data#416
dpage wants to merge 2 commits into
mainfrom
fix/issue-404-chart-data-defects

Conversation

@dpage

@dpage dpage commented Aug 12, 2026

Copy link
Copy Markdown
Member

Summary

Two unrelated chart defects, both of which made a chart show
something other than what its title claimed.

The comparative section of the cluster dashboard rendered a
"Connection Count" bar per server, but the series was built as
metrics.map(() => 1), so every bar was a hardcoded one. The
section already fetches /api/v1/metrics/performance-summary for
its other three bars, and that response had no connection count to
offer, so PerfConnectionResponse now carries an
active_connections figure, taken from the sum of numbackends
across the databases in the server's most recent
pg_stat_database snapshot, and the chart plots that value. No new
request is issued.

Both charts on the query drill-down page, "Execution Time Over
Time" and "Calls Over Time", queried the pg_stat_statements probe
without filtering to the selected query, because MetricFilters
had no way to express such a filter; the two series therefore
aggregated across every statement in the database whilst the page
presented them as belonging to one query. MetricFilters now
carries a QueryID, applied as queryid::text so that a 64-bit
identifier survives the round trip through JSON without losing
precision, and both the time-series and the latest-row paths of
GET /api/v1/metrics/query accept a queryid parameter that is
validated as a 64-bit integer before it reaches the query layer.
The query detail page passes the identifier of the selected query
to both charts.

The OpenAPI specification and the generated
docs/admin-guide/api/openapi.json are updated for the new
queryid parameter, and for index_name, which the time-series
endpoint has accepted for some time but never documented.

Test plan

  • New ComparativeChartsSection.test.tsx covers the connection
    count reaching the chart, the fallback to zero when the field is
    absent, and the loading, empty, and error states.

  • New QueryDetail.test.tsx asserts that both chart parameter sets
    carry the selected queryId, and covers the AI overview panel,
    the query text toggle, and the error paths.

  • useMetrics.test.ts gains cases for queryid appearing in, and
    being omitted from, the request URL.

  • Go: metricQueryBase, buildLatestRowsQuery and
    BuildDerivedMetricsQuery gain queryid placeholder and
    argument-binding tests; the metrics handler gains tests that the
    filter reaches the query layer and that a malformed queryid is
    rejected with 400 on both request paths.

  • New perf_summary_connection_count_test.go covers
    queryConnectionCount against a live Postgres (latest snapshot
    only, no data, missing table) and drives handlePerfSummary
    end-to-end, asserting active_connections per connection
    alongside the metrics it already reported.

  • Client coverage (make coverage, 173 files, 3527 tests passing):
    ComparativeChartsSection.tsx 100% lines, QueryDetail.tsx
    97.93% lines, useMetrics.ts 100% lines.

  • Go coverage for the touched functions: queryConnectionCount
    100%, parseQueryIDFilter 100%, metricQueryBase 100%,
    buildLatestRowsQuery 100%, and handlePerfSummary lifted from
    0% to 87.8%.

Closes #404

The comparative section of the cluster dashboard rendered a
"Connection Count" bar per server, but the series was built as
metrics.map(() => 1), so every bar was a hardcoded one and the chart
showed no real data at all. The section already fetches the
performance summary for its other three bars, and that response had
no connection count to offer, so the endpoint now reports an
active_connections figure per connection, taken from the sum of
numbackends across the databases in the server's most recent
pg_stat_database snapshot, and the chart plots that.

Both charts on the query drill-down page queried the
pg_stat_statements probe without filtering to the query the user had
selected, because MetricFilters had no way to express such a filter;
the series therefore aggregated across every statement in the
database whilst the page presented them as belonging to one query.
MetricFilters now carries a QueryID, applied as queryid::text so a
64-bit identifier survives the round trip through JSON, and both the
time-series and latest-row paths of GET /api/v1/metrics/query accept
a queryid parameter that is validated as a 64-bit integer before it
reaches the query layer. The query detail page passes the identifier
of the selected query to both charts.

Closes #404
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 34 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 72ddce94-d9a5-45c7-b051-a4a79971a7fb

📥 Commits

Reviewing files that changed from the base of the PR and between 19c645d and 162920d.

📒 Files selected for processing (16)
  • client/src/components/Dashboard/ClusterDashboard/ComparativeChartsSection.tsx
  • client/src/components/Dashboard/ClusterDashboard/__tests__/ComparativeChartsSection.test.tsx
  • client/src/components/Dashboard/ObjectDashboard/QueryDetail.tsx
  • client/src/components/Dashboard/ObjectDashboard/__tests__/QueryDetail.test.tsx
  • client/src/components/Dashboard/types.ts
  • client/src/hooks/__tests__/useMetrics.test.ts
  • client/src/hooks/useMetrics.ts
  • docs/admin-guide/api/openapi.json
  • docs/changelog.md
  • server/src/internal/api/metrics_handlers.go
  • server/src/internal/api/metrics_handlers_test.go
  • server/src/internal/api/openapi.go
  • server/src/internal/api/perf_summary_connection_count_test.go
  • server/src/internal/api/perf_summary_handlers.go
  • server/src/internal/metrics/query.go
  • server/src/internal/metrics/query_test.go

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

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 175 complexity · 42 duplication

Metric Results
Complexity 175
Duplication 42

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@dpage

dpage commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@dpage

dpage commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

dpage added a commit that referenced this pull request Aug 12, 2026
Every function whose rollback the sweep converted now clears the
project's 90% line-coverage floor, and every modified line but one is
executed by a test.

The three performance-summary endpoints and the query executor were the
gap: their handlers had no test at all, so the converted rollback lines
were never reached. The new handler tests follow the harness pattern
established in PR #416, wiring a real handler to the local Postgres over
a trimmed metrics schema and driving it through httptest. Distinct helper
and schema names keep the two test files independent, and no production
line #416 touches is modified here.

Coverage of the touched units, before and after:

  handlePerfSummary                0.0% -> 94.5%
  handleDatabaseSummaries          0.0% -> 90.0%
  handleTopQueries                 0.0% -> 95.9%
  executeQuery                    25.0% -> 91.7%
  UnacknowledgeAlert              81.0% -> 90.5%
  DeleteAutoDetectedCluster       76.0% -> 92.0%
  RemoveServerFromCluster          0.0% -> 95.2%
  Migrate (collector)             72.7% -> 90.9%

Reaching the last few branches needed realistic failure injection rather
than mocks: a query tracer that cancels the request context between
statements, schema drift such as a dropped column, a migration that
closes its own connection, and a monitored server on a dead port.

The one modified line that remains uncovered is the rollback inside
StoreMetrics in collector/src/probes/storage.go. Its guard tests an
outer err that the INSERT and Commit failure paths shadow with :=, so
the guard can never be true and the rollback is unreachable. That is a
pre-existing defect worth its own issue; this change deliberately does
not alter the behaviour.
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.

Cluster Connection Count chart is hardcoded, and QueryDetail charts ignore the selected query

1 participant