Skip to content

Commit 7281e2d

Browse files
zzylolmilindsrivastava1997claude
authored
feat(asap-tools): run sketch-bench workload tables end to end with the paced feeder (#841)
* feat(planner): asap-planner --planner saved writes a sketch-bench eval plan without re-solving Reads a plan from sketch-bench's autosketch_vs_asap plan file and the eval table's `e2e` block (PromQL queries, the plan RQEs each reads, metric labels), and writes streaming and inference YAML through the same converter as --planner milp. experiment_run_e2e.py gains controller.prebuilt_output_dir to deploy those configs instead of running the planner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(planner): address review on --planner saved Check saved picks against the RAQE's window rules, refuse duplicate picks, reject avg queries before the leaf split, and take a roll-up's grouping from the plan so the shared guard catches it. Share the flag checks of --planner milp and saved. Copy only the two prebuilt configs into a cleared output dir, refusing the dir itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(asap-tools): run sketch-bench workload tables end to end with the 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 * feat(asap-tools): give Prometheus a 5 s out-of-order window for the paced 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 * feat(asap-tools): feed records metrics to ASAPQuery only 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 * fix(asap-tools): address review on the paced feeder runner - 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 * revert(asap-tools): drop Prometheus' out-of-order window for the paced feeder The feeder now keeps each series' samples of a tick in one ordered request, and Prometheus 2.53's remote-write receiver accepted a full feed (48M samples) with no out-of-order window and no rejections. This reverts f7e5a66; Prometheus keeps --web.enable-remote-write-receiver. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AnJ7LocWxguh3q4QWkCYae * fix(asap-tools): give every e2e mode the same data windows Each mode's feeder now stamps its data from the last multiple of the aligned query intervals (sending it in real time from a shared send time), and aligned query groups evaluate at that origin + k*T, sent once the data has arrived. Every mode then answers over the same samples, evaluation times stay on ASAPQuery's windows, and the first window is never empty. Also from review: - refuse forward_unsupported_queries when sketchdb mode gives Prometheus no data (the generator sets it false), and auto_discover_labels - take the fed metrics from the feeder block - launch feeders with one SSH per node and fail if that overruns the lead - stop feeders at exit after a failed run - resolve a relative workload_table; check parallelism only for sketchdb Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(asap-tools): wait for an aligned feeder start instead of backdating Feeders now start at the next multiple of the aligned intervals' LCM (at most 600 s) rather than stamping data in the past, so the client sends each query at its eval time + query_time_offset and the feeder loses --send-at-ms. Also from review: - refuse sub-second aligned intervals and query_time_offset below ASAPQuery's 5 s allowed lateness - give feeder launches 10 s per node on top of the 5 s lead - keep feeders running under flow.no_teardown - refuse --sql-queries without --prebuilt-output-dir - refuse other exporters next to the feeder with no listed metrics Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Milind Srivastava <milindsrivastava1997@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent bbb3033 commit 7281e2d

19 files changed

Lines changed: 2014 additions & 73 deletions

File tree

‎.github/workflows/python.yml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ jobs:
9292
- name: Type check with mypy
9393
working-directory: asap-tools/queriers/prometheus-client
9494
run: mypy .
95+
- name: Run tests
96+
working-directory: asap-tools/queriers/prometheus-client
97+
run: python -m unittest discover -s tests -v
9598

9699
test-utilities:
97100
needs: detect-changes

‎asap-tools/data-sources/paced-feeder/README.md‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,7 @@ http: 2000000 records/s
160160
```
161161

162162
Event time starts at the next whole wall-clock second (or `--start-ms`), so
163-
`NOW()`-relative queries see the data as it arrives. `--send-at-ms` sends the
164-
first tick at a later wall-clock time, backdating the data by the difference.
163+
`NOW()`-relative queries see the data as it arrives.
165164

166165
## Usage
167166

‎asap-tools/data-sources/paced-feeder/src/main.rs‎

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,6 @@ struct Args {
9393
/// next whole wall-clock second, so `NOW()`-relative queries see live data.
9494
#[arg(long)]
9595
start_ms: Option<i64>,
96-
/// Wall-clock time to send the first tick, in ms since the epoch. Defaults
97-
/// to `--start-ms`; a later time backdates the data by the difference, so
98-
/// feeders launched at different moments share one event-time origin.
99-
#[arg(long, requires = "start_ms")]
100-
send_at_ms: Option<i64>,
10196

10297
/// Rows per HTTP request, for gauges and counters rounded down to whole
10398
/// series (at least one). Defaults to 50,000 for remote write, which keeps
@@ -139,7 +134,6 @@ struct RunStats {
139134
samples_per_sec: Option<u32>,
140135
seed: u64,
141136
start_ms: i64,
142-
send_at_ms: i64,
143137
duration_secs: u64,
144138
target_rows_per_sec: usize,
145139
rows_sent: usize,
@@ -279,14 +273,6 @@ fn next_whole_second_ms() -> i64 {
279273
(now_ms / 1_000 + 1) * 1_000
280274
}
281275

282-
/// Data sent before its own timestamp would be in the future.
283-
fn check_send_at(start_ms: i64, send_at_ms: i64) -> Result<()> {
284-
if send_at_ms < start_ms {
285-
bail!("--send-at-ms ({send_at_ms}) must not be before --start-ms ({start_ms})");
286-
}
287-
Ok(())
288-
}
289-
290276
/// Sleep until wall-clock `epoch_ms`, then return the monotonic instant it maps to.
291277
async fn wait_for_wall_clock(epoch_ms: i64) -> Instant {
292278
let now_ms = SystemTime::now()
@@ -452,8 +438,6 @@ async fn main() -> Result<()> {
452438
let sink = Arc::new(Sink::new(&args, sink_kind, url, &workload, batch_rows)?);
453439
let permits = Arc::new(Semaphore::new(args.concurrency));
454440
let start_ms = args.start_ms.unwrap_or_else(next_whole_second_ms);
455-
let send_at_ms = args.send_at_ms.unwrap_or(start_ms);
456-
check_send_at(start_ms, send_at_ms)?;
457441
let metric_names = workload.names();
458442

459443
let series = if workload.metrics.is_empty() {
@@ -466,12 +450,12 @@ async fn main() -> Result<()> {
466450
)
467451
};
468452
eprintln!(
469-
"paced_feeder: {sink_kind:?} -> {url}, {}{series} = {} rows/s for {duration_secs}s, start_ms={start_ms}, send_at_ms={send_at_ms}",
453+
"paced_feeder: {sink_kind:?} -> {url}, {}{series} = {} rows/s for {duration_secs}s, start_ms={start_ms}",
470454
metric_names.join(", "),
471455
workload.rows_per_tick(),
472456
);
473457

474-
let base = wait_for_wall_clock(send_at_ms).await;
458+
let base = wait_for_wall_clock(start_ms).await;
475459
let mut ticks = Vec::with_capacity(duration_secs as usize);
476460
let mut errors: Vec<String> = Vec::new();
477461
let mut failed_requests = 0;
@@ -564,7 +548,6 @@ async fn main() -> Result<()> {
564548
samples_per_sec: (!workload.metrics.is_empty()).then_some(workload.samples_per_sec),
565549
seed: args.seed,
566550
start_ms,
567-
send_at_ms,
568551
duration_secs,
569552
target_rows_per_sec: workload.rows_per_tick(),
570553
rows_sent,
@@ -609,11 +592,4 @@ mod tests {
609592
assert!(validate_start_ms(1_700_000_000_000).is_ok());
610593
assert!(validate_start_ms(1_700_000_000_500).is_err());
611594
}
612-
613-
#[test]
614-
fn send_at_may_backdate_but_not_postdate_the_data() {
615-
assert!(check_send_at(1_000, 1_000).is_ok());
616-
assert!(check_send_at(1_000, 301_000).is_ok());
617-
assert!(check_send_at(1_000, 999).is_err());
618-
}
619595
}

‎asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,48 @@ These parameters come from the `experiment_type` config group and are prefixed w
457457
- **Example**: `"gauge"`
458458
- **Note**: Counter metrics have `_total` suffix, gauge metrics don't
459459

460+
#### Paced Feeder Parameters
461+
462+
`paced_feeder` runs `asap-tools/data-sources/paced-feeder` (built by
463+
`installation/common/setup_dependencies.sh`) bare-metal on the worker nodes,
464+
one process per (sink, metric). It pushes over remote write instead of being
465+
scraped: in `sketchdb` mode to the query engine's ingest
466+
(`streaming.remote_write`, which must have `parallelism: 1`), plus Prometheus
467+
when the mode sets `query_prometheus_too`; in every other mode to Prometheus,
468+
which then starts with `--web.enable-remote-write-receiver`. All processes
469+
share the seed and table, so every system gets the same data. Its metrics are
470+
listed under `metrics` with `exporter: paced_feeder`; Prometheus does not
471+
forward them to the query engine. Generate a whole config from a sketch-bench
472+
table with `sketch_bench_e2e/sketch_bench_e2e_configs.py`.
473+
474+
#### `experiment_params.exporters.exporter_list.paced_feeder.workload_table` (string, required)
475+
- **Description**: Local path of the sketch-bench workload table; copied to each feeder node
476+
- **Example**: `/path/to/synthetic-templatesclassic-shared1.json`
477+
478+
#### `experiment_params.exporters.exporter_list.paced_feeder.metrics` (list, required)
479+
- **Description**: Metrics of the table's `workloads[0].e2e.metrics` to send. Gauge and counter metrics go to every sink; `records` metrics (one sample per value field, `<metric>.<field>`) only to ASAPQuery, so they are refused when any mode feeds Prometheus (baseline, or `query_prometheus_too`)
480+
- **Example**: `[data, data_total]`
481+
482+
#### `experiment_params.exporters.exporter_list.paced_feeder.seed` (int, required)
483+
- **Description**: `--seed` of every feeder process
484+
- **Example**: `42`
485+
486+
#### `experiment_params.exporters.exporter_list.paced_feeder.duration_secs` (int, required)
487+
- **Description**: Seconds of data to send. Must be at least the feeder's startup check (7 s) plus `flow.steady_state_wait` plus the query groups' running time
488+
- **Example**: `4000`
489+
490+
#### `experiment_params.exporters.exporter_list.paced_feeder.samples_per_sec` (int, optional)
491+
- **Description**: Overrides the table's `samples_per_sec_per_series` (gauge and counter metrics)
492+
- **Example**: `20`
493+
494+
#### `experiment_params.exporters.exporter_list.paced_feeder.records_per_sec` (int, optional)
495+
- **Description**: Overrides the table's `records_per_sec` (records metrics)
496+
- **Example**: `20000`
497+
498+
#### `experiment_params.exporters.exporter_list.paced_feeder.extra_flags` (string, optional)
499+
- **Description**: Appended to every feeder command line
500+
- **Example**: `"--concurrency 32"`
501+
460502
### Query Group Configuration
461503

462504
#### `experiment_params.query_groups` (list, required)
@@ -500,6 +542,15 @@ These parameters come from the `experiment_type` config group and are prefixed w
500542
- **Example**: `15`
501543
- **Usage**: Ensures data is available for lookback queries
502544

545+
#### `experiment_params.query_groups[].client_options.align_to_interval` (boolean, optional)
546+
- **Description**: Evaluate repetition k at `t_k = data_start_time + (max(1, ceil(starting_delay / T)) + k) * T`, with `T = repetition_delay_ms` (whole seconds), sending it at `t_k + query_time_offset`. `starting_delay` counts from `data_start_time`, not as a sleep from client start
547+
- **Default**: `false`
548+
- **Usage**: Every evaluation time is a multiple of `T`, and repetition k covers the same samples in every mode however late the mode started; `query_time_offset` (at least 5 s, ASAPQuery's allowed lateness) is how long the data of the window ending at `t_k` gets to arrive. Overrides the query engine's per-aggregation alignment in sketchdb mode. Requires `data_start_time`; the LCM of the aligned intervals must be at most 600 s
549+
550+
#### `experiment_params.query_groups[].client_options.data_start_time` (int)
551+
- **Description**: Time (epoch seconds) the paced feeder's data starts at
552+
- **Usage**: Not set by hand: `experiment_run_e2e.py` writes it into each mode's client config after starting the paced feeder, which waits for the next multiple of the aligned groups' intervals' LCM
553+
503554
#### `experiment_params.query_groups[].client_options.starting_delay` (int, required)
504555
- **Description**: Initial delay in seconds before starting query execution
505556
- **Example**: `610`

‎asap-tools/experiments/constants.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
# Peak query memory is roughly 16 B per sample (~8 GB at this cap).
4949
PROMETHEUS_QUERY_MAX_SAMPLES = 500_000_000
5050
PROMETHEUS_REMOTE_WRITE_ENDPOINT = "/api/v1/write"
51+
# Lets Prometheus accept samples pushed to PROMETHEUS_REMOTE_WRITE_ENDPOINT.
52+
PROMETHEUS_REMOTE_WRITE_RECEIVER_FLAG = "--web.enable-remote-write-receiver"
5153
HTTP_READINESS_CURL_TIMEOUT_SECONDS = 5
5254
QUERY_ENGINE_RUNTIME_INFO_ENDPOINT = "/api/v1/status/runtimeinfo"
5355
# Query engine spill files live in this subdirectory of its output dir, which

‎asap-tools/experiments/experiment_run_e2e.py‎

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import os
2+
import atexit
23
import json
34
import time
45

56
import hydra
7+
import yaml
68
from omegaconf import DictConfig, OmegaConf
79

810
import constants
@@ -25,6 +27,13 @@
2527
DockerPrometheusService,
2628
DockerVictoriaMetricsService,
2729
SystemExportersService,
30+
PACED_FEEDER_EXPORTER,
31+
PacedFeederService,
32+
aligned_interval_lcm,
33+
check_paced_feeder_config,
34+
paced_feeder_min_duration_secs,
35+
paced_feeder_sinks,
36+
set_data_start,
2837
)
2938
from experiment_utils.services.misc import DiscoveryBackend
3039

@@ -188,6 +197,39 @@ def main(cfg: DictConfig):
188197
cfg.experiment_params
189198
)
190199

200+
modes_by_name = {
201+
m["mode"]: m
202+
for m in OmegaConf.to_container(cfg.experiment_params.experiment, resolve=True)
203+
}
204+
paced_feeder_service = None
205+
paced_feeder_config = exporter_config["exporter_list"].get(PACED_FEEDER_EXPORTER)
206+
if paced_feeder_config is not None:
207+
paced_feeder_config = OmegaConf.to_container(paced_feeder_config, resolve=True)
208+
# The feeder runs from its own directory.
209+
paced_feeder_config["workload_table"] = os.path.abspath(
210+
paced_feeder_config["workload_table"]
211+
)
212+
check_paced_feeder_config(
213+
paced_feeder_config,
214+
modes=list(modes_by_name.values()),
215+
parallelism=args.parallelism,
216+
min_feed_secs=paced_feeder_min_duration_secs(
217+
0 if skip_querying else args.steady_state_wait,
218+
minimum_experiment_running_time,
219+
),
220+
forward_unsupported_queries=args.forward_unsupported_queries,
221+
auto_discover_labels=args.controller_auto_discover_labels,
222+
)
223+
# Also checks the aligned query groups before any service starts.
224+
paced_feeder_align_secs = aligned_interval_lcm(
225+
OmegaConf.to_container(cfg.experiment_params, resolve=True)
226+
)
227+
paced_feeder_service = PacedFeederService(provider, args)
228+
if not args.no_teardown:
229+
# Otherwise a failed run leaves feeders pushing into the next
230+
# run's sinks.
231+
atexit.register(paced_feeder_service.stop)
232+
191233
for experiment_mode in experiment_modes:
192234
print(f"Running experiment mode: {experiment_mode}")
193235
experiment_output_dir = os.path.join(
@@ -228,6 +270,8 @@ def main(cfg: DictConfig):
228270
exporter_service.stop()
229271
deathstar_service.stop()
230272
prometheus_service.reset()
273+
if paced_feeder_service is not None:
274+
paced_feeder_service.stop()
231275

232276
# Also stop avalanche exporters if they were started
233277
if config.check_exporter_and_queries_exist("avalanche", cfg.experiment_params):
@@ -481,6 +525,45 @@ def main(cfg: DictConfig):
481525
), f"Expected PrometheusService but got {type(prometheus_service).__name__}"
482526
prometheus_service.start(experiment_output_dir)
483527

528+
# Pushes to its sinks, so it starts once they accept writes.
529+
if paced_feeder_service is not None:
530+
prometheus_url = (
531+
f"http://{args.remote_write_ip}:"
532+
f"{prometheus_service.get_query_endpoint_port()}"
533+
f"{constants.PROMETHEUS_REMOTE_WRITE_ENDPOINT}"
534+
)
535+
sinks = paced_feeder_sinks(
536+
modes_by_name[experiment_mode],
537+
query_engine_url=f"http://{args.remote_write_ip}:"
538+
f"{args.remote_write_base_port}{args.remote_write_path}",
539+
prometheus_url=prometheus_url,
540+
)
541+
if prometheus_url in sinks.values():
542+
prometheus_service.wait_until_ready()
543+
local_client_config = os.path.join(
544+
local_experiment_root_dir,
545+
"controller_client_configs",
546+
f"{experiment_mode}.yaml",
547+
)
548+
with open(local_client_config) as f:
549+
client_config = yaml.safe_load(f)
550+
start_ms = paced_feeder_service.start(
551+
config=paced_feeder_config,
552+
sinks=sinks,
553+
experiment_output_dir=experiment_output_dir,
554+
local_experiment_dir=local_experiment_dir,
555+
align_secs=paced_feeder_align_secs,
556+
)
557+
set_data_start(client_config, start_ms)
558+
with open(local_client_config, "w") as f:
559+
yaml.safe_dump(client_config, f, sort_keys=False)
560+
sync.rsync_controller_client_configs(
561+
provider,
562+
experiment_root_output_dir,
563+
local_experiment_root_dir,
564+
node_offset=args.node_offset,
565+
)
566+
484567
# Start Prometheus throughput monitoring if enabled
485568
if args.throughput_prometheus:
486569
prometheus_throughput_monitor = PrometheusThroughputMonitor(
@@ -562,6 +645,9 @@ def main(cfg: DictConfig):
562645

563646
# Skip teardown if the no_teardown flag is set
564647
if not args.no_teardown:
648+
# Before its sinks go away, so its log shows no spurious errors.
649+
if paced_feeder_service is not None:
650+
paced_feeder_service.stop()
565651
if experiment_mode == constants.SKETCHDB_EXPERIMENT_NAME:
566652
query_engine_service.stop()
567653

‎asap-tools/experiments/experiment_utils/core.py‎

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,17 @@ def read_exporter_config(experiment_params: DictConfig) -> Tuple[Optional[Dict],
134134
"cluster_data_exporter with parts_mode='part-index' requires 'part_index'",
135135
)
136136

137+
from experiment_utils.services.paced_feeder import (
138+
PACED_FEEDER_EXPORTER,
139+
PACED_FEEDER_REQUIRED_KEYS,
140+
)
141+
142+
if PACED_FEEDER_EXPORTER in exporters_config.exporter_list:
143+
feeder_config = exporters_config.exporter_list[PACED_FEEDER_EXPORTER]
144+
missing_keys = [k for k in PACED_FEEDER_REQUIRED_KEYS if k not in feeder_config]
145+
if missing_keys:
146+
return None, f"Missing keys in paced_feeder section: {missing_keys}"
147+
137148
return exporters_config, ""
138149

139150

@@ -186,9 +197,36 @@ def call_generate_prometheus_config(
186197
import generate_prometheus_config
187198
import generate_victoriametrics_config
188199

200+
from experiment_utils.services.paced_feeder import (
201+
PACED_FEEDER_EXPORTER,
202+
paced_feeder_metric_names,
203+
)
204+
205+
# The paced feeder writes its metrics to the query engine itself, so
206+
# Prometheus forwarding them too would send them twice.
207+
fed_metrics = paced_feeder_metric_names(cfg.experiment_params)
208+
metrics_to_remote_write = [
209+
m
210+
for m in get_metrics_to_remote_write(cfg.experiment_params)
211+
if m not in fed_metrics
212+
]
213+
# With only fed metrics there is nothing for Prometheus to forward. (An
214+
# empty list without the feeder keeps meaning "forward everything".)
215+
forward_to_query_engine = bool(metrics_to_remote_write) or not fed_metrics
216+
exporter_list = cfg.experiment_params.get("exporters", {}).get("exporter_list", {})
217+
other_exporters = sorted(set(exporter_list) - {PACED_FEEDER_EXPORTER})
218+
if not forward_to_query_engine and other_exporters:
219+
raise ValueError(
220+
f"exporters {other_exporters} run next to the paced feeder but none "
221+
"of their metrics are listed under experiment_params.metrics, so "
222+
"Prometheus would forward nothing of theirs to the query engine"
223+
)
189224
# Set up remote write if this is a SketchDB experiment
190-
if experiment_mode == sketchdb_experiment_name and sketchdb_experiment_name:
191-
metrics_to_remote_write = get_metrics_to_remote_write(cfg.experiment_params)
225+
if (
226+
experiment_mode == sketchdb_experiment_name
227+
and sketchdb_experiment_name
228+
and forward_to_query_engine
229+
):
192230
args.remote_write_metric_names = metrics_to_remote_write
193231

194232
# Build remote_write_url from experiment params

0 commit comments

Comments
 (0)