fix: remove max without(prometheus_replica) from histogram_quantile (AROSLSRE-1746) - #6455
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes incorrect PromQL aggregation for histogram quantiles by removing max without(prometheus_replica) before histogram_quantile, preventing broken histogram monotonicity and false-positive latency signals in HA Prometheus setups.
Changes:
- Update the Frontend control plane latency dashboard P50/P95/P99 panels to use
sum by (le, ...) (rate(..._bucket))directly underhistogram_quantile. - Update the
FrontendPathLatencyPrometheusRule alert to use the same correct histogram aggregation pattern and document the rationale (AROSLSRE-1746).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| observability/grafana-dashboards/frontend/frontend-control-plane-latency.json | Removes HA replica max without(...) from histogram_quantile queries for dashboard latency quantiles. |
| frontend/alerts/frontend-path-latency-prometheusRule.yaml | Removes max without(prometheus_replica) from the alert’s histogram quantile expression and adds explanatory comments about the HA/monotonicity issue. |
| "datasource": { "type": "prometheus", "uid": "${datasource}" }, | ||
| "editorMode": "code", | ||
| "expr": "histogram_quantile(\n 0.99,\n sum by (le, route, method) (\n max without (prometheus_replica) (\n rate(frontend_http_requests_duration_seconds_bucket{cluster=\"$cluster\",route!=\"/subscriptions/{subscriptionid}/providers/microsoft.redhatopenshift/locations/{location}/hcpoperationresults/{operationid}\"}[$__rate_interval])\n )\n )\n)", | ||
| "expr": "histogram_quantile(\n 0.99,\n sum by (le, route, method) (\n rate(frontend_http_requests_duration_seconds_bucket{cluster=\"$cluster\",route!=\"/subscriptions/{subscriptionid}/providers/microsoft.redhatopenshift/locations/{location}/hcpoperationresults/{operationid}\"}[$__rate_interval])\n )\n)", |
| # HA Prometheus replicas are handled by sum (not max): histogram_quantile works on | ||
| # ratios between buckets, so doubled counts from two replicas cancel out. Using max | ||
| # per-bucket broke cumulative monotonicity and caused false positives (AROSLSRE-1746). |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
Suppressed comments (2)
frontend/alerts/frontend-path-latency-prometheusRule.yaml:23
- PR standards require before/after screenshots for changes that affect dashboards, alerting rules, or other metrics/visualizations. This PR updates both a Grafana dashboard and Prometheus alerting expressions, so please add annotated before/after screenshots to the PR description.
# HA Prometheus replicas are handled by sum (not max): histogram_quantile works on
# ratios between buckets, so doubled counts from two replicas cancel out. Using max
# per-bucket broke cumulative monotonicity and caused false positives (AROSLSRE-1746).
observability/grafana-dashboards/frontend/frontend-control-plane-latency.json:90
- This dashboard still has a histogram-bucket ratio panel ("Share of requests ≤ 1s by method + route") that dedups each bucket with
max without(prometheus_replica)(see expression around line ~291). That has the same non-atomic-per-bucket problem described in the PR (it can select different replicas forle="1"vsle="+Inf", producing incorrect ratios, potentially >1). Consider switching that panel to the samesum by (...) (rate(...))pattern so HA replica duplication cancels out in the ratio, rather than per-bucketmaxdedup.
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"editorMode": "code",
"expr": "histogram_quantile(\n 0.99,\n sum by (le, route, method) (\n rate(frontend_http_requests_duration_seconds_bucket{cluster=\"$cluster\",route!=\"/subscriptions/{subscriptionid}/providers/microsoft.redhatopenshift/locations/{location}/hcpoperationresults/{operationid}\"}[$__rate_interval])\n )\n)",
"legendFormat": "{{method}} {{route}}",
"refId": "A"
…xpressions (AROSLSRE-1746) Remove max without(prometheus_replica) from histogram_quantile expressions in the FrontendPathLatency alert and the control plane latency dashboard. Per Prometheus docs, sum by (le, ...) is the correct aggregation for histogram buckets — histogram_quantile works on ratios between buckets, so doubled counts from HA replicas cancel out. Using max per-bucket picked from different replicas independently, breaking cumulative histogram monotonicity. With sparse CI traffic (1-2 requests per 5m window), this caused histogram_quantile to interpolate into empty high-latency buckets, producing false positives (e.g. P99=12.083s when actual max was 26ms). The FrontendLatency alert (1h window, info severity) already uses sum without max and is unaffected. Non-histogram panels (request rate, SLO fraction) correctly retain max without for dedup.
Run `make alerts` from observability/ to regenerate the bicep file that deploys the FrontendPathLatency alert rule to Azure Monitor.
The root cause (max without(prometheus_replica) breaking histogram monotonicity) is fixed in this PR, so the known issues suppression added in Azure#6449 is no longer needed.
23d3204 to
66e057e
Compare
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: inbharajmani The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (2)
observability/grafana-dashboards/frontend/frontend-control-plane-latency.json:88
- This PR changes a Grafana dashboard and an alerting rule expression.
CONTRIBUTING.mdrequires before/after screenshots for any dashboard/graph/metrics/alerting-rule change (CONTRIBUTING.md:95-98). Please add the required screenshots to the PR description so reviewers can validate the visual/behavioral impact.
"expr": "histogram_quantile(\n 0.99,\n sum by (le, route, method) (\n rate(frontend_http_requests_duration_seconds_bucket{cluster=\"$cluster\",route!=\"/subscriptions/{subscriptionid}/providers/microsoft.redhatopenshift/locations/{location}/hcpoperationresults/{operationid}\"}[$__rate_interval])\n )\n)",
frontend/alerts/frontend-path-latency-prometheusRule.yaml:28
gather-observability/queries.yamlstill defines “Frontend Request Latency” ashistogram_quantile(... sum by (...) (max without(prometheus_replica) (rate(..._bucket...))))and its description says it “matches FrontendPathLatency”. With this PR changing the alert (and dashboard) to remove the per-bucketmax without, that gather query is now out of sync and can still reproduce the same non-monotonic histogram issue during CI triage. Please update the gather query to use the samesum by (le, ...) (rate(...))shape as the alert.
# HA Prometheus replicas are handled by sum (not max): histogram_quantile works on
# ratios between buckets, so doubled counts from two replicas cancel out. Using max
# per-bucket broke cumulative monotonicity and caused false positives (AROSLSRE-1746).
- alert: FrontendPathLatency
expr: |
histogram_quantile(0.99,
sum by (le, route, method, cluster) (
rate(frontend_http_requests_duration_seconds_bucket{route!="/subscriptions/{subscriptionid}/providers/microsoft.redhatopenshift/locations/{location}/hcpoperationresults/{operationid}"}[5m])
Summary
max without(prometheus_replica)fromhistogram_quantileexpressions in theFrontendPathLatencyalert and the control plane latency dashboard.sum by (le, ...)is the correct aggregation for histogram buckets —histogram_quantileworks on ratios between buckets, so doubled counts from HA replicas cancel out.FrontendPathLatencyfrom known issues (added in fix: add FrontendPathLatency to known issues (AROSLSRE-1746) #6449) since the root cause is fixed in this PR.FrontendLatencyalert (1h window, info severity) already usessumwithoutmaxand is unaffected.max withoutfor dedup.Root Cause
Using
max without(prometheus_replica)per-bucket picks from different HA replicas independently, breaking cumulative histogram monotonicity. With sparse CI traffic (1–2 requests per 5m window),histogram_quantileinterpolated into empty high-latency buckets — reporting P99 = 12.083s when the actual max request was 26ms (a 466x overestimate).This is the same class of problem documented in prometheus/prometheus#2610 and prometheus/prometheus#13671: non-atomic data fed into
histogram_quantilebreaks the monotonicity invariant that the algorithm depends on.The Prometheus docs explicitly warn about this:
The source of the invalid data was
max without(prometheus_replica). This PR removes it.Why
sumis correctThe Prometheus docs say: "To aggregate, use the
sum()aggregator around therate()function." — no mention ofmaxfor histogram buckets anywhere.sum by (le, route, method, cluster)sums across all other labels includingprometheus_replica. The doubled counts from 2 replicas don't affect the quantile becausehistogram_quantiledivides buckets by each other — the 2x factor cancels:Evidence
Failing E2E run: pull-ci-Azure-ARO-HCP-main-e2e-parallel/2085205020218757120
Kusto proof — alert fired with expressionValue=12.083:
Kusto proof — all 9,475 requests across the entire E2E run, none exceeded 1s:
Result: 9,475 requests, max 791ms, 0 exceeded 1 second.
Tracked in AROSLSRE-1746.
Test plan
FrontendPathLatencyalert rule test passes (promtool via CI)FrontendLatencyalert (1h window) is unchanged and already uses the samesumpatternmax withoutfor correct dedupFrontendPathLatencyis removed from known issues (no longer needed with root cause fixed)