Skip to content

mvp issue-46 ④ ⑥ partial — archive ground truth flowing; warm + probe routing remain - #333

Merged
zzylol merged 1 commit into
mainfrom
mvp/issue-46-blocker-fixes
May 8, 2026
Merged

zzylol merged 1 commit into
mainfrom
mvp/issue-46-blocker-fixes

Conversation

@zzylol

@zzylol zzylol commented May 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Three targeted fixes after agent #98 (PR #332) left ④ and ⑥ as UNKNOWN. ④'s archive ground-truth side now flows (500 quantile rows return archive_status=ok via Thanos), but the warm engine and the agent-side probe routing have separate pre-existing bugs that block both criteria from flipping to PASS in this run.

  • controller/src/main.rs typed bootstrap path — extends Edge stage config with freshness_metrics (warm + archive probes) and all workload-registry metrics into archive_tier_metrics and warm_passthrough_metrics. Generates a typed YAML with proper gorillas3 + routing pattern. Groundwork for the OpAMP-on-connect port (replan.rs::push_config_to_agent → typed pipeline) that's the durable fix.
  • deploy/docker-compose/mvp-thanos-archive.yml--sync-block-duration=30s (was upstream default 3 min). Honest about the trade-off: 30s sync keeps demo soak windows seeing fresh blocks; production deployments run with the 3-min default because read-heavy archive workloads tolerate minutes-of-staleness.
  • deploy/scripts/mvp_report.py — surface the criterion's actual PASS/FAIL/UNKNOWN evaluation for ⑥ instead of the placeholder CAPTURED/UNKNOWN rollup that masked freshness-probe failures.

Verdict matrix vs PR #332

# Criterion PR #332 This PR Why the change
Bandwidth PASS PASS unchanged
Query latency CAPTURED CAPTURED unchanged
Combined resource CAPTURED CAPTURED unchanged
Accuracy UNKNOWN (all archive_miss) UNKNOWN (archive ok, warm errors) Thanos sync interval shrunk → 500/500 quantile queries return archive_status=ok with archive_answer populated; warm side returns status:error for the same 500 queries — separate warm-engine pattern-matcher gap
Cold-fallback PASS PASS unchanged
Freshness UNKNOWN (probe routing absent) UNKNOWN (still absent at agent) typed bootstrap NOW has the right routing, but agents load the static placeholder via volume mount and OpAMP-on-connect uses legacy generate_agent_config — neither has freshness probe routing
§8 Emitter live-bootstrap live-bootstrap unchanged

Remaining root causes (separate workstreams)

  1. Warm SimpleEngine errors on quantile_over_time and sum-instant queriesreplay.jsonl shows status=error for 500 of 500 quantile queries and 500 of 1000 sum queries (only sum by (zone) (rate(...)) succeeds). Fixing this needs a backend warm-engine investigation, not a config change.
  2. Static placeholder agent config has no routing connectorasap-otel-agent-b6-asap-single-sketch.yaml has only [gorillas3, ddsketch, batch]. DDSketch renames http_freshness_probe_warm_quantile, so the original metric name never reaches the warm tier in queryable form. The durable fix is the OpAMP-on-connect typed-config push (today blocked on replan.rs::push_config_to_agent still using generate_agent_config).

Test plan

  • cargo build --release -p controller
  • bash deploy/scripts/run_mvp_demo.sh --mode both — both pipelines run synchronously to teardown; report under /tmp/asap-mvp-rerun-fix/MVP_REPORT.md
  • Verify ④ archive_status=ok rows present (500/1500)
  • Verify §8 emitter: live-bootstrap (unchanged)
  • Flip ④ to PASS — blocked on warm-engine bug
  • Flip ⑥ to PASS — blocked on agent-side probe routing

🤖 Generated with Claude Code

…g, warm + probe routing remain

Changes:
- controller typed bootstrap: extend Edge stage config with freshness probes + workload-registry archive metrics so the typed path emits gorillas3 + warm-passthrough routing (groundwork for OpAMP-on-connect future port)
- thanos-store-gateway: shrink --sync-block-duration to 30s (was upstream default 3min) so demo soak window sees fresh blocks
- mvp_report.py: surface real ⑥ pass/fail verdict from criterion eval, not placeholder CAPTURED/UNKNOWN rollup

