Skip to content

Commit ab84f78

Browse files
authored
Merge pull request #6785 from JSONbored/test/sync-grafana-dashboard-assertions-6779
test(selfhost): sync grafana dashboard assertions with #6779's gittensory_ fallback exprs
2 parents cf8bad4 + 3324a9d commit ab84f78

1 file changed

Lines changed: 25 additions & 25 deletions

File tree

test/unit/selfhost-grafana-dashboard.test.ts

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,14 @@ describe("Loopover Self-Host Grafana dashboard", () => {
9999
const dashboard = readDashboard(selfhostDashboardPath);
100100
const targets = dashboard.panels.flatMap((panel) => panel.targets ?? []);
101101

102-
expect(targets.some((target) => target.expr === "sum by (result) (rate(loopover_github_response_cache_total[5m]))")).toBe(true);
103-
expect(targets.some((target) => target.expr === "sum by (class, result) (loopover_github_response_cache_total)")).toBe(true);
102+
expect(targets.some((target) => target.expr === "sum by (result) ((rate(loopover_github_response_cache_total[5m]) or rate(gittensory_github_response_cache_total[5m])))")).toBe(true);
103+
expect(targets.some((target) => target.expr === "sum by (class, result) ((loopover_github_response_cache_total or gittensory_github_response_cache_total))")).toBe(true);
104104
expect(targets.some((target) => target.legendFormat === "{{class}} {{result}}")).toBe(true);
105-
expect(targets.some((target) => target.expr === "sum by (remaining_bucket, key_scope) (rate(loopover_github_rest_rate_limit_observations_total[5m])) or vector(0)")).toBe(true);
106-
expect(targets.some((target) => target.expr === "sum by (status, retry, key_scope) (rate(loopover_github_rest_rate_limit_responses_total[5m])) or vector(0)")).toBe(true);
107-
expect(targets.some((target) => target.expr === "sum by (kind, key_scope, job_type) (rate(loopover_jobs_rate_limit_admission_deferred_total[5m])) or vector(0)")).toBe(true);
108-
expect(targets.some((target) => target.expr === "sum by (kind, key_scope, job_type) (rate(loopover_jobs_rate_limit_budget_deferred_total[5m])) or vector(0)")).toBe(true);
109-
expect(targets.some((target) => target.expr === "sum by (kind, key_scope, job_type) (rate(loopover_jobs_rate_limited_by_type_total[5m])) or vector(0)")).toBe(true);
105+
expect(targets.some((target) => target.expr === "sum by (remaining_bucket, key_scope) ((rate(loopover_github_rest_rate_limit_observations_total[5m]) or rate(gittensory_github_rest_rate_limit_observations_total[5m]))) or vector(0)")).toBe(true);
106+
expect(targets.some((target) => target.expr === "sum by (status, retry, key_scope) ((rate(loopover_github_rest_rate_limit_responses_total[5m]) or rate(gittensory_github_rest_rate_limit_responses_total[5m]))) or vector(0)")).toBe(true);
107+
expect(targets.some((target) => target.expr === "sum by (kind, key_scope, job_type) ((rate(loopover_jobs_rate_limit_admission_deferred_total[5m]) or rate(gittensory_jobs_rate_limit_admission_deferred_total[5m]))) or vector(0)")).toBe(true);
108+
expect(targets.some((target) => target.expr === "sum by (kind, key_scope, job_type) ((rate(loopover_jobs_rate_limit_budget_deferred_total[5m]) or rate(gittensory_jobs_rate_limit_budget_deferred_total[5m]))) or vector(0)")).toBe(true);
109+
expect(targets.some((target) => target.expr === "sum by (kind, key_scope, job_type) ((rate(loopover_jobs_rate_limited_by_type_total[5m]) or rate(gittensory_jobs_rate_limited_by_type_total[5m]))) or vector(0)")).toBe(true);
110110
// The AI request/fallback + cost/token panels moved to the consolidated grafana/dashboards/ai-usage.json
111111
// (Phase B2, 2026-07) — see test/unit/selfhost-grafana-ai-usage-dashboard.test.ts for their coverage there.
112112
});
@@ -128,9 +128,9 @@ describe("Loopover Self-Host Grafana dashboard", () => {
128128
const dashboard = readDashboard(selfhostDashboardPath);
129129
const targets = dashboard.panels.flatMap((panel) => panel.targets ?? []);
130130

131-
expect(targets.some((target) => target.expr === "loopover_orb_events_exported_total or vector(0)")).toBe(true);
132-
expect(targets.some((target) => target.expr === "loopover_orb_export_errors_total or vector(0)")).toBe(true);
133-
expect(targets.some((target) => target.expr === "sum by (result) (rate(loopover_orb_webhook_total[5m])) or vector(0)")).toBe(true);
131+
expect(targets.some((target) => target.expr === "(loopover_orb_events_exported_total or gittensory_orb_events_exported_total) or vector(0)")).toBe(true);
132+
expect(targets.some((target) => target.expr === "(loopover_orb_export_errors_total or gittensory_orb_export_errors_total) or vector(0)")).toBe(true);
133+
expect(targets.some((target) => target.expr === "sum by (result) ((rate(loopover_orb_webhook_total[5m]) or rate(gittensory_orb_webhook_total[5m]))) or vector(0)")).toBe(true);
134134
});
135135

