Skip to content

perf(stats): fold the dashboard's readings out of the statistics rollups - #281

Merged
henry40408 merged 1 commit into
mainfrom
perf/dashboard-rollups
Sep 13, 2026
Merged

henry40408 merged 1 commit into
mainfrom
perf/dashboard-rollups

Conversation

@henry40408

Copy link
Copy Markdown
Owner

Summary

Every dashboard tick scanned 30 days of idx_query_logs_ts_metrics for its summary, and the top domain, client and upstream lists scanned their own indexes over 24 hours. Under the default retention those windows are the whole table, so a tick cost an index's length every 10 seconds.

This moves those readings onto the rollups from #280.

  • Readers moved: summary_multi_since, timeline_since, traffic_lists_since, domain_stats_since and top_upstreams_since.
  • How they read: each takes every whole unit (quarter hour or hour) from a rollup, and reads query_logs only for the part of a unit its window starts inside, through idx_query_logs_timestamp, in one statement. Nothing is read at the far end: the rollups are written in the same transaction as the rows, so the unit still filling up is complete.
  • Summary windows: summary_multi_since tells its three windows apart by which arm a table row came from. A row belongs to the one window whose partial quarter it fills; the wider windows count that quarter through the rollup.
  • Fine-grained timeline: timeline_since keeps counting the table when its bucket is finer than a quarter hour, which only happens while the log is a few hours old.
  • Behaviour change: top upstreams now break ties by name, as the domain and client lists already did. Before this, ties came back in arbitrary order.
  • Also affects Statistics: traffic_lists_since is shared with the Statistics page, so its two lists move too. stats_scan_since and the /api/stats/* metrics statements are the next PR.

Page misses

All three benches on the same database copies and BENCH_NOW=1789212354, before (db67506) and after. Every reading that changed is listed; the rest are identical.

370 677 rows
  dashboard  summary                                              2157       28
  dashboard  top domains + clients                                 748      115
  dashboard  top upstreams                                         212       37
  dashboard  FIRST RESPONSE TOTAL                                 3117      180
  dashboard  timeline (tick only)                                  293       16
  dashboard  TICK TOTAL (compute_snapshot)                        3408      190
  logs       domain suggestions                                   3973      557
  logs       SUM OF ALL READINGS                                103445   100029
  stats      range_stats (all readings, charts, both lists)       7923     2704
  stats      top_domains alone (domain index)                     3973      540
  stats      both lists alone                                     5770      551
  stats      PAGE TOTAL (whole visit)                             7937     2718

1 482 708 rows
  dashboard  summary                                              9480       61
  dashboard  top domains + clients                                 752      116
  dashboard  top upstreams                                         212       38
  dashboard  FIRST RESPONSE TOTAL                                10444      215
  dashboard  timeline (tick only)                                  332       16
  dashboard  TICK TOTAL (compute_snapshot)                       10774      227
  logs       domain suggestions                                   6192      559
  logs       SUM OF ALL READINGS                                374596   368963
  stats      range_stats (all readings, charts, both lists)      31870    11628
  stats      top_domains alone (domain index)                    16084     2111
  stats      both lists alone                                    22394     2152
  stats      PAGE TOTAL (whole visit)                            31883    11641

No reading in any of the three benches got worse. idx_query_logs_ts_domain_client and idx_query_logs_ts_upstream now serve nothing; they are dropped in the index-consolidation PR, once the Statistics scan has moved too.

Tests

  • dashboard_readings_equal_a_recount_of_the_table (tests/stats_db_test.rs): three days of traffic starting 1 234 ms past an hour. Every reading is compared with the statement it replaced, run on the same rows, for windows starting before the data, on an hour, on a quarter, inside a quarter, inside an hour, and after the data. The timeline uses 60/600/1 800/3 600 s buckets, the lists use limits 5 and 1 000. On the old code, every comparison it reached matched until the top-upstream tie order, which the old statement left arbitrary.
  • the_dashboard_readings_fold_rollups_rather_than_the_table (tests/stats_page_miss_test.rs): replaces three tests tied to the old indexes (the_dashboard_summary_is_one_metrics_scan, the_top_upstreams_never_read_the_log_table, a_short_window_reads_a_short_stretch_of_the_traffic_lists). Each reading must cost under a tenth of a scan over every row. Before the implementation it failed with summary read 107 pages where a scan over every row reads 168.
  • Removed: the_traffic_lists_are_covered_by_their_index (src/db.rs), which asserted the plan of a statement that no longer exists.

Test plan

  • cargo fmt --check
  • cargo clippy --all-targets -- -D warnings
  • cargo nextest run: 681 passed, 8 skipped
  • cd e2e && cargo test --test specs: all spec cases passed
  • cd e2e && cargo test --test e2e: 17 scenarios (17 passed), 85 steps (85 passed)
  • All three page-miss benches before/after on both databases

🤖 Generated with Claude Code

Every dashboard tick scanned 30 days of idx_query_logs_ts_metrics for
its summary, and the top domain, client and upstream lists scanned their
own indexes over 24 hours. Under the default retention those windows are
the whole table, so the tick cost an index's length every 10 seconds.

summary_multi_since, timeline_since, traffic_lists_since,
domain_stats_since and top_upstreams_since now take every whole unit
from the rollups and only the part of a unit their window starts inside
from query_logs, in one statement. Nothing is read at the far end: the
rollups are written with the rows, so the current unit is complete.
timeline_since keeps counting the table when its bucket is finer than a
quarter hour, which only happens while the log is a few hours old. Top
upstreams now break ties by name, as the other lists do.

Page misses, same database copies and BENCH_NOW as the baseline:
- 370 677 rows: tick 3 408 -> 190, first response 3 117 -> 180,
  domain suggestions 3 973 -> 557, Statistics visit 7 937 -> 2 718
- 1 482 708 rows: tick 10 774 -> 227, first response 10 444 -> 215,
  domain suggestions 6 192 -> 559, Statistics visit 31 883 -> 11 641
No reading in any of the three benches got worse.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.38710% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.32%. Comparing base (db67506) to head (ab0981d).

Files with missing lines Patch % Lines
src/db.rs 98.38% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #281      +/-   ##
==========================================
+ Coverage   91.30%   91.32%   +0.02%     
==========================================
  Files          31       31              
  Lines       11587    11625      +38     
==========================================
+ Hits        10579    10617      +38     
  Misses       1008     1008              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 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.

@henry40408
henry40408 merged commit d801b9c into main Sep 13, 2026
7 checks passed
@henry40408
henry40408 deleted the perf/dashboard-rollups branch September 13, 2026 16:39
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.

1 participant