-
Notifications
You must be signed in to change notification settings - Fork 0
test: add runnable PromQL differential compliance suite #742
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
milindsrivastava1997
wants to merge
31
commits into
main
Choose a base branch
from
732-test-add-prometheus-remote-write-promql-differential-suite
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
df65437
test: establish PromQL compliance runner contracts
milindsrivastava1997 2a4f7cf
test: encode PromQL compliance fixtures as remote write
milindsrivastava1997 694b366
test: send shared remote write bodies to differential targets
milindsrivastava1997 b03ba67
test: query Prometheus-compatible differential targets
milindsrivastava1997 4c4730b
test: compare Prometheus API responses
milindsrivastava1997 8a80905
test: add executable differential runner
milindsrivastava1997 248515d
test: drain backend and compare query ranges
milindsrivastava1997 73d3f7e
test: add PromQL compliance service topology
milindsrivastava1997 d9293a8
test: add semantic PromQL response comparison
milindsrivastava1997 001ab57
test: write PromQL differential JSON reports
milindsrivastava1997 a60c19a
test: port PromQL compliance corpora
milindsrivastava1997 8262039
test: derive backend-local plans from PromQL suites
milindsrivastava1997 2ac9263
test: orchestrate PromQL Compose lifecycle
milindsrivastava1997 1bdb403
test: add runnable PromQL compliance workflow
milindsrivastava1997 7748a10
fix: resolve Compose contexts from primary checkout
milindsrivastava1997 db234de
build: resolve private dependencies from local contexts
milindsrivastava1997 af124d5
test: start backend from suite planning snapshots
milindsrivastava1997 f63b018
test: allow backend-local plans without fallback
milindsrivastava1997 d89f822
test: report PromQL runner progress
milindsrivastava1997 0c9369b
test: quote PromQL planning snapshots before startup
milindsrivastava1997 2d7536b
fix: create planning snapshot bind target
milindsrivastava1997 2877119
fix: reset Compose state between compliance cases
milindsrivastava1997 d7197ee
fix: retain compliance logs on runner failure
milindsrivastava1997 10e4ed4
test: enable Prometheus fallback for compliance queries
milindsrivastava1997 4ff0058
test: include raw query responses in reports
milindsrivastava1997 9e7a8e1
test: record backend query provenance in reports
milindsrivastava1997 8615db1
test: add PromQL compliance report card
milindsrivastava1997 1d1c9be
test: label Prometheus fallback responses explicitly
milindsrivastava1997 e390e8b
test: require ASAPQuery-served differential results
milindsrivastava1997 d98d99e
docs: explain PromQL compliance workflows
milindsrivastava1997 1501e44
fix: make PromQL compliance artifacts reliable
milindsrivastava1997 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| name: PromQL compliance | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| differential: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 90 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| path: ASAPQuery-backend | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| repository: ProjectASAP/ASAPCollector | ||
| path: ASAPCollector | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| repository: ProjectASAP/asap_sketchlib | ||
| path: asap_sketchlib | ||
| - uses: actions/setup-go@v5 | ||
| with: | ||
| go-version: "1.25.8" | ||
| - name: Run every differential corpus | ||
| working-directory: ASAPQuery-backend/promql-compliance/runner | ||
| run: make run-all REPORT_DIR="$GITHUB_WORKSPACE/artifacts/reports" LOGS_DIR="$GITHUB_WORKSPACE/artifacts/logs" | ||
| - name: Upload reports and service logs | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: promql-compliance-evidence | ||
| path: artifacts | ||
| if-no-files-found: warn |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| //! Complete a backend-local planning snapshot with deterministic unit-cost | ||
| //! quotes for the PromQL compliance harness. Candidate identities and demand | ||
| //! still come from the production planner and physical compiler. | ||
|
|
||
| use control_plane::physical::{ | ||
| compiler::{ | ||
| BackendLocalPlanningInput, PhysicalPlanCompiler, BACKEND_REVISION, PLANNER_REVISION, | ||
| }, | ||
| workload_cost::{ | ||
| enumerate_exact_and_materialized_candidates, manifest, WorkloadCostEvidence, WorkloadQuote, | ||
| }, | ||
| }; | ||
| use std::{collections::BTreeMap, path::Path}; | ||
|
|
||
| fn quote_snapshot( | ||
| mut snapshot: BackendLocalPlanningInput, | ||
| ) -> Result<BackendLocalPlanningInput, String> { | ||
| if snapshot.workload_cost_evidence.is_some() { | ||
| return Err("planning snapshot already contains workload_cost_evidence".into()); | ||
| } | ||
| let observed_at_unix_ms = snapshot.environment.observed_at_unix_ms; | ||
| let valid_for_ms = snapshot.environment.max_evidence_age_ms; | ||
| let (request, environment) = snapshot | ||
| .clone() | ||
| .into_physical_compilation_request() | ||
| .map_err(|error| error.to_string())?; | ||
| let quotes = enumerate_exact_and_materialized_candidates(request) | ||
| .map_err(|error| error.to_string())? | ||
| .into_iter() | ||
| .filter_map(|candidate| { | ||
| let plan = PhysicalPlanCompiler | ||
| .compile_promql(candidate.clone(), environment.clone()) | ||
| .ok()?; | ||
| let manifest = manifest(&plan, &candidate.queries).ok()?; | ||
| Some(WorkloadQuote { | ||
| unit_costs: manifest | ||
| .components | ||
| .keys() | ||
| .map(|key| (key.clone(), 1.0)) | ||
| .collect::<BTreeMap<_, _>>(), | ||
| manifest, | ||
| executable: true, | ||
| }) | ||
| }) | ||
| .collect(); | ||
| snapshot.workload_cost_evidence = Some(WorkloadCostEvidence { | ||
| backend_revision: BACKEND_REVISION.into(), | ||
| planner_revision: PLANNER_REVISION.into(), | ||
| data_snapshot_id: "promql-compliance".into(), | ||
| model_version: "promql-compliance-unit-costs".into(), | ||
| observed_at_unix_ms, | ||
| valid_for_ms, | ||
| quotes, | ||
| }); | ||
| Ok(snapshot) | ||
| } | ||
|
|
||
| fn main() -> Result<(), String> { | ||
| let mut args = std::env::args_os().skip(1); | ||
| let input = args | ||
| .next() | ||
| .ok_or("usage: control_plane_quote_snapshot INPUT OUTPUT")?; | ||
| let output = args | ||
| .next() | ||
| .ok_or("usage: control_plane_quote_snapshot INPUT OUTPUT")?; | ||
| if args.next().is_some() { | ||
| return Err("usage: control_plane_quote_snapshot INPUT OUTPUT".into()); | ||
| } | ||
| let snapshot = std::fs::read(&input) | ||
| .map_err(|error| format!("read {}: {error}", Path::new(&input).display()))?; | ||
| let snapshot = | ||
| serde_json::from_slice(&snapshot).map_err(|error| format!("decode snapshot: {error}"))?; | ||
| let quoted = quote_snapshot(snapshot)?; | ||
| std::fs::write( | ||
| &output, | ||
| serde_json::to_vec_pretty("ed).map_err(|error| error.to_string())?, | ||
| ) | ||
| .map_err(|error| format!("write {}: {error}", Path::new(&output).display()))?; | ||
| Ok(()) | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| #[test] | ||
| fn adds_complete_candidate_quotes_to_a_snapshot() { | ||
| let fixture = | ||
| include_str!("../../../docs/examples/asapquery-compatibility-demo-snapshot.json"); | ||
| let mut snapshot: BackendLocalPlanningInput = serde_json::from_str(fixture).unwrap(); | ||
| snapshot.workload_cost_evidence = None; | ||
| let quoted = quote_snapshot(snapshot).unwrap(); | ||
| assert!(!quoted.workload_cost_evidence.unwrap().quotes.is_empty()); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| # PromQL compliance design Q&A | ||
|
|
||
| > **Question:** should v1 be a strict differential suite for a deliberately supported, locally answered subset of PromQL—with unsupported queries required to fail—or should it allow Prometheus fallback? | ||
| > | ||
| > **Recommendation:** require local answers and reject fallback in v1. Otherwise Prometheus can answer on the backend’s behalf, yielding a green comparison that proves neither backend ingestion nor backend query semantics. | ||
|
|
||
| **Answer:** unsupported queries required to fail, yes | ||
|
|
||
| > **Question:** should the suite compare approximate sketch-backed values to Prometheus within an explicit per-query tolerance, or start with only result shapes/data sizes where equality is exact? | ||
| > | ||
| > **Recommendation:** support explicit per-query tolerances from day one, defaulting to exact equality. The backend is designed to return approximate sketch results, so pretending all valid local answers are exact would either constrain the suite to an unrepresentative corpus or create noisy failures. | ||
|
|
||
| **Answer:** yes | ||
|
|
||
| > **Question:** should v1 use a finite, timestamp-pinned fixture and explicitly call the backend’s `/api/v1/precompute/drain` before querying? | ||
| > | ||
| > **Recommendation:** yes. It makes ingestion completion deterministic and avoids flaky “did the asynchronous precompute path catch up?” failures. Live-scrape/streaming behavior should be a separate suite later, because `drain` deliberately closes the backend’s Remote Write input. | ||
|
|
||
| **Answer:** yes | ||
|
|
||
| > **Question:** before the backend can accept Remote Write, it needs a configuration called a PhysicalPlan that says what metrics/queries it should accelerate. Should this new test suite: (1) give the backend a small, fixed test configuration; or (2) start the planner/control plane too and have it create that configuration? | ||
| > | ||
| > **Recommendation:** option 1 for this issue. It keeps failures clear: if the test fails, it is likely ingestion or query behavior in the backend, not plan generation. | ||
|
|
||
| **Answer:** i wanna do option 2 actually. we can add option 1 later | ||
|
|
||
| > **Question:** should “planner/control plane” mean the backend repository’s `control_plane` binary and its normal plan-publication protocol, rather than importing ASAPQuery’s older `asap-planner-rs` service? | ||
| > | ||
| > **Recommendation:** use the backend’s own `control_plane`. It tests the deployment users of `ASAPQuery-backend` actually run and avoids coupling this repository’s suite to a separate repository’s planner implementation. | ||
|
|
||
| **Answer:** yes | ||
|
|
||
| > **Question:** should we port the existing Go-based seeder/comparator and Docker Compose runner essentially intact, adapting only the backend service wiring, or rewrite it as Rust process tests? | ||
| > | ||
| > **Recommendation:** port the Go tooling and Compose workflow. It already provides deterministic Remote Write encoding, structured result comparison, fixtures, tolerances, reports, and lifecycle handling; a rewrite would add risk without improving the test’s signal. | ||
|
|
||
| **Answer:** yes | ||
|
|
||
| > **Question:** what should be the first required green corpus? | ||
| > | ||
| > **Recommendation:** begin with one small fixture and suite covering a selector, `rate`, `increase`, one aggregation, and both instant/range evaluations—plus one intentionally unsupported query that must fail locally. Add sparse/staleness, counter resets, and larger aggregation matrices after this vertical slice is stable. | ||
|
|
||
| **Answer:** Let's just add all corpora. I think we may not get any green righ tnow | ||
|
|
||
| > **Question:** when those corpora find differences, should the runner exit non-zero from day one? | ||
| > | ||
| > **Recommendation:** yes—never encode known failures as passes. Keep the full workflow manual/non-required initially, preserve its JSON reports as evidence, and only make a stable subset required in PR CI after the gaps are fixed. | ||
|
|
||
| **Answer:** yes | ||
|
|
||
| > **Question:** should every successful backend response be required to carry and pass a local-execution provenance check (for example, its existing ASAPQuery data-source marker), in addition to disabling fallback? | ||
| > | ||
| > **Recommendation:** yes. Disabling fallback catches most masking, but provenance makes the test’s claim explicit and will catch accidental routing changes that still return a successful response. | ||
|
|
||
| **Answer:** no, it's fine. just disable fallback | ||
|
|
||
| > **Question:** should the runner wait until the control plane has published and the backend reports an active Remote Write-ready plan before it sends any fixture data? | ||
| > | ||
| > **Recommendation:** yes. Then seed both targets, call the backend’s finite-input `drain`, and only then execute the fixed-time queries. This makes plan activation and ingestion completion explicit rather than timing-dependent. | ||
|
|
||
| **Answer:** yes | ||
|
|
||
| > **Question:** should the runner derive the control-plane workload/configuration from the same query-suite YAML it executes, rather than maintain a second hand-written plan configuration per corpus? | ||
| > | ||
| > **Recommendation:** yes. One source of truth prevents a test from querying expressions that the control plane was never asked to plan, and it makes adding a corpus a fixture-only change. | ||
|
|
||
| **Answer:** yes | ||
|
|
||
| > **Question:** on failure, should the runner retain the JSON report and collect service logs, while still tearing down containers by default? | ||
| > | ||
| > **Recommendation:** yes. CI should upload the report and logs as artifacts; local runs should offer `--keep-services` for interactive debugging. Default cleanup prevents stale volumes/ports from contaminating the next run. | ||
|
|
||
| **Answer:** yes | ||
|
|
||
| > **Question:** should `ASAPQuery-backend` own a copied/adapted version of the harness and fixtures, rather than invoke `ASAPQuery/promql-compliance` across repositories? | ||
| > | ||
| > **Recommendation:** own it in the backend repository. The backend needs different service wiring—its `control_plane`, PhysicalPlan lifecycle, and one HTTP listener—and an external cross-repo dependency would make local and CI runs less reproducible. | ||
|
|
||
| **Answer:** yes |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overwrites
.cargo/config.tomland patches all builds (medium). (Same block incontrol_plane/Dockerfile.)>replaces the checked-in config, dropping[net] git-fetch-with-cli = true. And since this applies to every image built from these Dockerfiles, not just the compliance suite,asap-precompute-rs/asap_sketchlibnow compile from whatever sibling working trees are passed as build contexts rather than the revisions pinned inCargo.lock, so production images can pick up uncommitted/unpinned code. Suggest appending (>>) and gating the patch behind a build arg used only by the compliance build.