136136
it("no longer references loopover_orb_events_recorded_total / loopover_orb_installs_total, retired with the per-instance Orb App in #1256 but never cleaned out of the dashboard (2026-07 fix)", () => {
@@ -188,7 +188,7 @@ describe("Loopover Self-Host Grafana dashboard", () => {
188188
expect(targets.some((target) => target.expr === 'topk(10, pg_stat_user_tables_n_live_tup{datname="loopover"}) or vector(0)')).toBe(true);
189189
expect(targets.some((target) => target.expr === 'topk(10, pg_stat_user_tables_n_dead_tup{datname="loopover"}) or vector(0)')).toBe(true);
190190
expect(targets.some((target) => target.expr === 'sum by (relname) (increase(pg_stat_user_tables_autovacuum_count{datname="loopover"}[1h])) or vector(0)')).toBe(true);
191-
expect(targets.some((target) => target.expr === 'loopover_backup_files{target=~"postgres|sqlite|qdrant"} or vector(0)')).toBe(true);
191+
expect(targets.some((target) => target.expr === '(loopover_backup_files or gittensory_backup_files){target=~"postgres|sqlite|qdrant"} or vector(0)')).toBe(true);
192192
});
193193

194194
it("ships Postgres and backup alerts for the same dashboarded failure modes", () => {
@@ -224,8 +224,8 @@ describe("Loopover Self-Host Grafana dashboard", () => {
224224
"Maintenance Admission Deferrals (total)",
225225
]),
226226
);
227-
expect(targets.some((target) => target.expr === "sum by (reason, job_type) (rate(loopover_jobs_maintenance_admission_deferred_by_reason_total[5m])) or vector(0)")).toBe(true);
228-
expect(targets.some((target) => target.expr === "sum(rate(loopover_jobs_maintenance_admission_deferred_total[5m])) or vector(0)")).toBe(true);
227+
expect(targets.some((target) => target.expr === "sum by (reason, job_type) ((rate(loopover_jobs_maintenance_admission_deferred_by_reason_total[5m]) or rate(gittensory_jobs_maintenance_admission_deferred_by_reason_total[5m]))) or vector(0)")).toBe(true);
228+
expect(targets.some((target) => target.expr === "sum((rate(loopover_jobs_maintenance_admission_deferred_total[5m]) or rate(gittensory_jobs_maintenance_admission_deferred_total[5m]))) or vector(0)")).toBe(true);
229229
});
230230

231231
it("surfaces self-host runtime-drift signal panels, every counter query fleet-aggregated", () => {
@@ -247,21 +247,21 @@ describe("Loopover Self-Host Grafana dashboard", () => {
247247
);
248248
// Every stat-panel counter is sum()-wrapped, matching its siblings -- a multi-instance self-host scrape
249249
// must render one fleet-level value per stat, not one value per target (gate finding, #chore-runtime-drift).
250-
expect(targets.some((target) => target.expr === "sum(loopover_jobs_maintenance_trickle_admitted_persisted_total) or vector(0)")).toBe(true);
251-
expect(targets.some((target) => target.expr === 'sum(loopover_orb_relay_register_total{result="failed"}) or vector(0)')).toBe(true);
252-
expect(targets.some((target) => target.expr === 'sum(loopover_installation_health_broker_probe_total{result="failed"}) or vector(0)')).toBe(true);
250+
expect(targets.some((target) => target.expr === "sum((loopover_jobs_maintenance_trickle_admitted_persisted_total or gittensory_jobs_maintenance_trickle_admitted_persisted_total)) or vector(0)")).toBe(true);
251+
expect(targets.some((target) => target.expr === 'sum((loopover_orb_relay_register_total or gittensory_orb_relay_register_total){result="failed"}) or vector(0)')).toBe(true);
252+
expect(targets.some((target) => target.expr === 'sum((loopover_installation_health_broker_probe_total or gittensory_installation_health_broker_probe_total){result="failed"}) or vector(0)')).toBe(true);
253253
expect(targets.some((target) => target.expr === "sum(loopover_agent_action_permission_denied_total) or vector(0)")).toBe(true);
254254
// Grouped (sum-by) queries must NOT have "or vector(0)": Prometheus's `or` unions result sets, and
255255
// vector(0) is a single unlabeled series that can't match the actionClass/mode,result label set --
256256
// that renders a bogus extra unlabeled zero-series alongside the real labeled series (gate finding).
257257
expect(targets.some((target) => target.expr === "sum by (actionClass) (rate(loopover_agent_action_permission_denied_total[5m]))")).toBe(true);
258258
expect(targets.some((target) => target.expr === "sum by (actionClass) (rate(loopover_agent_action_permission_denied_suppressed_total[5m]))")).toBe(true);
259-
expect(targets.some((target) => target.expr === "sum by (mode, result) (rate(loopover_orb_relay_register_total[5m]))")).toBe(true);
259+
expect(targets.some((target) => target.expr === "sum by (mode, result) ((rate(loopover_orb_relay_register_total[5m]) or rate(gittensory_orb_relay_register_total[5m])))")).toBe(true);
260260
// #selfhost-runtime-drift follow-up: the streak-vs-drain-progress panel is the dashboard-visible
261261
// counterpart to isOrbRelayRegistrationAlerting's gate -- a lone registration timeout must not read as
262262
// a dashboard error on its own as long as the drain loop is still making progress.
263-
expect(targets.some((target) => target.expr === "loopover_orb_relay_register_consecutive_failures or vector(0)")).toBe(true);
264-
expect(targets.some((target) => target.expr === "loopover_orb_relay_drain_seconds_since_last or vector(0)")).toBe(true);
263+
expect(targets.some((target) => target.expr === "(loopover_orb_relay_register_consecutive_failures or gittensory_orb_relay_register_consecutive_failures) or vector(0)")).toBe(true);
264+
expect(targets.some((target) => target.expr === "(loopover_orb_relay_drain_seconds_since_last or gittensory_orb_relay_drain_seconds_since_last) or vector(0)")).toBe(true);
265265

266266
const alerts = readFileSync(selfhostAlertsPath, "utf8");
267267
expect(alerts).toContain("alert: LoopoverOrbRelayRegistrationStuck");
@@ -283,12 +283,12 @@ describe("Loopover Self-Host Grafana dashboard", () => {
283283
"Top Repos by Backlog Depth",
284284
]),
285285
);
286-
expect(targets.some((target) => target.expr === "loopover_queue_backlog_convergence_pending")).toBe(true);
287-
expect(targets.some((target) => target.expr === "loopover_queue_fresh_intake_pending")).toBe(true);
288-
expect(targets.some((target) => target.expr === "loopover_github_rest_rate_limit_remaining")).toBe(true);
289-
expect(targets.some((target) => target.legendFormat === "{{key_scope}}" && target.expr === "loopover_github_rest_rate_limit_remaining")).toBe(true);
290-
expect(targets.some((target) => target.expr === "sum by (lane) (rate(loopover_jobs_claimed_by_lane_total[5m])) or vector(0)")).toBe(true);
291-
expect(targets.some((target) => target.expr === "loopover_queue_backlog_by_repo" && target.format === "table" && target.instant === true)).toBe(true);
286+
expect(targets.some((target) => target.expr === "(loopover_queue_backlog_convergence_pending or gittensory_queue_backlog_convergence_pending)")).toBe(true);
287+
expect(targets.some((target) => target.expr === "(loopover_queue_fresh_intake_pending or gittensory_queue_fresh_intake_pending)")).toBe(true);
288+
expect(targets.some((target) => target.expr === "(loopover_github_rest_rate_limit_remaining or gittensory_github_rest_rate_limit_remaining)")).toBe(true);
289+
expect(targets.some((target) => target.legendFormat === "{{key_scope}}" && target.expr === "(loopover_github_rest_rate_limit_remaining or gittensory_github_rest_rate_limit_remaining)")).toBe(true);
290+
expect(targets.some((target) => target.expr === "sum by (lane) ((rate(loopover_jobs_claimed_by_lane_total[5m]) or rate(gittensory_jobs_claimed_by_lane_total[5m]))) or vector(0)")).toBe(true);
291+
expect(targets.some((target) => target.expr === "(loopover_queue_backlog_by_repo or gittensory_queue_backlog_by_repo)" && target.format === "table" && target.instant === true)).toBe(true);
292292
});
293293
});
294294

0 commit comments

Comments
 (0)