Skip to content

test(e2e): tighten Test 3's wire-shape requirements + document deeper gap - #250

Merged
zzylol merged 1 commit into
mainfrom
tighten-e2e-query-assertion
May 15, 2026
Merged

zzylol merged 1 commit into
mainfrom
tighten-e2e-query-assertion

Conversation

@zzylol

@zzylol zzylol commented May 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Investigation following #249 (L5-walk fix) clarified two more ingest-path requirements that were silently dropping the OTLP DPs even after the streaming-config JSON shape was correct:

  1. OTLP DP needs at least one attribute (or known sid). With both empty, the receiver hits the "invalid wire shape" drop in route_modified_otlp_sketches_to_precompute (per the comment block at otel.rs:926(sid=0, no attrs) is dropped). Test 3 now attaches service="e2e-test" to the DP.

  2. The DP's group_by_keys must EXACTLY match the streaming-config policy's grouping_labels for find_policy_by_content to bind policy_fp to the registered sid. The match is strict at ingest (asap_tier_analysis.rs:525) but subset at query time (asap_tier_analysis.rs:587) — intentional asymmetry (ingest needs uniqueness; queries can re-aggregate down). Test 3 now uses group_by_labels: ["service"] to align.

After both alignments, the runtime-info endpoint shows the sketch state DID land in SketchStore (earliest_timestamp_per_sid is populated). The query nevertheless still returns bad_data / "No result for query" — there's a remaining gap between SketchStore::instances_matching and the engine's reducer dispatch. Untangling that needs deeper engine-path tracing (likely a candidate.required_capability vs policy_capability asymmetry, or a sid-by-policy_fp reverse-index lookup failure).

What this PR delivers

  • Test 3 now exercises a realistic OTLP DP shape instead of the minimal "invalid wire shape" one.
  • The findings live as comments in the test file so the next investigation starts from a documented baseline.
  • The query soft-check (status field exists, value not asserted) remains. Tightening to status == "success" is what remains for whoever closes the engine-path gap.

Test plan

  • cargo test --test e2e_controller_plans_and_backend_serves: 3 passed

🤖 Generated with Claude Code

… gap

Investigation following #249 (L5-walk fix) clarified two more
ingest-path requirements that were silently dropping the OTLP DPs
even after the streaming-config JSON shape was correct:

1. **OTLP DP needs at least one attribute (or known sid).** With
   both empty, the receiver hits the "invalid wire shape" drop in
   `route_modified_otlp_sketches_to_precompute` (per the comment
   block at otel.rs:926 — `(sid=0, no attrs)` is dropped). Test 3 now
   attaches `service="e2e-test"` to the DP; with this, the resolver
   mints a sid and the sketch state lands in `SketchStore`.

2. **The DP's `group_by_keys` (from `dp.attrs.keys()`) must EXACTLY
   match the streaming-config policy's `grouping_labels`** for
   `find_policy_by_content` to bind `policy_fp` to the registered
   sid. The match is **strict** at ingest (asap_tier_analysis.rs:525)
   but **subset** at query time (asap_tier_analysis.rs:587) — that
   asymmetry is intentional (ingest needs uniqueness; queries can
   re-aggregate down). Test 3 now uses `group_by_labels: ["service"]`
   in the workload so the streaming-config grouping aligns with the
   DP's attrs.

After both alignments, the runtime-info endpoint shows the sketch
state DID land in `SketchStore` (`earliest_timestamp_per_sid` is
populated). The query nevertheless still returns `bad_data` /
"No result for query" — there's a remaining gap between
`SketchStore::instances_matching` and the engine's reducer dispatch.
Untangling that needs deeper engine-path tracing (likely a candidate.
required_capability vs policy_capability asymmetry, or a
sid-by-policy_fp reverse-index lookup failure).

This PR captures the findings as comments and tightens the test's
wire-shape requirements so the next investigation starts from a
realistic OTLP DP shape rather than the minimal "invalid wire shape"
one.

The query soft-check (status field exists, value not asserted)
remains in place. Tightening to `status == "success"` plus an
exact-value-within-SLA check on the returned quantile is what
remains for whoever closes the engine-path gap.

Tests: 3/3 pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zzylol
zzylol merged commit 09726eb into main May 15, 2026
zzylol added a commit that referenced this pull request May 15, 2026
…re (#251)

Mirrors #244 / #246 / #250's PR-5 wire-cleanup pattern, now for the
edge-side runtime emitters. The patched asap-otel processors (any
runtime — OTel collector / OTAP / Telegraf) don't consume the
controller-allocated `aggregation_id` string: sid identity is
content-addressed at the backend via `(metric_name,
attrs_fingerprint, agg_kind_canonical)`, and `policy_fp` content-
matches via `(metric, sketch_kind, config, group_by_keys)`. The
controller-allocated string is dead weight on the wire.

The OTel-collector YAML emitter (`emit_edge_yaml`) was already
clean — there's an existing test at stage_config.rs asserting the
agent YAML does NOT contain `aggregation_id:`. This PR catches the
two remaining edge-runtime emitters that still spelled it out:

- `emit/otap.rs::build_asap_sketches_config` (line ~287): drop
  the `aggregation_id` map entry; keep `sketch_kind` etc.
- `emit/telegraf.rs::emit_processors_allsketches` (line ~158):
  drop the `aggregation_id = "…"` TOML line; keep `sketch_kind`.

`EdgeSketchProcessor.aggregation_id` stays on the struct as
internal emitter plumbing for cross-stage references during the
DAG walk (`SketchAgg → BackendAggregation → BackendReadout`); it
just doesn't reach the wire from any runtime emitter anymore.

Tests: 690 lib + 27 binary tests pass. (No test asserted the field
was present in OTAP / Telegraf output, so nothing to flip.)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
zzylol added a commit that referenced this pull request May 15, 2026
…itations (#252)

Engine-path debug session diagnosis (post-#247#248#249#250).

The query layer's "No result for query" symptom for sketch-backed
metrics has a precise root cause: `query_precomputes_by_agg` (called
unconditionally by `execute_store_query`) filters its candidate-sid
scan with `matches!(&m.agg_kind, AggKind::ExactAgg { … })` — never
matching `AggKind::Sketch`. Since OTLP-arriving DDSketch / KLL / HLL /
CountSketch / CountMinSketch DPs are registered with
`AggKind::Sketch { kind, config, .. }`, the lookup always returns an
empty map for them, the engine bubbles up "No precomputed outputs
found", and `handle_query` returns `None` → HTTP responds
`errorType: bad_data` / `error: "No result for query"`.

Sketches DO reach `SketchStore` — they're readable via the sid-keyed
`query_range(sid, ...)` path which filters on `payload.as_sketch()`.
The agg-keyed precompute lookup is the gap.

This PR adds doc-comment blocks at both the call site
(`engine.rs::execute_store_query`) and the function definition
(`mod.rs::query_precomputes_by_agg`) flagging the gap with
file:line citations and pointing at the two viable fixes:
  * teach `query_precomputes_by_agg` to also collect sketch
    payloads (assemble `Box<dyn AggregateCore>` from
    `payload.as_sketch()`) — non-trivial; payload shapes diverge.
  * route the legacy `handle_query` path through the newer
    `ASAPQueryEngine::execute(&str)` trait dispatcher (around
    engine.rs:3430) which already handles sketches via
    `idx.sids_for_policy(fp)` + reducer dispatch.

No behaviour change. 690 lib + 27 binary tests pass.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zzylol
zzylol deleted the tighten-e2e-query-assertion branch July 17, 2026 20:06
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.

1 participant