Skip to content

feat(asap-tools): run sketch-bench workload tables end to end with the paced feeder - #841

Open
zzylol wants to merge 4 commits into
824-planner-savedfrom
feat/e2e-paced-feeder-runner
Open

zzylol wants to merge 4 commits into
824-planner-savedfrom
feat/e2e-paced-feeder-runner

Conversation

@zzylol

@zzylol zzylol commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #828 (--planner saved, controller.prebuilt_output_dir); base is its branch. This is #824 B4, revised: the data comes from the paced feeder instead of fake_exporter.

Summary

Runs a sketch-bench #777 workload table end to end with experiment_run_e2e.py. The paced feeder pushes the table's data in real time, and queries repeat at each RQE's interval T at evaluation times aligned to T.

  • Feeder service (experiment_utils/services/paced_feeder.py), configured by exporters.exporter_list.paced_feeder: {workload_table, metrics, seed, duration_secs, samples_per_sec?, extra_flags?}:
    • One feeder process per (sink, metric), on the worker nodes (the coordinator in local mode). All processes get the same seed, table and --start-ms, so every system receives identical data.
    • sketchdb mode pushes to ASAPQuery's ingest, and to Prometheus too with query_prometheus_too; other modes push to Prometheus. In sketchdb mode Prometheus no longer forwards the fed metrics to ASAPQuery, so they don't arrive twice.
    • It starts once its sinks are ready, and fails the run if a feeder dies at startup (wrong URL, etc.).
    • Startup checks: the metric is in the table and is a gauge/counter, streaming.parallelism == 1, and duration_secs outlasts the queries.
    • setup_dependencies.sh builds the feeder.
  • Prometheus: when the feeder is configured, it starts with --web.enable-remote-write-receiver and storage.tsdb.out_of_order_time_window: 5s. The feeder sends each one-second tick concurrently (fix(asap-tools): send paced feeder ticks concurrently, ordered per series, in (t, t+1s] #840), so a series' samples can arrive out of order within a tick, which Prometheus otherwise rejects. Bare metal and container both read the generated prometheus.yml.
  • Query-time alignment: client_options.align_to_interval evaluates repetition k at floor((start − O)/T)·T + k·T and sends it O = query_time_offset seconds later, so all systems answer the same windows.
  • Config generator (sketch_bench_e2e/sketch_bench_e2e_configs.py): from a workload table (+ optional prebuilt controller output dir), it writes an experiment_type YAML. Query groups come from e2e.queries grouped by interval_secs (the same grouping as --planner saved), with metrics from e2e.metrics and the feeder block.
  • ASAPQuery's allowed lateness in these runs is the engine default, 5 s (the framework never overrides it), so the feeder's within-tick reordering is safe.

Not covered yet

  • Multigroup (records) metrics (feeder support in feat(asap-tools): generate records metrics in the paced feeder #843) are fed to ASAPQuery only, as <table>.<field> for its SQL frontend. The startup check refuses them when any mode also sends to Prometheus (baseline, or query_prometheus_too). The generator feeds them only with --sql-queries, and then writes a sketchdb-only config; the Prometheus baseline for the classic queries of an all table is a separate run.
  • SQL query groups: the query client uses one protocol per server, so multigroup's SQL queries can't be sent to ASAPQuery's SQL endpoint from this runner yet. The generator includes them only with --sql-queries FILE.
  • No cluster run yet. The end-to-end check (ASAPQuery vs Prometheus vs ClickHouse on the same data) comes with the rest of the stack.

Testing

  • 29 new tests: tests/test_paced_feeder.py (feeder command lines, sinks per mode, startup checks, the Prometheus receiver flag and out-of-order window via the real config generator), tests/test_sketch_bench_e2e_configs.py (config generation from a real classic table snippet) and queriers/prometheus-client/tests/test_query_time.py (alignment math). The experiments suite passes (86 tests) under pytest and unittest. A CI step now runs the prometheus-client tests. black/flake8 are clean.
  • Dry run: the generated YAML for sketch-bench's classic shared1 table loads through Hydra and passes the runner's startup checks; controller, client and Prometheus configs are generated. In dry-run mode the client, started at 12:00:35 with T = 60 s and a 10 s offset, evaluated at 12:00:00, 12:01:00 and 12:02:00.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AnJ7LocWxguh3q4QWkCYae

zzylol and others added 2 commits October 13, 2026 01:27
…e paced feeder

- exporters.exporter_list.paced_feeder: experiment_run_e2e.py runs one
  paced_feeder process per (sink, metric) on the worker nodes, pushing over
  remote write to the query engine's ingest (sketchdb mode) and/or
  Prometheus (other modes, or query_prometheus_too). It starts once its
  sinks accept writes, shares one --start-ms and seed, and fails the run if
  a feeder dies. Prometheus does not forward fed metrics to the query engine.
- Prometheus (bare-metal and containerized) starts with
  --web.enable-remote-write-receiver when the feeder is configured.
- client_options.align_to_interval: repetition k evaluates at
  floor((start - query_time_offset) / T) * T + k * T and is sent
  query_time_offset after that time.
- sketch_bench_e2e/sketch_bench_e2e_configs.py writes an experiment_type
  config from a table's e2e block: one query group per interval, the feeder
  block, metrics, and controller.prebuilt_output_dir; structured queries
  only with a SQL file.
- setup_dependencies.sh builds the feeder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnJ7LocWxguh3q4QWkCYae
…aced feeder

The feeder sends each tick's requests concurrently, so a series' samples
can reach Prometheus' remote-write receiver out of order within a second,
and Prometheus rejects them without an out-of-order window. When the paced
feeder is configured, the generated prometheus.yml (used by bare-metal and
containerized Prometheus) sets storage.tsdb.out_of_order_time_window: 5s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnJ7LocWxguh3q4QWkCYae
zzylol and others added 2 commits October 13, 2026 01:52
Records metrics (http, flows) reach remote write as one sample per value
field, many sharing a series and timestamp, which Prometheus' receiver
rejects. check_paced_feeder_config now takes the experiment modes: it
accepts records metrics when every mode feeds ASAPQuery only and refuses
them when a mode feeds Prometheus (baseline or query_prometheus_too).

The config generator feeds a table's records metrics only with
--sql-queries (only the structured queries read them); the config then
has no baseline mode, and records metrics stay out of `metrics`, which
with prebuilt planner configs only keeps fed metrics out of Prometheus'
forwarding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnJ7LocWxguh3q4QWkCYae
- Pass --samples-per-sec only to gauge and counter feeders and the new
  records_per_sec as --records-per-sec only to records feeders; the
  feeder exits on the other kind's flag.
- SQL query groups get time_window_seconds: 0; their templates read only
  {{ end_time }} / {{ end_datetime }}, but the client refuses to render
  templates without a window.
- Take the shared --start-ms after the per-node binary check and table
  copy, so the 5 s lead covers only the launches.
- duration_secs must also cover the feeder's startup check before
  steady_state_wait and the queries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnJ7LocWxguh3q4QWkCYae
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