diff --git a/Cargo.lock b/Cargo.lock index febd8591d..40330971c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -423,7 +423,7 @@ dependencies = [ [[package]] name = "asap_sketchlib" version = "0.1.0" -source = "git+https://github.com/ProjectASAP/asap_sketchlib?branch=refactor%2Fadopt-sketch-core-modules#d84ff152c7ac7c90b97bf2fbe0d88f28c147d7a6" +source = "git+https://github.com/ProjectASAP/asap_sketchlib?branch=refactor%2Fwire-format-align-go#d8c0c7f50c99d0e455080e3aa9ecac545c8a070e" dependencies = [ "bytes", "prost", @@ -1592,7 +1592,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2314,7 +2314,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi 0.5.2", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2359,7 +2359,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3264,7 +3264,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ "heck 0.5.0", - "itertools 0.10.5", + "itertools 0.13.0", "log", "multimap", "once_cell", @@ -3284,7 +3284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.117", @@ -3743,7 +3743,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4090,7 +4090,6 @@ dependencies = [ "cfg-if", "libc", "psm", - "windows-sys 0.52.0", "windows-sys 0.59.0", ] @@ -4246,7 +4245,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/TODO.md b/TODO.md index fc6688346..066efe414 100644 --- a/TODO.md +++ b/TODO.md @@ -1,11 +1,91 @@ # TODO — ASAPQuery-backend / sketchDB -Post-session state: PRs #43–#51 landed. This doc enumerates what's +_Last updated: 2026-05-01._ + +Post-session state: PRs #43–#71 landed. This doc enumerates what's left for sketchDB to be paper-ready (VLDB / SIGMOD) + what's deferred to future work. See the design source at [`docs/design-sketch-db.md`](docs/design-sketch-db.md). +## Warm-tier query path closes the loop (2026-05-01) + +The all-five-sketch query path from 2026-04-30 was wire-correct but +the live PromQL surface still returned empty even with data +demonstrably in the precompute store. Two PRs fixed that: + +- **OTLP gRPC `max_decoding_message_size`** ([#70](https://github.com/ProjectASAP/ASAPQuery-backend/pull/70)). + tonic's 4 MiB default rejected the gateway's first-window + full-state DDSketch batch (~17 MiB at 1k cardinality). Gateway + exporter looped on `decoded message length too large` forever. + Bumped the receiver to 64 MiB, matching the `max_recv_msg_size_mib` + value the agent and gateway already declare on their own OTLP + receivers. + +- **`range_query_into` overlap filter + closest-pane + response + annotation** ([#71](https://github.com/ProjectASAP/ASAPQuery-backend/pull/71)). + Two-part fix: + + 1. **Overlap filter (store side).** `MutableEpoch::range_query_into` + and `SealedEpoch::range_query_into` in + `simple_map_store/common.rs` (and the on-disk parts variant + in `per_key.rs:query_disk_parts`) used a "fully-contained" + filter (`tr.0 < start || tr.0 > end || tr.1 > end → skip`). + For tumbling windows of size W with a query range R, this + matches at most `floor(R/W)` panes and only when both query + endpoints land exactly on the pane grid. PromQL queries + don't align to the grid (the wall-clock fractional portion + of `query_time` is generally non-zero), so the strict filter + returned 0 panes for every realistic query. Replaced with + standard half-open overlap: keep `[tr.0, tr.1)` if `tr.1 > start + && tr.0 < end`. + + 2. **Closest-pane + annotation (engine + adapter side).** Per + follow-up review: rather than merge multiple overlapping + panes (slightly imprecise for sketch summaries), the engine + now picks a **single closest pane** (max `tr.1`, tie-break + on max `tr.0`) and threads the chosen `[start_ms, end_ms)` + up through `QueryResult::with_window_used` to the Prometheus + HTTP adapter, which adds it to the response's `infos` array + as `precompute_window: [..., ...) ms (width N ms)`. Mirrors + the existing `with_accuracy` annotation pattern. Now the + caller sees exactly which precompute time range produced + each value — important when the request range and the + answered range differ. + +### Live verification + +``` +$ curl '/api/v1/query?query=quantile_over_time(0.5, http_requests_total_latency_ms_quantile[1m])&time=$(now-90s)' +{"data":{"result":[{"metric":{"node":""}, + "value":[..., "19.493849507395904"]}], + "resultType":"vector"}, + "infos":["accuracy: ε=0.01, δ=0, kind=relative_quantile", + "precompute_window: [1777655280000, 1777655310000) ms (width 30000 ms)"]} +``` + +Pre-fix: `result: []` with `No precomputed outputs found` even +though `runtime_info.earliest_timestamp_per_aggregation_id` was +populated and worker logs showed `Worker emitting 1 sketch outputs +for group (1, )` at every flush. + +### Companion changes on the agent side + +The collector-side path needed three connected fixes for delta +transmission to round-trip +([ASAPCollector#210](https://github.com/ProjectASAP/ASAPCollector/pull/210)) +plus a windowed-processor pass-through to make multi-sketch +single-pipeline configs work +([ASAPCollector#211](https://github.com/ProjectASAP/ASAPCollector/pull/211)). +The backend-side delta apply path +(`apply_modified_otlp_delta_bytes` → +`{DDSketch,CMS,CountSketch,HLL}Accumulator::apply_proto_delta_bytes`) +was already in place; it just wasn't reachable until the agent +correctly tagged delta payloads on the typed encoding field and +stopped polluting the per-data-point attribute set with the +encoding string (which had broken the per-series snapshot cache +key). + ## All-five-sketch query path verification (2026-04-30) Each sketch type now has a runtime-verified PromQL → backend path @@ -48,6 +128,18 @@ data points). Specifically: frequency. To drive `topk(N, …)` over CMS-tracked keys we need a key-aggregator processor on the agent. Tracked as a paper follow-up; out of scope for v1. +- **`IngestState.sketch_snapshots` is RAM-only.** Per-series + snapshot cache that delta frames apply against is lost on + backend restart. After a bounce, agents continue emitting + `proto_delta` against their local snapshots, and the backend + drops them as "delta-sketch arrived before any base snapshot" + until the agent itself restarts. Persist to the existing + per-key disk layer used by `SimpleMapStore::with_persistence_per_key`, + or add an OpAMP capability for backend → agent "send next + frame as full state" signalling. Same item lives on the + collector side + ([`PROGRESS.md` follow-up #3](https://github.com/ProjectASAP/ASAPCollector/blob/main/PROGRESS.md)); + a fix on either side closes the gap. ## For paper submission (blocker) diff --git a/asap-query-engine/Cargo.toml b/asap-query-engine/Cargo.toml index 90c4c2efb..108d98ecb 100644 --- a/asap-query-engine/Cargo.toml +++ b/asap-query-engine/Cargo.toml @@ -61,7 +61,7 @@ zstd = "0.13" reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls"] } tracing-appender = "0.2" elastic_dsl_utilities.workspace = true -asap_sketchlib = { git = "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/ProjectASAP/asap_sketchlib", branch = "refactor/adopt-sketch-core-modules" } +asap_sketchlib = { git = "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/ProjectASAP/asap_sketchlib", branch = "refactor/wire-format-align-go" } # Persistence layer (SimpleMapStore parts / manifest / Tier-2 cache) moka = { version = "0.12", features = ["sync"] } memmap2 = "0.9" diff --git a/asap-query-engine/src/precompute_operators/count_sketch_accumulator.rs b/asap-query-engine/src/precompute_operators/count_sketch_accumulator.rs index 00238eb61..8efeaed7e 100644 --- a/asap-query-engine/src/precompute_operators/count_sketch_accumulator.rs +++ b/asap-query-engine/src/precompute_operators/count_sketch_accumulator.rs @@ -178,11 +178,23 @@ impl CountSketchAccumulator { .zip(pb.d_counts.iter()) .map(|((r, c), dc)| (*r, *c, *dc)) .collect(); + // Proto-schema-divergence-tracker: the Go-side + // `CountSketchDelta` proto carries an `hh_keys` field + // (heavy-hitter candidate keys forwarded by the upstream + // Space-Saving tracker). The Rust wire-format struct now + // models it (`asap_sketchlib::CountSketchDelta::hh_keys`), + // but the vendored Rust proto bindings in + // `asap_otel_proto::sketchlib::v1` haven't been regenerated + // against the latest `.proto` yet, so no `hh_keys` arrive on + // the wire from Go producers. Sending an empty `hh_keys` + // disables the TopK rebuild path; it'll start firing once the + // proto-schema sync PR lands. let delta = CountSketchDelta { rows: pb.rows, cols: pb.cols, cells, l2: pb.l2, + hh_keys: Vec::new(), }; self.inner .apply_delta(&delta)