Verdict shift from PR #332's run:
- ④ archive ground truth: 500 quantile rows archive_status=ok (was 0, all archive_miss)
- ④ warm side: warm engine returns status=error for ALL 500 quantile queries — separate warm-engine pattern-matcher gap
- ⑥ still UNKNOWN: agents load static placeholder via volume mount, NOT typed bootstrap; freshness-probe routing absent at agent
- ① ② ③ ⑤: unchanged from PR #332

Two follow-up bugs documented:
1. Backend SimpleEngine errors on quantile_over_time and sum-instant queries (out of scope)
2. Static placeholder agent config has no routing for http_freshness_probe_* (out of scope; OpAMP-on-connect typed-config push is the durable fix)
@zzylol
zzylol merged commit c2fd32f into main May 8, 2026
zzylol added a commit that referenced this pull request May 8, 2026
… pipeline (#334)

`Replanner::push_config_to_agent` (and the agent-config push in
`replan_metric`) called the legacy `generate_agent_config` emitter,
which produces a single-pipeline DDSketch YAML with no `gorillas3`
archive write, no OTTL `routing` processor, and no
`metrics/warm_passthrough` pipeline. Agents that connected via the
OpAMP `on_connect` callback (the post-#333 reconnection path) got
that legacy YAML — so freshness-probe routing reached fresh-connect
agents (criterion ⑥ on issue #46) but NOT plan-pinned reconnecting
agents.

Mirror `main::emit_bootstrap_typed`'s flow on the OpAMP push path:
`bind_workload_typed` → `split_typed_three_stage` → pick the Edge
stage → extend with freshness-probe + workload-registry archive
metrics → `emit_for_runtime`. Gate it behind the existing
`USE_TYPED_STAGE_SPLIT` env var so the legacy single-pipeline
fallback still runs when the gate is off, matching `handle_plan` /
`handle_bootstrap_agent_config`. On any typed-emit error the push
falls back to the legacy emitter so it never silently drops.

The bootstrap-scope demo plumbing (freshness probes +
workload-registry archive metrics) is lifted out of
`emit_bootstrap_typed` into a shared `config::extend_edge_with_demo_plumbing`
helper; both bootstrap and replan now apply the SAME extension. The
runtime defaults to `AgentRuntime::AsapOtel` since OpAMP `on_connect`
doesn't surface the agent's runtime header today (matches the
bootstrap default for legacy clients).

Adds two unit tests in `replan::tests`:
- `typed_replan_emit_includes_freshness_probe_routing` —
  asserts the typed path emits `gorillas3`, `routing`,
  `metrics/warm_passthrough`, and references `http_freshness_probe_warm`.
- `legacy_path_omits_typed_processors_when_gate_off` — pins the
  gate semantics so a regression that always-on'd the typed path
  would surface here.

Together with PR #329 (bootstrap GET path) this finishes the
OpAMP-on-connect side of the typed emit so reconnecting agents now
receive the same routed YAML as fresh-connect agents.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
zzylol added a commit that referenced this pull request May 8, 2026
Pair with ASAPQuery-backend's per-tenant `BackendStorageRouting`
data-model + lookup change. Adds an explicit `tenant` field to
the controller-emitted JSON document the backend's
`POST /api/v1/storage_routing` endpoint consumes.

* New `emit_backend_storage_routing_for_tenant(tenant, plans)`
  and `emit_backend_storage_routing_with_prometheus_for_tenant(
  tenant, plans, mode3)` entry points. Tenant lands in the
  emitted JSON's top-level `tenant` field; the backend's
  per-tenant swap routes to the named slot.
* The single-tenant aliases (`emit_backend_storage_routing` /
  `emit_backend_storage_routing_with_prometheus`) keep emitting
  the `default` tenant id so existing single-tenant deploys are
  source-compatible.
* `DEFAULT_TENANT` constant mirrors the backend's value so the
  controller doesn't take a build-time dep on the backend crate.
* Snapshot test updated for the new `tenant: "default"` field;
  three new unit tests cover the per-tenant emit path.

Out of scope (matches backend part 1/2):
* Tenant-aware AUTH.
* Per-tenant sketch state isolation.

Closes the per-tenant follow-up flagged in PR #333.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
zzylol added a commit that referenced this pull request May 8, 2026
…L/CountSketch/CountMinSketch) (#340)

Rewrites the typed L5 edge YAML emitter so the agent loads all 5
sketch processors and the OTel `routing` *connector* (NOT the
deprecated routing processor) dispatches per metric to the right
sketch family — the canonical wire shape for MVP issue #46.

## Bugfix call-out: routing is a CONNECTOR, not a processor

OTel collector v0.106+ removed `routingprocessor` and re-shipped
the routing component as a connector under the top-level
`connectors:` block. The legacy emit path placed `routing` under
`processors:`, which fails confmap validation at agent boot:
  `error decoding 'processors': unknown type: "routing"`.

This PR emits the connector-form layout the asap-otel binary's
builder-config registers:

  receivers:  { otlp }
  processors: { gorillas3?, batch,
                ddsketchprocessor, kllprocessor, hllprocessor,
                countsketchprocessor, countminsketchprocessor }
  connectors: { routing: { default_pipelines: [...],
                           table: [...route() statements...] } }
  exporters:  { otlp/backend, otlphttp/prometheus? }

  service.pipelines:
    metrics:                            (entry — receivers: [otlp],
                                          exporters: [routing])
    metrics/raw_passthrough             (default — receivers: [routing],
                                          processors: [gorillas3?, batch],
                                          exporters: [otlp/backend])
    metrics/ddsketch_path
    metrics/kll_path
    metrics/hll_path
    metrics/countsketch_path            (per-family — receivers: [routing],
    metrics/countminsketch_path           processors: [gorillas3?,
                                                       <family>processor,
                                                       batch],
                                          exporters: [otlp/backend])

`gorillas3` runs FIRST in every per-sketch pipeline (when an
archive tier is declared) so the cold-tier write happens BEFORE
the family processor mutates / suffix-renames the stream — same
invariant the legacy emit path enforces.

## EdgeStageConfig field

Adds `metric_to_family: HashMap<String, SketchKind>` to
`EdgeStageConfig` (agreed convention with the parallel planner
agent). Empty map ⇒ legacy single-pipeline / Mode-3 /
warm-passthrough emit shapes are preserved verbatim
(backward-compat).

When non-empty, the new `emit_edge_yaml_5sketch_routing` helper
emits the canonical 6-pipeline layout. Metrics in the map dispatch
per-family; metrics absent fall through to `metrics/raw_passthrough`
(this is the home for `http_requests_total` and the freshness
probes from PR #333's warm-passthrough routing).

## Field plumbing

Updates every `EdgeStageConfig` constructor in `controller/src/`
to initialise `metric_to_family: HashMap::new()` so existing
callers keep producing the legacy shape.

Adds `connectors: HashMap<String, Value>` to the structural
`CollectorYaml` type with `skip_serializing_if = "is_empty"` so
the legacy single-pipeline shape doesn't gain an empty
`connectors: {}` block.

## Test coverage

11 new tests pin the new wire shape:
  * mvp46_emit_loads_all_5_sketch_processors
  * mvp46_routing_lives_in_connectors_not_processors  (the bugfix)
  * mvp46_emits_all_6_named_pipelines
  * mvp46_entry_pipeline_routes_to_connector_not_processor
  * mvp46_per_sketch_pipelines_use_routing_as_receiver
  * mvp46_per_sketch_pipelines_have_gorillas3_first_when_archive_declared
  * mvp46_routing_table_dispatches_per_metric_to_correct_family
  * mvp46_default_pipeline_is_raw_passthrough
  * mvp46_warm_passthrough_routes_to_raw_passthrough_pipeline
  * mvp46_empty_metric_to_family_falls_back_to_legacy_emit
  * mvp46_composes_with_prometheus_archive_mode3

All 99 `config::*` tests pass; the 10 pre-existing failures on
`main` (analyzer, intent_algebra, planner cost_model, opamp,
api_tests) are untouched by this change.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zzylol
zzylol deleted the mvp/issue-46-blocker-fixes branch May 9, 2026 18:00
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