Skip to content

test: add runnable PromQL differential compliance suite - #742

Draft
milindsrivastava1997 wants to merge 29 commits into
mainfrom
732-test-add-prometheus-remote-write-promql-differential-suite
Draft

milindsrivastava1997 wants to merge 29 commits into
mainfrom
732-test-add-prometheus-remote-write-promql-differential-suite

Conversation

@milindsrivastava1997

Copy link
Copy Markdown
Contributor

Why

Provide a repeatable way to compare ASAPQuery-backend with Prometheus across representative PromQL workloads before changing query execution.

What

  • Adds Remote Write fixture ingestion, semantic response comparison, range/instant parity checks, and JSON reports.
  • Ports temporal and aggregation corpora and provides make run and make run-all workflows.
  • Starts Prometheus and the backend through Compose, retains logs, cleans up per case, and writes a report card plus detailed raw responses.
  • Derives backend-local planning snapshots from each suite and uses control-plane code to create complete candidate cost evidence.

Before this PR

There was no runnable end-to-end PromQL differential suite. A developer had no single command to ingest identical fixtures, start a backend-local plan, compare outputs, or inspect the serving path.

After this PR

make run-all starts a clean case, derives its plan, writes identical samples to both systems, compares every configured query, then writes summary.md, summary.json, per-case raw responses, and retained Compose logs under /tmp.

Design decisions discussed

  • Treat the query suite as the source of truth: derive the planning snapshot from the workload instead of maintaining a separate hand-written plan.
  • Preserve production planning rules: use control-plane candidate enumeration and quotes rather than fabricating a PhysicalPlan.
  • Keep the backend capable of startup without fallback, but enable Prometheus fallback in this compliance Compose profile so planner-authorized exact/unsupported nodes remain comparable.
  • Remove expect_error because upstream suites do not use it; compare actual Prometheus API results instead.
  • Use exact labels and timestamps, semantic NaN/Inf handling, and explicit numeric tolerances only for finite values.
  • Make each case isolated: Compose state and volumes are reset to prevent cross-case sample contamination.
  • Keep raw reference/backend payloads and backend serving provenance in reports, not only terminal output.
  • Use local sibling source contexts for currently private Docker dependencies; follow-up issue Remove local Docker dependency overrides after sibling repositories are public #735 tracks replacing them once public.

Verification

  • go test ./... in promql-compliance/runner
  • cargo test -p control_plane --bin control_plane_quote_snapshot
  • Full live make run-all: 1 temporal query in each temporal fixture and 66 aggregation queries in each aggregation fixture passed.

Limitations

The first Docker build compiles the Rust images and can take several minutes. The suite currently reports backend serving provenance from X-ASAP-Data-Source; an absent value denotes Prometheus fallback in this Compose profile.

@milindsrivastava1997 milindsrivastava1997 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated code review: 5 findings, posted inline.

if err := l.runCompose(ctx, environment, "wait", "planner"); err != nil {
return fmt.Errorf("derive workload cost evidence: %w", err)
}
if err := l.runCompose(ctx, environment, "up", "-d", "data-plane"); err != nil {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale backend image (high). prometheus/planner get --build above, but data-plane is brought up without it, so Compose reuses the existing asapquery-backend-promql-compliance-data-plane image. After the first make run-all, subsequent runs on the same machine test the old data_plane binary (e.g. edit data_plane/src/..., rerun, and results still reflect the first build). Suggest adding --build here or building all three services in the first up.

c := caseCard{Dataset: r.Dataset, Suite: r.Suite, Passed: r.Passed, Queries: len(r.Queries)}
for _, q := range r.Queries {
for _, i := range q.Instant {
if i.Responses.Backend.ServedBy != "" {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Prometheus fallback" column is always 0 (medium). query.go sets ServedBy = "prometheus_fallback" when the provenance header is absent, so ServedBy is never empty for backend responses and this check counts fallback answers as ASAPQuery answers. The loop also only looks at q.Instant, skipping range responses. summary.md/summary.json therefore overstate local coverage.

func main() {
dir := flag.String("reports-dir", "/tmp/asapquery-backend-promql-reports", "report directory")
flag.Parse()
files, err := filepath.Glob(filepath.Join(*dir, "*.json"))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Picks up stale reports (medium). *.json in REPORT_DIR (a fixed /tmp path by default) also matches the summary.json written by the previous run; it decodes as a runner.Report with empty dataset/suite and the previous overall passed, adding a blank row and possibly pinning the result to false. Likewise, a case that fails before writing its report (build error, health timeout) leaves the previous run's <case>.json counted as current. Suggest excluding summary.json and clearing/scoping REPORT_DIR per run.

Comment thread data_plane/Dockerfile
# not need credentials for ASAPCollector or Sketchlib while this dependency
# remains private.
RUN mkdir -p ASAPQuery-backend/.cargo && \
printf '%s\n' \

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overwrites .cargo/config.toml and patches all builds (medium). (Same block in control_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_sketchlib now compile from whatever sibling working trees are passed as build contexts rather than the revisions pinned in Cargo.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.

asap-precompute-rs: ${ASAP_PRECOMPUTE_RS_CONTEXT}
asap-sketchlib: ${ASAP_SKETCHLIB_CONTEXT}
asap-gorilla-rust: ${ASAP_GORILLA_RUST_CONTEXT}
command: ["--profile", "asapquery", "--planning-snapshot", "/config/planning-snapshot.json", "--prometheus-server", "http://prometheus:9090", "--forward-unsupported-queries", "--http-port", "9091", "--output-dir", "/tmp/asap"]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fallback enabled but always fails the suite (low). --forward-unsupported-queries is on, but report.go:104 fails every response served by Prometheus fallback, so any query routed to the exact/fallback path fails rather than being compared. The design doc also says fallback should be disabled, which would make the validate_profile change in data_plane/src/main.rs pointless as written. Either drop the flag or accept fallback responses for those nodes.

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.

test: add Prometheus Remote Write PromQL differential suite

1 participant