From 69204f3e2c20d60c713399e1f775fc269fbd4de0 Mon Sep 17 00:00:00 2001 From: Milind Srivastava Date: Tue, 6 Oct 2026 16:50:35 -0400 Subject: [PATCH 1/4] refactor(planner): rename latency_sla to optional latency_sla_ms `controller_options.latency_sla` had no unit and was never enforced. The MILP planner takes a per-query latency ceiling in milliseconds, so the field becomes `latency_sla_ms: Option` (finite, > 0; omitted = no limit). `ControllerOptions` now denies unknown fields so an old `latency_sla` key fails loudly instead of being ignored. Old `latency_sla` lines are removed from configs, generators, the Go runner and docs. Co-Authored-By: Claude Opus 5.5 --- asap-planner-rs/src/bin/candidate_gen_dump.rs | 6 +- asap-planner-rs/src/config/input.rs | 91 +++++++++++++++++-- .../src/optimizer/aqe_extractor.rs | 12 +-- .../src/optimizer/candidate_gen.rs | 2 +- asap-planner-rs/src/optimizer/cost_model.rs | 2 +- asap-planner-rs/src/optimizer/error.rs | 2 +- asap-planner-rs/src/optimizer/greedy.rs | 6 +- .../src/optimizer/label_set_facts.rs | 2 +- asap-planner-rs/src/optimizer/pipeline.rs | 2 +- asap-planner-rs/src/optimizer/solution.rs | 5 +- .../test_data/configs/binary_arithmetic.yaml | 1 - .../configs/binary_arithmetic_dedup.yaml | 1 - .../configs/binary_arithmetic_nested.yaml | 1 - .../binary_arithmetic_non_acceleratable.yaml | 1 - .../configs/binary_arithmetic_scalar.yaml | 1 - .../test_data/configs/cleanup_circular.yaml | 1 - .../test_data/configs/cleanup_read_based.yaml | 1 - .../test_data/configs/deduplicated.yaml | 2 - .../test_data/configs/increase.yaml | 1 - .../test_data/configs/mixed_workload.yaml | 1 - .../test_data/configs/quantile_over_time.yaml | 1 - .../test_data/configs/range_query.yaml | 1 - .../test_data/configs/rate_increase.yaml | 1 - .../test_data/configs/spatial_quantile.yaml | 1 - .../comparison/test_data/configs/sum_by.yaml | 1 - .../test_data/configs/sum_by_overlapping.yaml | 1 - .../test_data/configs/sum_over_time.yaml | 1 - .../configs/temporal_overlapping.yaml | 1 - .../comparison/test_data/configs/topk.yaml | 1 - .../tests/elastic_dsl_integration.rs | 3 - asap-planner-rs/tests/elastic_example.yaml | 1 - asap-planner-rs/tests/integration.rs | 16 ---- asap-planner-rs/tests/sql_integration.rs | 13 --- .../test_data/windowing/promql_sliding.yaml | 2 - .../test_data/windowing/sql_sliding.yaml | 2 - .../windowing/sql_sliding_invalid.yaml | 2 - .../tests/e2e_precompute_equivalence.rs | 1 - asap-quickstart/config/controller-config.yaml | 1 - asap-tools/docs/architecture.md | 1 - asap-tools/docs/configuration.md | 2 +- .../CONFIG_PARAMETERS_REFERENCE.md | 12 +-- .../cluster_data_alibaba_msresource_2021.yaml | 1 - .../cluster_data_alibaba_msresource_2022.yaml | 1 - .../cluster_data_alibaba_node_2021.yaml | 1 - .../cluster_data_alibaba_node_2022.yaml | 1 - .../experiment_type/cluster_data_google.yaml | 1 - ...aba_v2022_ms_cpu_by_msname_5m_default.yaml | 1 - ...v2022_ms_cpu_by_msname_5m_recommended.yaml | 1 - ...2022_ms_cpu_by_msname_instant_default.yaml | 1 - ..._ms_cpu_by_msname_instant_recommended.yaml | 1 - .../google_2011_cpu_by_job_id_5m_default.yaml | 1 - ...gle_2011_cpu_by_job_id_5m_recommended.yaml | 1 - ...le_2011_cpu_by_job_id_instant_default.yaml | 1 - ...011_cpu_by_job_id_instant_recommended.yaml | 1 - .../google_2011_cpu_p99_instant_default.yaml | 1 - ...ogle_2011_cpu_p99_instant_recommended.yaml | 1 - .../experiments/experiment_utils/config.py | 14 ++- asap-tools/experiments/generate_workload.py | 2 +- .../recommended_sketch_configs.py | 2 +- benchmarks/config/controller-config.yaml | 1 - .../operations/try-asap-planner-promql.md | 8 +- .../operations/try-asap-planner-sql.md | 9 +- promql-compliance/runner/run.go | 3 +- tools/run_metrics_observability_benchmark.py | 2 +- 64 files changed, 132 insertions(+), 130 deletions(-) diff --git a/asap-planner-rs/src/bin/candidate_gen_dump.rs b/asap-planner-rs/src/bin/candidate_gen_dump.rs index c8b07bef..80eb59c4 100644 --- a/asap-planner-rs/src/bin/candidate_gen_dump.rs +++ b/asap-planner-rs/src/bin/candidate_gen_dump.rs @@ -61,7 +61,7 @@ fn main() -> anyhow::Result<()> { query_string: q.clone(), t_repeat_ms: qg.repetition_delay_ms, accuracy_sla: qg.controller_options.accuracy_sla, - latency_sla: qg.controller_options.latency_sla, + latency_sla_ms: qg.controller_options.latency_sla_ms, }) }) .collect(); @@ -71,13 +71,13 @@ fn main() -> anyhow::Result<()> { for (i, aqe) in aqes.iter().enumerate() { println!( - "\n--- Item #{i}: metric={} stat={:?} range={}ms T={}ms accuracy_sla={} latency_sla={} freq={:.4}Hz ---", + "\n--- Item #{i}: metric={} stat={:?} range={}ms T={}ms accuracy_sla={} latency_sla_ms={:?} freq={:.4}Hz ---", aqe.requirements.metric, aqe.requirements.statistics, aqe.requirements.data_range_ms, aqe.t_repeat_ms, aqe.accuracy_sla, - aqe.latency_sla, + aqe.latency_sla_ms, aqe.query_frequency_hz, ); println!(" queries: {:?}", aqe.query_strings); diff --git a/asap-planner-rs/src/config/input.rs b/asap-planner-rs/src/config/input.rs index 8e260323..aef2fef9 100644 --- a/asap-planner-rs/src/config/input.rs +++ b/asap-planner-rs/src/config/input.rs @@ -32,16 +32,16 @@ pub struct ControllerConfig { } impl ControllerConfig { - /// Warn if any query group has both SLAs at 0.0 (the serde Default), - /// which indicates `controller_options` was omitted from the config. + /// Warn if any query group still has the serde-default SLAs, which + /// indicates `controller_options` was omitted from the config. pub fn warn_default_slas(&self) { for qg in &self.query_groups { let opts = &qg.controller_options; - if opts.accuracy_sla == 0.0 && opts.latency_sla == 0.0 { + if opts.accuracy_sla == 0.0 && opts.latency_sla_ms.is_none() { warn!( query_group_id = ?qg.id, "controller_options not set in query group; \ - accuracy_sla=0.0 and latency_sla=0.0 will be used — \ + accuracy_sla=0.0 and no latency_sla_ms limit will be used — \ add controller_options to your config" ); } @@ -79,11 +79,13 @@ pub struct QueryGroup { } #[derive(Debug, Clone, Deserialize, Default)] +#[serde(deny_unknown_fields)] pub struct ControllerOptions { #[serde(deserialize_with = "deserialize_finite_f64")] pub accuracy_sla: f64, - #[serde(deserialize_with = "deserialize_finite_f64")] - pub latency_sla: f64, + /// Maximum modeled query latency in milliseconds; `None` means no limit. + #[serde(default, deserialize_with = "deserialize_optional_positive_f64")] + pub latency_sla_ms: Option, } fn deserialize_finite_f64<'de, D>(deserializer: D) -> Result @@ -98,6 +100,18 @@ where } } +fn deserialize_optional_positive_f64<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + match Option::::deserialize(deserializer)? { + Some(value) if !(value.is_finite() && value > 0.0) => Err(serde::de::Error::custom( + "must be a finite number greater than zero", + )), + value => Ok(value), + } +} + fn deserialize_positive_u64<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -265,7 +279,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: .nan - latency_sla: .inf "#; let error = serde_yaml::from_str::(yaml) @@ -283,13 +296,73 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 + latency_sla_ms: 250.0 "#; let config: ControllerConfig = serde_yaml::from_str(yaml).unwrap(); let options = &config.query_groups[0].controller_options; assert_eq!(options.accuracy_sla, 0.99); - assert_eq!(options.latency_sla, 1.0); + assert_eq!(options.latency_sla_ms, Some(250.0)); + } + + #[test] + fn omitted_latency_sla_ms_means_no_limit() { + let yaml = r#" +query_groups: + - queries: [sum(metric)] + repetition_delay_ms: 60000 + controller_options: + accuracy_sla: 0.99 +"#; + + let config: ControllerConfig = serde_yaml::from_str(yaml).unwrap(); + assert_eq!( + config.query_groups[0].controller_options.latency_sla_ms, + None + ); + } + + // The unitless `latency_sla` key was never enforced; reject it so stale + // configs fail loudly instead of silently losing their latency limit. + #[test] + fn rejects_legacy_latency_sla_key() { + let yaml = r#" +query_groups: + - queries: [sum(metric)] + repetition_delay_ms: 60000 + controller_options: + accuracy_sla: 0.99 + latency_sla: 1.0 +"#; + + let error = serde_yaml::from_str::(yaml) + .expect_err("legacy latency_sla key must be rejected") + .to_string(); + assert!(error.contains("unknown field `latency_sla`"), "{error}"); + } + + #[test] + fn rejects_non_positive_or_non_finite_latency_sla_ms() { + for bad in ["0.0", "-5.0", ".inf", ".nan"] { + let yaml = format!( + r#" +query_groups: + - queries: [sum(metric)] + repetition_delay_ms: 60000 + controller_options: + accuracy_sla: 0.99 + latency_sla_ms: {bad} +"# + ); + + let error = serde_yaml::from_str::(&yaml) + .expect_err("invalid latency_sla_ms must be rejected") + .to_string(); + assert!( + error.contains("must be a finite number greater than zero"), + "{bad}: {error}" + ); + } } #[test] diff --git a/asap-planner-rs/src/optimizer/aqe_extractor.rs b/asap-planner-rs/src/optimizer/aqe_extractor.rs index 15ed2064..fb532294 100644 --- a/asap-planner-rs/src/optimizer/aqe_extractor.rs +++ b/asap-planner-rs/src/optimizer/aqe_extractor.rs @@ -20,7 +20,7 @@ pub struct RQE { pub query_string: String, pub t_repeat_ms: u64, pub accuracy_sla: f64, - pub latency_sla: f64, + pub latency_sla_ms: Option, } /// Stable key for merging identical optimizer demand. @@ -36,7 +36,7 @@ struct OptimizerItemKey { topk_by_labels: Option, t_repeat_ms: u64, accuracy_sla_bits: u64, - latency_sla_bits: u64, + latency_sla_ms_bits: Option, } impl OptimizerItemKey { @@ -51,7 +51,7 @@ impl OptimizerItemKey { topk_by_labels: req.topk_by_labels.clone(), t_repeat_ms: rqe.t_repeat_ms, accuracy_sla_bits: normalized_f64_bits(rqe.accuracy_sla), - latency_sla_bits: normalized_f64_bits(rqe.latency_sla), + latency_sla_ms_bits: rqe.latency_sla_ms.map(normalized_f64_bits), } } } @@ -110,7 +110,7 @@ pub fn extract_aqes( query_frequency_hz, t_repeat_ms: key.t_repeat_ms, accuracy_sla: f64::from_bits(key.accuracy_sla_bits), - latency_sla: f64::from_bits(key.latency_sla_bits), + latency_sla_ms: key.latency_sla_ms_bits.map(f64::from_bits), }, ) .collect()) @@ -236,7 +236,7 @@ mod tests { query_string: query.to_string(), t_repeat_ms: t_ms, accuracy_sla: 0.0, - latency_sla: 0.0, + latency_sla_ms: None, } } @@ -312,7 +312,7 @@ mod tests { #[test] fn signed_zero_slas_merge_into_one_item() { let mut negative_zero = rqe("sum_over_time(metric[5m])", 60_000); - negative_zero.latency_sla = -0.0; + negative_zero.accuracy_sla = -0.0; let items = extract_aqes( &[negative_zero, rqe("sum_over_time(metric[5m])", 60_000)], &empty_schema(), diff --git a/asap-planner-rs/src/optimizer/candidate_gen.rs b/asap-planner-rs/src/optimizer/candidate_gen.rs index 53e46223..b3aa0f88 100644 --- a/asap-planner-rs/src/optimizer/candidate_gen.rs +++ b/asap-planner-rs/src/optimizer/candidate_gen.rs @@ -408,7 +408,7 @@ mod tests { query_frequency_hz: 1.0 / 60.0, t_repeat_ms: min_t, accuracy_sla: 0.0, - latency_sla: 0.0, + latency_sla_ms: None, } } diff --git a/asap-planner-rs/src/optimizer/cost_model.rs b/asap-planner-rs/src/optimizer/cost_model.rs index f663bb70..fe9b0f15 100644 --- a/asap-planner-rs/src/optimizer/cost_model.rs +++ b/asap-planner-rs/src/optimizer/cost_model.rs @@ -216,7 +216,7 @@ mod tests { query_frequency_hz: 1.0 / 60.0, t_repeat_ms: min_t, accuracy_sla: 0.0, - latency_sla: 0.0, + latency_sla_ms: None, } } diff --git a/asap-planner-rs/src/optimizer/error.rs b/asap-planner-rs/src/optimizer/error.rs index 9269c5c7..da7933b5 100644 --- a/asap-planner-rs/src/optimizer/error.rs +++ b/asap-planner-rs/src/optimizer/error.rs @@ -24,6 +24,6 @@ pub struct UnservableItem { pub data_range_ms: u64, pub t_repeat_ms: u64, pub accuracy_sla: f64, - pub latency_sla: f64, + pub latency_sla_ms: Option, pub reason: String, } diff --git a/asap-planner-rs/src/optimizer/greedy.rs b/asap-planner-rs/src/optimizer/greedy.rs index dff2b44c..51ab0f8e 100644 --- a/asap-planner-rs/src/optimizer/greedy.rs +++ b/asap-planner-rs/src/optimizer/greedy.rs @@ -66,7 +66,7 @@ pub fn greedy_assign( data_range_ms: aqe.requirements.data_range_ms, t_repeat_ms: aqe.t_repeat_ms, accuracy_sla: aqe.accuracy_sla, - latency_sla: aqe.latency_sla, + latency_sla_ms: aqe.latency_sla_ms, reason: "no candidate remained after structural and atomic-cost filters".into(), }); continue; @@ -139,7 +139,7 @@ mod tests { query_frequency_hz: freq_hz, t_repeat_ms: min_t, accuracy_sla: 0.0, - latency_sla: 0.0, + latency_sla_ms: None, } } @@ -196,7 +196,7 @@ mod tests { query_frequency_hz: 1.0 / 60.0, t_repeat_ms: 60_000, accuracy_sla: 0.0, - latency_sla: 0.0, + latency_sla_ms: None, }; let error = greedy_assign( vec![aqe.clone()], diff --git a/asap-planner-rs/src/optimizer/label_set_facts.rs b/asap-planner-rs/src/optimizer/label_set_facts.rs index d268b535..418899fd 100644 --- a/asap-planner-rs/src/optimizer/label_set_facts.rs +++ b/asap-planner-rs/src/optimizer/label_set_facts.rs @@ -308,7 +308,7 @@ mod tests { query_frequency_hz: 1.0 / 60.0, t_repeat_ms: 60_000, accuracy_sla: 0.0, - latency_sla: 0.0, + latency_sla_ms: None, } } diff --git a/asap-planner-rs/src/optimizer/pipeline.rs b/asap-planner-rs/src/optimizer/pipeline.rs index cc40dfc6..8a817d68 100644 --- a/asap-planner-rs/src/optimizer/pipeline.rs +++ b/asap-planner-rs/src/optimizer/pipeline.rs @@ -104,7 +104,7 @@ fn config_to_rqes(config: &ControllerConfig) -> Vec { query_string: q.clone(), t_repeat_ms: qg.repetition_delay_ms, accuracy_sla: qg.controller_options.accuracy_sla, - latency_sla: qg.controller_options.latency_sla, + latency_sla_ms: qg.controller_options.latency_sla_ms, }) }) .collect() diff --git a/asap-planner-rs/src/optimizer/solution.rs b/asap-planner-rs/src/optimizer/solution.rs index ba866faf..2dfa9930 100644 --- a/asap-planner-rs/src/optimizer/solution.rs +++ b/asap-planner-rs/src/optimizer/solution.rs @@ -26,8 +26,9 @@ pub struct OptimizerItem { /// Required accuracy for every RQE contributing to this item. pub accuracy_sla: f64, - /// Required query latency for every RQE contributing to this item. - pub latency_sla: f64, + /// Maximum query latency (ms) for every RQE contributing to this item; + /// `None` means no limit. + pub latency_sla_ms: Option, } /// How an optimizer item is answered from its assigned streaming config. diff --git a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic.yaml b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic.yaml index 30d55df0..2d1b0c7a 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic.yaml @@ -5,7 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 metrics: - metric: "errors_total" labels: ["instance", "job"] diff --git a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_dedup.yaml b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_dedup.yaml index 18b8fd4d..bc84afcf 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_dedup.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_dedup.yaml @@ -6,7 +6,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 metrics: - metric: "errors_total" labels: ["instance", "job"] diff --git a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_nested.yaml b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_nested.yaml index 879d918a..a5b86496 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_nested.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_nested.yaml @@ -5,7 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 metrics: - metric: "a_total" labels: ["instance"] diff --git a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_non_acceleratable.yaml b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_non_acceleratable.yaml index 2542bb7f..f02f8e2b 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_non_acceleratable.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_non_acceleratable.yaml @@ -5,7 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 metrics: - metric: "errors_total" labels: ["instance"] diff --git a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_scalar.yaml b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_scalar.yaml index 63d2e22b..c754560a 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_scalar.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_scalar.yaml @@ -5,7 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 metrics: - metric: "errors_total" labels: ["instance", "job"] diff --git a/asap-planner-rs/tests/comparison/test_data/configs/cleanup_circular.yaml b/asap-planner-rs/tests/comparison/test_data/configs/cleanup_circular.yaml index 6e53ddac..c4f5e5d4 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/cleanup_circular.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/cleanup_circular.yaml @@ -5,6 +5,5 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "circular_buffer" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/cleanup_read_based.yaml b/asap-planner-rs/tests/comparison/test_data/configs/cleanup_read_based.yaml index 96637d51..dc842064 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/cleanup_read_based.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/cleanup_read_based.yaml @@ -5,6 +5,5 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/deduplicated.yaml b/asap-planner-rs/tests/comparison/test_data/configs/deduplicated.yaml index 0e8017b0..d61f6664 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/deduplicated.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/deduplicated.yaml @@ -7,13 +7,11 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 - id: 2 queries: - "increase(http_requests_total[5m])" repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/increase.yaml b/asap-planner-rs/tests/comparison/test_data/configs/increase.yaml index 38d23e94..d424015d 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/increase.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/increase.yaml @@ -5,6 +5,5 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/mixed_workload.yaml b/asap-planner-rs/tests/comparison/test_data/configs/mixed_workload.yaml index 79d11262..51c32415 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/mixed_workload.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/mixed_workload.yaml @@ -6,6 +6,5 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/quantile_over_time.yaml b/asap-planner-rs/tests/comparison/test_data/configs/quantile_over_time.yaml index a5f4c1b9..55aef2f2 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/quantile_over_time.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/quantile_over_time.yaml @@ -5,6 +5,5 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/range_query.yaml b/asap-planner-rs/tests/comparison/test_data/configs/range_query.yaml index 96637d51..dc842064 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/range_query.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/range_query.yaml @@ -5,6 +5,5 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/rate_increase.yaml b/asap-planner-rs/tests/comparison/test_data/configs/rate_increase.yaml index 96637d51..dc842064 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/rate_increase.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/rate_increase.yaml @@ -5,6 +5,5 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/spatial_quantile.yaml b/asap-planner-rs/tests/comparison/test_data/configs/spatial_quantile.yaml index 4e2ba500..b34337bc 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/spatial_quantile.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/spatial_quantile.yaml @@ -5,6 +5,5 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/sum_by.yaml b/asap-planner-rs/tests/comparison/test_data/configs/sum_by.yaml index ad8aaf50..f61a9857 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/sum_by.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/sum_by.yaml @@ -5,6 +5,5 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/sum_by_overlapping.yaml b/asap-planner-rs/tests/comparison/test_data/configs/sum_by_overlapping.yaml index 9a9b57bd..251ad5f7 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/sum_by_overlapping.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/sum_by_overlapping.yaml @@ -5,6 +5,5 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/sum_over_time.yaml b/asap-planner-rs/tests/comparison/test_data/configs/sum_over_time.yaml index 8e0eee95..62cd574f 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/sum_over_time.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/sum_over_time.yaml @@ -5,6 +5,5 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/temporal_overlapping.yaml b/asap-planner-rs/tests/comparison/test_data/configs/temporal_overlapping.yaml index 23017f48..f8a3f025 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/temporal_overlapping.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/temporal_overlapping.yaml @@ -8,6 +8,5 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/topk.yaml b/asap-planner-rs/tests/comparison/test_data/configs/topk.yaml index 7ab4b3cb..04b336c8 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/topk.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/topk.yaml @@ -5,6 +5,5 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/elastic_dsl_integration.rs b/asap-planner-rs/tests/elastic_dsl_integration.rs index 4d143893..29db8dfa 100644 --- a/asap-planner-rs/tests/elastic_dsl_integration.rs +++ b/asap-planner-rs/tests/elastic_dsl_integration.rs @@ -28,7 +28,6 @@ query_groups: repetition_delay_ms: {t_repeat_ms} controller_options: accuracy_sla: 0.95 - latency_sla: 1.0 aggregate_cleanup: policy: read_based "#, @@ -390,7 +389,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 1.0 - id: 2 index: other_metrics time_field: "timestamp" @@ -429,7 +427,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 1.0 aggregate_cleanup: policy: read_based "#; diff --git a/asap-planner-rs/tests/elastic_example.yaml b/asap-planner-rs/tests/elastic_example.yaml index 66014c45..2f2b5d1d 100644 --- a/asap-planner-rs/tests/elastic_example.yaml +++ b/asap-planner-rs/tests/elastic_example.yaml @@ -30,6 +30,5 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 1.0 aggregate_cleanup: policy: read_based diff --git a/asap-planner-rs/tests/integration.rs b/asap-planner-rs/tests/integration.rs index 1c8e3aea..b6749b25 100644 --- a/asap-planner-rs/tests/integration.rs +++ b/asap-planner-rs/tests/integration.rs @@ -125,14 +125,12 @@ query_groups: repetition_delay_ms: 65000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 - id: 2 queries: - "rate(http_requests_total[55s])" repetition_delay_ms: 55000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#, http_requests_schema(), default_opts(), @@ -165,7 +163,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#, http_requests_schema(), default_opts(), @@ -241,7 +238,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#, http_requests_schema(), default_opts(), @@ -278,7 +274,6 @@ query_groups: step_ms: 80000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#, http_requests_schema(), default_opts(), @@ -306,7 +301,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#, http_requests_schema(), default_opts(), @@ -680,7 +674,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#, http_requests_schema(), default_opts(), @@ -731,7 +724,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#, http_requests_schema(), default_opts(), @@ -905,7 +897,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "not_a_real_policy" "#; @@ -928,7 +919,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#; let c = Controller::from_yaml_with_schema(yaml, http_requests_schema(), default_opts()).unwrap(); @@ -948,14 +938,12 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 - id: 2 queries: - "rate(http_requests_total[5m])" repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#; let c = Controller::from_yaml_with_schema(yaml, http_requests_schema(), default_opts()).unwrap(); @@ -976,7 +964,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#; // Schema only knows about http_requests_total, not unknown_metric. let c = @@ -1284,14 +1271,12 @@ query_groups: repetition_delay_ms: 65000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 - id: 2 queries: - "rate(errors_total[55s]) / rate(requests_total[55s])" repetition_delay_ms: 55000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#, binary_arithmetic_schema(), default_opts(), @@ -1326,7 +1311,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "#, binary_arithmetic_schema(), default_opts(), diff --git a/asap-planner-rs/tests/sql_integration.rs b/asap-planner-rs/tests/sql_integration.rs index 0e9aa364..b9722596 100644 --- a/asap-planner-rs/tests/sql_integration.rs +++ b/asap-planner-rs/tests/sql_integration.rs @@ -85,7 +85,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - "{query}" aggregate_cleanup: @@ -123,7 +122,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - "{query}" aggregate_cleanup: @@ -192,7 +190,6 @@ query_groups: repetition_delay_ms: {t_repeat_ms} controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- {query} @@ -642,7 +639,6 @@ query_groups: repetition_delay_ms: {t_repeat_ms} controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- {query} @@ -771,7 +767,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- SELECT MIN(cpu_usage) FROM metrics_table WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY datacenter @@ -779,7 +774,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- SELECT MAX(cpu_usage) FROM metrics_table WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY datacenter @@ -812,7 +806,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- SELECT SUM(cpu_usage) FROM metrics_table WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY datacenter @@ -846,7 +839,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- {q} @@ -854,7 +846,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- {q} @@ -883,7 +874,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- SELECT SUM(cpu_usage) FROM metrics_table WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY datacenter @@ -891,7 +881,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- SELECT SUM(cpu_usage) FROM metrics_table WHERE time BETWEEN DATEADD(s, -600, NOW()) AND NOW() GROUP BY datacenter @@ -975,7 +964,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- {q} @@ -1006,7 +994,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- {q} diff --git a/asap-planner-rs/tests/test_data/windowing/promql_sliding.yaml b/asap-planner-rs/tests/test_data/windowing/promql_sliding.yaml index ad1093cf..b4d1b1fa 100644 --- a/asap-planner-rs/tests/test_data/windowing/promql_sliding.yaml +++ b/asap-planner-rs/tests/test_data/windowing/promql_sliding.yaml @@ -9,13 +9,11 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 - id: 2 queries: - "rate(http_requests_total[2m])" repetition_delay_ms: 120000 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/test_data/windowing/sql_sliding.yaml b/asap-planner-rs/tests/test_data/windowing/sql_sliding.yaml index acf8a142..f157ebd8 100644 --- a/asap-planner-rs/tests/test_data/windowing/sql_sliding.yaml +++ b/asap-planner-rs/tests/test_data/windowing/sql_sliding.yaml @@ -12,7 +12,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- SELECT MIN(cpu_usage) FROM metrics_table @@ -22,7 +21,6 @@ query_groups: repetition_delay_ms: 120000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- SELECT MIN(cpu_usage) FROM metrics_table diff --git a/asap-planner-rs/tests/test_data/windowing/sql_sliding_invalid.yaml b/asap-planner-rs/tests/test_data/windowing/sql_sliding_invalid.yaml index 91af6af8..243a8cd7 100644 --- a/asap-planner-rs/tests/test_data/windowing/sql_sliding_invalid.yaml +++ b/asap-planner-rs/tests/test_data/windowing/sql_sliding_invalid.yaml @@ -12,7 +12,6 @@ query_groups: repetition_delay_ms: 75000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- SELECT MIN(cpu_usage) FROM metrics_table @@ -22,7 +21,6 @@ query_groups: repetition_delay_ms: 90000 controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- SELECT MIN(cpu_usage) FROM metrics_table diff --git a/asap-query-engine/tests/e2e_precompute_equivalence.rs b/asap-query-engine/tests/e2e_precompute_equivalence.rs index 5d6592a5..fd016a6a 100644 --- a/asap-query-engine/tests/e2e_precompute_equivalence.rs +++ b/asap-query-engine/tests/e2e_precompute_equivalence.rs @@ -175,7 +175,6 @@ query_groups: repetition_delay_ms: {interval_ms} controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 "# ); let planner = Controller::from_yaml_with_schema( diff --git a/asap-quickstart/config/controller-config.yaml b/asap-quickstart/config/controller-config.yaml index cacd044f..ab459da2 100644 --- a/asap-quickstart/config/controller-config.yaml +++ b/asap-quickstart/config/controller-config.yaml @@ -12,7 +12,6 @@ query_groups: repetition_delay: 10 controller_options: accuracy_sla: 0.99 - latency_sla: 1 # Metric metadata - includes the 'pattern' label metrics: diff --git a/asap-tools/docs/architecture.md b/asap-tools/docs/architecture.md index bada0fe1..906ef7d1 100644 --- a/asap-tools/docs/architecture.md +++ b/asap-tools/docs/architecture.md @@ -763,7 +763,6 @@ query_groups: query_time_offset: 0 controller_options: accuracy_sla: 0.99 - latency_sla: 1.0 servers: - name: prometheus diff --git a/asap-tools/docs/configuration.md b/asap-tools/docs/configuration.md index f9f07fb3..04cd58dc 100644 --- a/asap-tools/docs/configuration.md +++ b/asap-tools/docs/configuration.md @@ -757,7 +757,7 @@ The framework validates configurations at runtime using `experiment_utils/config - `client_options.repetitions`: Number of repetitions - `client_options.starting_delay`: Warmup period - `controller_options.accuracy_sla`: Accuracy threshold - - `controller_options.latency_sla`: Latency threshold + - `controller_options.latency_sla_ms` (optional): Maximum modeled query latency in milliseconds; omit for no limit 2. **exporters** - Must have: - `exporter_list`: Dictionary of exporter configs diff --git a/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md b/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md index 46fa9a93..a1ae51bc 100644 --- a/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md +++ b/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md @@ -513,12 +513,12 @@ These parameters come from the `experiment_type` config group and are prefixed w - **Example**: `0.95` - **Usage**: Quality assurance for approximate query results -#### `experiment_params.query_groups[].controller_options.latency_sla` (float, optional) -- **Description**: Latency SLA in seconds -- **Default**: `1` -- **Range**: 0.1-60.0 seconds -- **Example**: `2` -- **Usage**: Performance requirement for query response time +#### `experiment_params.query_groups[].controller_options.latency_sla_ms` (float, optional) +- **Description**: Maximum modeled query latency in milliseconds +- **Default**: omitted (no latency limit) +- **Range**: finite and > 0 +- **Example**: `250` +- **Usage**: Hard ceiling on query latency for the planner ### Metrics Configuration diff --git a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2021.yaml b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2021.yaml index ea38e1dd..6cf35ba8 100644 --- a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2021.yaml +++ b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2021.yaml @@ -49,7 +49,6 @@ query_groups: starting_delay: 70 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: "alibaba_microservice_cpu_usage" diff --git a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2022.yaml b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2022.yaml index 2a1be88a..3d13fd21 100644 --- a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2022.yaml +++ b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2022.yaml @@ -49,7 +49,6 @@ query_groups: starting_delay: 70 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: "alibaba_microservice_cpu_usage" diff --git a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2021.yaml b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2021.yaml index e4311124..99d32fbe 100644 --- a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2021.yaml +++ b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2021.yaml @@ -60,7 +60,6 @@ query_groups: starting_delay: 70 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: "alibaba_node_cpu_usage" diff --git a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2022.yaml b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2022.yaml index c6f644bf..42911b88 100644 --- a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2022.yaml +++ b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2022.yaml @@ -52,7 +52,6 @@ query_groups: starting_delay: 70 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: "alibaba_node_cpu_usage" diff --git a/asap-tools/experiments/config/experiment_type/cluster_data_google.yaml b/asap-tools/experiments/config/experiment_type/cluster_data_google.yaml index 70436d2d..7c2942b2 100644 --- a/asap-tools/experiments/config/experiment_type/cluster_data_google.yaml +++ b/asap-tools/experiments/config/experiment_type/cluster_data_google.yaml @@ -66,7 +66,6 @@ query_groups: starting_delay: 70 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: # Google metrics with aggregation_type=0 diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_default.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_default.yaml index bd721fc5..5dfd5968 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_default.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_default.yaml @@ -35,7 +35,6 @@ experiment_params: starting_delay: 390 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: alibaba_microservice_cpu_usage labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_recommended.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_recommended.yaml index 593b834c..005f51e4 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_recommended.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_recommended.yaml @@ -35,7 +35,6 @@ experiment_params: starting_delay: 390 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: alibaba_microservice_cpu_usage labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_default.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_default.yaml index 6f54463e..a1425e93 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_default.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_default.yaml @@ -35,7 +35,6 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: alibaba_microservice_cpu_usage labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_recommended.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_recommended.yaml index dac39e20..8ad6b078 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_recommended.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_recommended.yaml @@ -35,7 +35,6 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: alibaba_microservice_cpu_usage labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_default.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_default.yaml index 9a163036..f83f1a69 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_default.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_default.yaml @@ -34,7 +34,6 @@ experiment_params: starting_delay: 390 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_recommended.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_recommended.yaml index 0f815477..bff8c5c4 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_recommended.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_recommended.yaml @@ -34,7 +34,6 @@ experiment_params: starting_delay: 390 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_default.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_default.yaml index d68ab47c..09ec1088 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_default.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_default.yaml @@ -34,7 +34,6 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_recommended.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_recommended.yaml index c6fd091c..155df666 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_recommended.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_recommended.yaml @@ -34,7 +34,6 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_default.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_default.yaml index 3be876db..266b1d91 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_default.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_default.yaml @@ -34,7 +34,6 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_recommended.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_recommended.yaml index e26d8cd7..52f5603a 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_recommended.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_recommended.yaml @@ -34,7 +34,6 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 - latency_sla: 1 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/experiment_utils/config.py b/asap-tools/experiments/experiment_utils/config.py index 6828bd6c..f73f92ee 100644 --- a/asap-tools/experiments/experiment_utils/config.py +++ b/asap-tools/experiments/experiment_utils/config.py @@ -853,7 +853,8 @@ def generate_sql_planner_input( Args: query_groups: ListConfig of query group dicts. Each entry must have ``sql_file``, ``repetition_delay_ms``, and - ``controller_options`` (``accuracy_sla``, ``latency_sla``). + ``controller_options`` (``accuracy_sla``, optional + ``latency_sla_ms``). dataset_cfg: DictConfig with ``table``/``name``, and ``precompute`` sub-config (``timestamp_col``, ``value_col``, ``label_cols``). sketch_parameters: Optional DictConfig/dict mirroring ``config.yaml``'s @@ -901,15 +902,18 @@ def generate_sql_planner_input( raise ValueError(f"No SQL statements found in {sql_file!r}") ctrl_opts = dict(group.get("controller_options") or {}) + planner_ctrl_opts = { + "accuracy_sla": float(ctrl_opts.get("accuracy_sla", 0.95)), + } + # Omitted latency_sla_ms means no latency limit in the planner. + if ctrl_opts.get("latency_sla_ms") is not None: + planner_ctrl_opts["latency_sla_ms"] = float(ctrl_opts["latency_sla_ms"]) planner_query_groups.append( { "id": idx + 1, "repetition_delay_ms": int(group.get("repetition_delay_ms", 0)), "queries": queries, - "controller_options": { - "accuracy_sla": float(ctrl_opts.get("accuracy_sla", 0.95)), - "latency_sla": float(ctrl_opts.get("latency_sla", 100.0)), - }, + "controller_options": planner_ctrl_opts, } ) diff --git a/asap-tools/experiments/generate_workload.py b/asap-tools/experiments/generate_workload.py index ac79d02e..2b855d78 100644 --- a/asap-tools/experiments/generate_workload.py +++ b/asap-tools/experiments/generate_workload.py @@ -433,7 +433,7 @@ def get_base_config() -> Dict: "query_time_offset": 10, "starting_delay": 60, }, - "controller_options": {"accuracy_sla": 0.99, "latency_sla": 1}, + "controller_options": {"accuracy_sla": 0.99}, } ], "metrics": [ diff --git a/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py b/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py index a0b104e6..9cd15516 100644 --- a/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py +++ b/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py @@ -238,7 +238,7 @@ def build_experiment_config( "query_time_offset": 10, "starting_delay": starting_delay, }, - "controller_options": {"accuracy_sla": 0.99, "latency_sla": 1}, + "controller_options": {"accuracy_sla": 0.99}, } ], "metrics": [ diff --git a/benchmarks/config/controller-config.yaml b/benchmarks/config/controller-config.yaml index 444be132..00483bdc 100644 --- a/benchmarks/config/controller-config.yaml +++ b/benchmarks/config/controller-config.yaml @@ -12,7 +12,6 @@ query_groups: repetition_delay_ms: 10000 controller_options: accuracy_sla: 0.99 - latency_sla: 1 # Metric metadata - includes the 'pattern' label metrics: diff --git a/docs/03-how-to-guides/operations/try-asap-planner-promql.md b/docs/03-how-to-guides/operations/try-asap-planner-promql.md index fec12012..09ce421e 100644 --- a/docs/03-how-to-guides/operations/try-asap-planner-promql.md +++ b/docs/03-how-to-guides/operations/try-asap-planner-promql.md @@ -23,7 +23,6 @@ query_groups: repetition_delay_ms: 300000 # ms between repeats of this query controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - "sum by (job) (rate(http_requests_total[5m]))" aggregate_cleanup: @@ -43,8 +42,11 @@ auto-infer label sets per metric. ### `controller_options` -`accuracy_sla` and `latency_sla` are required by the config schema but not currently used by -the planner's decision logic — any numeric values are fine (e.g. the placeholders above). +`accuracy_sla` is required by the config schema but not currently used by the planner's +decision logic — any numeric value is fine (e.g. the placeholder above). + +`latency_sla_ms` is optional: the maximum modeled query latency in milliseconds (must be +finite and > 0). Omit it for no latency limit. ### Choosing `repetition_delay_ms` and `--data-ingestion-interval-ms` diff --git a/docs/03-how-to-guides/operations/try-asap-planner-sql.md b/docs/03-how-to-guides/operations/try-asap-planner-sql.md index cdb39838..f7ac6092 100644 --- a/docs/03-how-to-guides/operations/try-asap-planner-sql.md +++ b/docs/03-how-to-guides/operations/try-asap-planner-sql.md @@ -25,7 +25,6 @@ query_groups: repetition_delay: 300 # seconds between repeats of this query controller_options: accuracy_sla: 0.95 - latency_sla: 100.0 queries: - >- SELECT avg(cpu_usage) FROM metrics_table @@ -46,9 +45,11 @@ For each table: ### `controller_options` -`accuracy_sla` and `latency_sla` are required by the config schema but not currently used by -the planner's decision logic — any numeric values are fine (e.g. the placeholders in the -example above). +`accuracy_sla` is required by the config schema but not currently used by the planner's +decision logic — any numeric value is fine (e.g. the placeholder in the example above). + +`latency_sla_ms` is optional: the maximum modeled query latency in milliseconds (must be +finite and > 0). Omit it for no latency limit. ### Choosing `repetition_delay` and `--data-ingestion-interval` diff --git a/promql-compliance/runner/run.go b/promql-compliance/runner/run.go index d4aebfbc..2b8b7a36 100644 --- a/promql-compliance/runner/run.go +++ b/promql-compliance/runner/run.go @@ -333,7 +333,6 @@ type plannerQueryGroup struct { type plannerController struct { AccuracySLA float64 `yaml:"accuracy_sla"` - LatencySLA float64 `yaml:"latency_sla"` } type plannerMetric struct { @@ -377,7 +376,7 @@ func writeGeneratedConfigs(directory string, fixture seeder.Fixture, suite Suite } group := plannerQueryGroup{ ID: index + 1, Queries: []string{query.Expr}, RepetitionDelayMS: repetitionDelayMS, - ControllerOptions: plannerController{AccuracySLA: 0.99, LatencySLA: 1}, + ControllerOptions: plannerController{AccuracySLA: 0.99}, } if query.Range != nil { stepMS := int(query.Range.StepSeconds * float64(time.Second/time.Millisecond)) diff --git a/tools/run_metrics_observability_benchmark.py b/tools/run_metrics_observability_benchmark.py index 4cbcb2be..056c962e 100644 --- a/tools/run_metrics_observability_benchmark.py +++ b/tools/run_metrics_observability_benchmark.py @@ -165,7 +165,7 @@ def make_workload(queries, path, scrape_ms, repeat_ms): { "id": 1, "repetition_delay_ms": repeat_ms, - "controller_options": {"accuracy_sla": 0.95, "latency_sla": 100.0}, + "controller_options": {"accuracy_sla": 0.95}, "queries": [ entry["query"] for entry in queries From 0d3f0a8760fe9d547d5ef23eca23c9465d719a3f Mon Sep 17 00:00:00 2001 From: Milind Srivastava Date: Tue, 6 Oct 2026 17:34:26 -0400 Subject: [PATCH 2/4] fix(planner): reject unknown query group and controller option keys - `QueryGroup` denies unknown fields, so a misspelled `controller_options` fails instead of silently falling back to default SLAs. - asap-tools strips only `client_options` from query groups for the planner input and rejects unknown SQL `controller_options` keys, so a stale `latency_sla` reaches an error instead of being dropped. - Test that differing `latency_sla_ms` values stay distinct items. - Docs note that `latency_sla_ms` is not enforced yet. Co-Authored-By: Claude Opus 5.5 --- asap-planner-rs/src/config/input.rs | 21 +++++++++++ .../src/optimizer/aqe_extractor.rs | 14 ++++++++ asap-tools/docs/configuration.md | 2 +- .../CONFIG_PARAMETERS_REFERENCE.md | 2 +- .../experiments/experiment_utils/config.py | 19 +++++++++- .../tests/test_sql_planner_input.py | 36 +++++++++++++++++++ .../operations/try-asap-planner-promql.md | 2 +- .../operations/try-asap-planner-sql.md | 2 +- 8 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 asap-tools/experiments/tests/test_sql_planner_input.py diff --git a/asap-planner-rs/src/config/input.rs b/asap-planner-rs/src/config/input.rs index aef2fef9..7f63b10a 100644 --- a/asap-planner-rs/src/config/input.rs +++ b/asap-planner-rs/src/config/input.rs @@ -63,6 +63,7 @@ impl ControllerConfig { } #[derive(Debug, Clone, Deserialize)] +#[serde(deny_unknown_fields)] pub struct QueryGroup { pub id: Option, pub queries: Vec, @@ -341,6 +342,26 @@ query_groups: assert!(error.contains("unknown field `latency_sla`"), "{error}"); } + #[test] + fn rejects_misspelled_controller_options() { + // A typo would otherwise drop the whole SLA block to its defaults. + let yaml = r#" +query_groups: + - queries: [sum(metric)] + repetition_delay_ms: 60000 + controler_options: + accuracy_sla: 0.99 +"#; + + let error = serde_yaml::from_str::(yaml) + .expect_err("unknown query group key must be rejected") + .to_string(); + assert!( + error.contains("unknown field `controler_options`"), + "{error}" + ); + } + #[test] fn rejects_non_positive_or_non_finite_latency_sla_ms() { for bad in ["0.0", "-5.0", ".inf", ".nan"] { diff --git a/asap-planner-rs/src/optimizer/aqe_extractor.rs b/asap-planner-rs/src/optimizer/aqe_extractor.rs index fb532294..ac825a38 100644 --- a/asap-planner-rs/src/optimizer/aqe_extractor.rs +++ b/asap-planner-rs/src/optimizer/aqe_extractor.rs @@ -309,6 +309,20 @@ mod tests { assert_eq!(items.len(), 2); } + #[test] + fn different_latency_slas_become_distinct_items() { + let unlimited = rqe("sum_over_time(metric[5m])", 60_000); + let mut fast = rqe("sum_over_time(metric[5m])", 60_000); + fast.latency_sla_ms = Some(100.0); + let mut slow = rqe("sum_over_time(metric[5m])", 60_000); + slow.latency_sla_ms = Some(1_000.0); + + let items = extract_aqes(&[unlimited, fast, slow], &empty_schema(), 15_000).unwrap(); + let mut slas: Vec<_> = items.iter().map(|item| item.latency_sla_ms).collect(); + slas.sort_by(|a, b| a.partial_cmp(b).unwrap()); + assert_eq!(slas, vec![None, Some(100.0), Some(1_000.0)]); + } + #[test] fn signed_zero_slas_merge_into_one_item() { let mut negative_zero = rqe("sum_over_time(metric[5m])", 60_000); diff --git a/asap-tools/docs/configuration.md b/asap-tools/docs/configuration.md index 04cd58dc..ef1163d9 100644 --- a/asap-tools/docs/configuration.md +++ b/asap-tools/docs/configuration.md @@ -757,7 +757,7 @@ The framework validates configurations at runtime using `experiment_utils/config - `client_options.repetitions`: Number of repetitions - `client_options.starting_delay`: Warmup period - `controller_options.accuracy_sla`: Accuracy threshold - - `controller_options.latency_sla_ms` (optional): Maximum modeled query latency in milliseconds; omit for no limit + - `controller_options.latency_sla_ms` (optional): Maximum modeled query latency in milliseconds; omit for no limit. Not yet enforced by the planner 2. **exporters** - Must have: - `exporter_list`: Dictionary of exporter configs diff --git a/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md b/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md index a1ae51bc..35a8afed 100644 --- a/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md +++ b/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md @@ -518,7 +518,7 @@ These parameters come from the `experiment_type` config group and are prefixed w - **Default**: omitted (no latency limit) - **Range**: finite and > 0 - **Example**: `250` -- **Usage**: Hard ceiling on query latency for the planner +- **Usage**: Intended as a hard ceiling on query latency for the planner. Not yet enforced: plans are not rejected for exceeding it. ### Metrics Configuration diff --git a/asap-tools/experiments/experiment_utils/config.py b/asap-tools/experiments/experiment_utils/config.py index f73f92ee..cf436ac3 100644 --- a/asap-tools/experiments/experiment_utils/config.py +++ b/asap-tools/experiments/experiment_utils/config.py @@ -13,6 +13,9 @@ import constants from experiment_utils.providers.factory import create_provider +# Keys the planner's `ControllerOptions` accepts. +CONTROLLER_OPTION_KEYS = {"accuracy_sla", "latency_sla_ms"} + def validate_basic_config( cfg: DictConfig, @@ -412,6 +415,12 @@ def generate_controller_client_configs( controller_only_config = { k: v for k, v in full_config.items() if k in CONTROLLER_ALLOWED_KEYS } + # Only the query client reads `client_options`; any other unknown group + # key reaches the planner and is rejected there. + controller_only_config["query_groups"] = [ + {k: v for k, v in group.items() if k != "client_options"} + for group in controller_only_config.get("query_groups", []) + ] with open( os.path.join( output_dir, "{}_controller_input.yaml".format(experiment_mode["mode"]) @@ -887,6 +896,15 @@ def generate_sql_planner_input( planner_query_groups = [] for idx, group in enumerate(groups_list): + ctrl_opts = dict(group.get("controller_options") or {}) + # Dropping an unknown key here would hide it from the planner's strict parse. + unknown = set(ctrl_opts) - CONTROLLER_OPTION_KEYS + if unknown: + raise ValueError( + f"query_groups[{idx}].controller_options has unknown keys " + f"{sorted(unknown)}; allowed: {sorted(CONTROLLER_OPTION_KEYS)}" + ) + sql_file = group.get("sql_file") if not sql_file: raise ValueError(f"query_groups[{idx}] missing 'sql_file'") @@ -901,7 +919,6 @@ def generate_sql_planner_input( if not queries: raise ValueError(f"No SQL statements found in {sql_file!r}") - ctrl_opts = dict(group.get("controller_options") or {}) planner_ctrl_opts = { "accuracy_sla": float(ctrl_opts.get("accuracy_sla", 0.95)), } diff --git a/asap-tools/experiments/tests/test_sql_planner_input.py b/asap-tools/experiments/tests/test_sql_planner_input.py new file mode 100644 index 00000000..0b6efc70 --- /dev/null +++ b/asap-tools/experiments/tests/test_sql_planner_input.py @@ -0,0 +1,36 @@ +"""Tests for generating the SQL planner input.""" + +import unittest + +from omegaconf import OmegaConf + +from experiment_utils.config import generate_sql_planner_input + + +class ControllerOptionKeysTest(unittest.TestCase): + def test_unknown_controller_option_is_rejected(self): + # A stale `latency_sla` used to be dropped here, so the planner ran + # with no latency limit and never saw the bad key. + groups = [ + { + "sql_file": "unused.sql", + "repetition_delay_ms": 60000, + "controller_options": {"accuracy_sla": 0.99, "latency_sla": 1}, + } + ] + dataset_cfg = OmegaConf.create( + { + "name": "t", + "precompute": { + "timestamp_col": "ts", + "value_col": "v", + "label_cols": ["job"], + }, + } + ) + with self.assertRaisesRegex(ValueError, "latency_sla"): + generate_sql_planner_input(groups, dataset_cfg) + + +if __name__ == "__main__": + unittest.main() diff --git a/docs/03-how-to-guides/operations/try-asap-planner-promql.md b/docs/03-how-to-guides/operations/try-asap-planner-promql.md index 09ce421e..acdad6dc 100644 --- a/docs/03-how-to-guides/operations/try-asap-planner-promql.md +++ b/docs/03-how-to-guides/operations/try-asap-planner-promql.md @@ -46,7 +46,7 @@ auto-infer label sets per metric. decision logic — any numeric value is fine (e.g. the placeholder above). `latency_sla_ms` is optional: the maximum modeled query latency in milliseconds (must be -finite and > 0). Omit it for no latency limit. +finite and > 0). Omit it for no latency limit. The planner does not enforce it yet. ### Choosing `repetition_delay_ms` and `--data-ingestion-interval-ms` diff --git a/docs/03-how-to-guides/operations/try-asap-planner-sql.md b/docs/03-how-to-guides/operations/try-asap-planner-sql.md index f7ac6092..431a49d8 100644 --- a/docs/03-how-to-guides/operations/try-asap-planner-sql.md +++ b/docs/03-how-to-guides/operations/try-asap-planner-sql.md @@ -49,7 +49,7 @@ For each table: decision logic — any numeric value is fine (e.g. the placeholder in the example above). `latency_sla_ms` is optional: the maximum modeled query latency in milliseconds (must be -finite and > 0). Omit it for no latency limit. +finite and > 0). Omit it for no latency limit. The planner does not enforce it yet. ### Choosing `repetition_delay` and `--data-ingestion-interval` From bc80c47e296b4976c4f2fd071f83b071560646a1 Mon Sep 17 00:00:00 2001 From: Milind Srivastava Date: Tue, 6 Oct 2026 17:52:14 -0400 Subject: [PATCH 3/4] chore(planner): set latency_sla_ms: 1000 where latency_sla was removed Configs, generators and the compliance runner that set the old unitless `latency_sla` now set an explicit 1 s `latency_sla_ms` ceiling instead of omitting it. SQL experiment planner input defaults to 1000 ms; an explicit null still means no limit. Co-Authored-By: Claude Opus 5.5 --- .../test_data/configs/binary_arithmetic.yaml | 1 + .../configs/binary_arithmetic_dedup.yaml | 1 + .../configs/binary_arithmetic_nested.yaml | 1 + .../binary_arithmetic_non_acceleratable.yaml | 1 + .../configs/binary_arithmetic_scalar.yaml | 1 + .../test_data/configs/cleanup_circular.yaml | 1 + .../test_data/configs/cleanup_read_based.yaml | 1 + .../test_data/configs/deduplicated.yaml | 2 + .../test_data/configs/increase.yaml | 1 + .../test_data/configs/mixed_workload.yaml | 1 + .../test_data/configs/quantile_over_time.yaml | 1 + .../test_data/configs/range_query.yaml | 1 + .../test_data/configs/rate_increase.yaml | 1 + .../test_data/configs/spatial_quantile.yaml | 1 + .../comparison/test_data/configs/sum_by.yaml | 1 + .../test_data/configs/sum_by_overlapping.yaml | 1 + .../test_data/configs/sum_over_time.yaml | 1 + .../configs/temporal_overlapping.yaml | 1 + .../comparison/test_data/configs/topk.yaml | 1 + .../tests/elastic_dsl_integration.rs | 3 ++ asap-planner-rs/tests/elastic_example.yaml | 1 + asap-planner-rs/tests/integration.rs | 16 ++++++ asap-planner-rs/tests/sql_integration.rs | 13 +++++ .../test_data/windowing/promql_sliding.yaml | 2 + .../test_data/windowing/sql_sliding.yaml | 2 + .../windowing/sql_sliding_invalid.yaml | 2 + .../tests/e2e_precompute_equivalence.rs | 1 + asap-quickstart/config/controller-config.yaml | 1 + asap-tools/docs/architecture.md | 1 + .../CONFIG_PARAMETERS_REFERENCE.md | 2 +- .../cluster_data_alibaba_msresource_2021.yaml | 1 + .../cluster_data_alibaba_msresource_2022.yaml | 1 + .../cluster_data_alibaba_node_2021.yaml | 1 + .../cluster_data_alibaba_node_2022.yaml | 1 + .../experiment_type/cluster_data_google.yaml | 1 + ...aba_v2022_ms_cpu_by_msname_5m_default.yaml | 1 + ...v2022_ms_cpu_by_msname_5m_recommended.yaml | 1 + ...2022_ms_cpu_by_msname_instant_default.yaml | 1 + ..._ms_cpu_by_msname_instant_recommended.yaml | 1 + .../google_2011_cpu_by_job_id_5m_default.yaml | 1 + ...gle_2011_cpu_by_job_id_5m_recommended.yaml | 1 + ...le_2011_cpu_by_job_id_instant_default.yaml | 1 + ...011_cpu_by_job_id_instant_recommended.yaml | 1 + .../google_2011_cpu_p99_instant_default.yaml | 1 + ...ogle_2011_cpu_p99_instant_recommended.yaml | 1 + .../experiments/experiment_utils/config.py | 11 ++-- asap-tools/experiments/generate_workload.py | 2 +- .../recommended_sketch_configs.py | 2 +- .../tests/test_sql_planner_input.py | 53 ++++++++++++++++++- benchmarks/config/controller-config.yaml | 1 + .../operations/try-asap-planner-promql.md | 1 + .../operations/try-asap-planner-sql.md | 1 + promql-compliance/runner/run.go | 5 +- tools/run_metrics_observability_benchmark.py | 2 +- 54 files changed, 146 insertions(+), 11 deletions(-) diff --git a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic.yaml b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic.yaml index 2d1b0c7a..6c9209ed 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic.yaml @@ -5,6 +5,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: "errors_total" labels: ["instance", "job"] diff --git a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_dedup.yaml b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_dedup.yaml index bc84afcf..a2469b0b 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_dedup.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_dedup.yaml @@ -6,6 +6,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: "errors_total" labels: ["instance", "job"] diff --git a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_nested.yaml b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_nested.yaml index a5b86496..848798f9 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_nested.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_nested.yaml @@ -5,6 +5,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: "a_total" labels: ["instance"] diff --git a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_non_acceleratable.yaml b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_non_acceleratable.yaml index f02f8e2b..71641492 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_non_acceleratable.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_non_acceleratable.yaml @@ -5,6 +5,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: "errors_total" labels: ["instance"] diff --git a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_scalar.yaml b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_scalar.yaml index c754560a..ba31242c 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_scalar.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/binary_arithmetic_scalar.yaml @@ -5,6 +5,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: "errors_total" labels: ["instance", "job"] diff --git a/asap-planner-rs/tests/comparison/test_data/configs/cleanup_circular.yaml b/asap-planner-rs/tests/comparison/test_data/configs/cleanup_circular.yaml index c4f5e5d4..623d0765 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/cleanup_circular.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/cleanup_circular.yaml @@ -5,5 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "circular_buffer" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/cleanup_read_based.yaml b/asap-planner-rs/tests/comparison/test_data/configs/cleanup_read_based.yaml index dc842064..9fc4f613 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/cleanup_read_based.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/cleanup_read_based.yaml @@ -5,5 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/deduplicated.yaml b/asap-planner-rs/tests/comparison/test_data/configs/deduplicated.yaml index d61f6664..5f8f9a76 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/deduplicated.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/deduplicated.yaml @@ -7,11 +7,13 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 - id: 2 queries: - "increase(http_requests_total[5m])" repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/increase.yaml b/asap-planner-rs/tests/comparison/test_data/configs/increase.yaml index d424015d..c63df302 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/increase.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/increase.yaml @@ -5,5 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/mixed_workload.yaml b/asap-planner-rs/tests/comparison/test_data/configs/mixed_workload.yaml index 51c32415..e31dbfaa 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/mixed_workload.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/mixed_workload.yaml @@ -6,5 +6,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/quantile_over_time.yaml b/asap-planner-rs/tests/comparison/test_data/configs/quantile_over_time.yaml index 55aef2f2..2e2231da 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/quantile_over_time.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/quantile_over_time.yaml @@ -5,5 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/range_query.yaml b/asap-planner-rs/tests/comparison/test_data/configs/range_query.yaml index dc842064..9fc4f613 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/range_query.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/range_query.yaml @@ -5,5 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/rate_increase.yaml b/asap-planner-rs/tests/comparison/test_data/configs/rate_increase.yaml index dc842064..9fc4f613 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/rate_increase.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/rate_increase.yaml @@ -5,5 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/spatial_quantile.yaml b/asap-planner-rs/tests/comparison/test_data/configs/spatial_quantile.yaml index b34337bc..817adbb0 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/spatial_quantile.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/spatial_quantile.yaml @@ -5,5 +5,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/sum_by.yaml b/asap-planner-rs/tests/comparison/test_data/configs/sum_by.yaml index f61a9857..a98e5b3c 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/sum_by.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/sum_by.yaml @@ -5,5 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/sum_by_overlapping.yaml b/asap-planner-rs/tests/comparison/test_data/configs/sum_by_overlapping.yaml index 251ad5f7..893b7845 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/sum_by_overlapping.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/sum_by_overlapping.yaml @@ -5,5 +5,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/sum_over_time.yaml b/asap-planner-rs/tests/comparison/test_data/configs/sum_over_time.yaml index 62cd574f..29484139 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/sum_over_time.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/sum_over_time.yaml @@ -5,5 +5,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/temporal_overlapping.yaml b/asap-planner-rs/tests/comparison/test_data/configs/temporal_overlapping.yaml index f8a3f025..f3da78c5 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/temporal_overlapping.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/temporal_overlapping.yaml @@ -8,5 +8,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/comparison/test_data/configs/topk.yaml b/asap-planner-rs/tests/comparison/test_data/configs/topk.yaml index 04b336c8..ec069ae2 100644 --- a/asap-planner-rs/tests/comparison/test_data/configs/topk.yaml +++ b/asap-planner-rs/tests/comparison/test_data/configs/topk.yaml @@ -5,5 +5,6 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/elastic_dsl_integration.rs b/asap-planner-rs/tests/elastic_dsl_integration.rs index 29db8dfa..334e217b 100644 --- a/asap-planner-rs/tests/elastic_dsl_integration.rs +++ b/asap-planner-rs/tests/elastic_dsl_integration.rs @@ -28,6 +28,7 @@ query_groups: repetition_delay_ms: {t_repeat_ms} controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 aggregate_cleanup: policy: read_based "#, @@ -389,6 +390,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 - id: 2 index: other_metrics time_field: "timestamp" @@ -427,6 +429,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 aggregate_cleanup: policy: read_based "#; diff --git a/asap-planner-rs/tests/elastic_example.yaml b/asap-planner-rs/tests/elastic_example.yaml index 2f2b5d1d..15bc9993 100644 --- a/asap-planner-rs/tests/elastic_example.yaml +++ b/asap-planner-rs/tests/elastic_example.yaml @@ -30,5 +30,6 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 aggregate_cleanup: policy: read_based diff --git a/asap-planner-rs/tests/integration.rs b/asap-planner-rs/tests/integration.rs index b6749b25..f193a1db 100644 --- a/asap-planner-rs/tests/integration.rs +++ b/asap-planner-rs/tests/integration.rs @@ -125,12 +125,14 @@ query_groups: repetition_delay_ms: 65000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 - id: 2 queries: - "rate(http_requests_total[55s])" repetition_delay_ms: 55000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#, http_requests_schema(), default_opts(), @@ -163,6 +165,7 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#, http_requests_schema(), default_opts(), @@ -238,6 +241,7 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#, http_requests_schema(), default_opts(), @@ -274,6 +278,7 @@ query_groups: step_ms: 80000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#, http_requests_schema(), default_opts(), @@ -301,6 +306,7 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#, http_requests_schema(), default_opts(), @@ -674,6 +680,7 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#, http_requests_schema(), default_opts(), @@ -724,6 +731,7 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#, http_requests_schema(), default_opts(), @@ -897,6 +905,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "not_a_real_policy" "#; @@ -919,6 +928,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#; let c = Controller::from_yaml_with_schema(yaml, http_requests_schema(), default_opts()).unwrap(); @@ -938,12 +948,14 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 - id: 2 queries: - "rate(http_requests_total[5m])" repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#; let c = Controller::from_yaml_with_schema(yaml, http_requests_schema(), default_opts()).unwrap(); @@ -964,6 +976,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#; // Schema only knows about http_requests_total, not unknown_metric. let c = @@ -1271,12 +1284,14 @@ query_groups: repetition_delay_ms: 65000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 - id: 2 queries: - "rate(errors_total[55s]) / rate(requests_total[55s])" repetition_delay_ms: 55000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#, binary_arithmetic_schema(), default_opts(), @@ -1311,6 +1326,7 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "#, binary_arithmetic_schema(), default_opts(), diff --git a/asap-planner-rs/tests/sql_integration.rs b/asap-planner-rs/tests/sql_integration.rs index b9722596..ee77222b 100644 --- a/asap-planner-rs/tests/sql_integration.rs +++ b/asap-planner-rs/tests/sql_integration.rs @@ -85,6 +85,7 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - "{query}" aggregate_cleanup: @@ -122,6 +123,7 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - "{query}" aggregate_cleanup: @@ -190,6 +192,7 @@ query_groups: repetition_delay_ms: {t_repeat_ms} controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- {query} @@ -639,6 +642,7 @@ query_groups: repetition_delay_ms: {t_repeat_ms} controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- {query} @@ -767,6 +771,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- SELECT MIN(cpu_usage) FROM metrics_table WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY datacenter @@ -774,6 +779,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- SELECT MAX(cpu_usage) FROM metrics_table WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY datacenter @@ -806,6 +812,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- SELECT SUM(cpu_usage) FROM metrics_table WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY datacenter @@ -839,6 +846,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- {q} @@ -846,6 +854,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- {q} @@ -874,6 +883,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- SELECT SUM(cpu_usage) FROM metrics_table WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY datacenter @@ -881,6 +891,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- SELECT SUM(cpu_usage) FROM metrics_table WHERE time BETWEEN DATEADD(s, -600, NOW()) AND NOW() GROUP BY datacenter @@ -964,6 +975,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- {q} @@ -994,6 +1006,7 @@ query_groups: repetition_delay_ms: 300000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- {q} diff --git a/asap-planner-rs/tests/test_data/windowing/promql_sliding.yaml b/asap-planner-rs/tests/test_data/windowing/promql_sliding.yaml index b4d1b1fa..51e8e705 100644 --- a/asap-planner-rs/tests/test_data/windowing/promql_sliding.yaml +++ b/asap-planner-rs/tests/test_data/windowing/promql_sliding.yaml @@ -9,11 +9,13 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 - id: 2 queries: - "rate(http_requests_total[2m])" repetition_delay_ms: 120000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 aggregate_cleanup: policy: "read_based" diff --git a/asap-planner-rs/tests/test_data/windowing/sql_sliding.yaml b/asap-planner-rs/tests/test_data/windowing/sql_sliding.yaml index f157ebd8..1187b428 100644 --- a/asap-planner-rs/tests/test_data/windowing/sql_sliding.yaml +++ b/asap-planner-rs/tests/test_data/windowing/sql_sliding.yaml @@ -12,6 +12,7 @@ query_groups: repetition_delay_ms: 60000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- SELECT MIN(cpu_usage) FROM metrics_table @@ -21,6 +22,7 @@ query_groups: repetition_delay_ms: 120000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- SELECT MIN(cpu_usage) FROM metrics_table diff --git a/asap-planner-rs/tests/test_data/windowing/sql_sliding_invalid.yaml b/asap-planner-rs/tests/test_data/windowing/sql_sliding_invalid.yaml index 243a8cd7..42ada292 100644 --- a/asap-planner-rs/tests/test_data/windowing/sql_sliding_invalid.yaml +++ b/asap-planner-rs/tests/test_data/windowing/sql_sliding_invalid.yaml @@ -12,6 +12,7 @@ query_groups: repetition_delay_ms: 75000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- SELECT MIN(cpu_usage) FROM metrics_table @@ -21,6 +22,7 @@ query_groups: repetition_delay_ms: 90000 controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- SELECT MIN(cpu_usage) FROM metrics_table diff --git a/asap-query-engine/tests/e2e_precompute_equivalence.rs b/asap-query-engine/tests/e2e_precompute_equivalence.rs index fd016a6a..47127774 100644 --- a/asap-query-engine/tests/e2e_precompute_equivalence.rs +++ b/asap-query-engine/tests/e2e_precompute_equivalence.rs @@ -175,6 +175,7 @@ query_groups: repetition_delay_ms: {interval_ms} controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 "# ); let planner = Controller::from_yaml_with_schema( diff --git a/asap-quickstart/config/controller-config.yaml b/asap-quickstart/config/controller-config.yaml index ab459da2..49235fcd 100644 --- a/asap-quickstart/config/controller-config.yaml +++ b/asap-quickstart/config/controller-config.yaml @@ -12,6 +12,7 @@ query_groups: repetition_delay: 10 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 # Metric metadata - includes the 'pattern' label metrics: diff --git a/asap-tools/docs/architecture.md b/asap-tools/docs/architecture.md index 906ef7d1..e79ecc06 100644 --- a/asap-tools/docs/architecture.md +++ b/asap-tools/docs/architecture.md @@ -763,6 +763,7 @@ query_groups: query_time_offset: 0 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 servers: - name: prometheus diff --git a/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md b/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md index 35a8afed..f27983cc 100644 --- a/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md +++ b/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md @@ -515,7 +515,7 @@ These parameters come from the `experiment_type` config group and are prefixed w #### `experiment_params.query_groups[].controller_options.latency_sla_ms` (float, optional) - **Description**: Maximum modeled query latency in milliseconds -- **Default**: omitted (no latency limit) +- **Default**: `1000` for SQL experiments (`DEFAULT_LATENCY_SLA_MS` in `experiment_utils/config.py`); for PromQL experiments, omitted means no latency limit - **Range**: finite and > 0 - **Example**: `250` - **Usage**: Intended as a hard ceiling on query latency for the planner. Not yet enforced: plans are not rejected for exceeding it. diff --git a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2021.yaml b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2021.yaml index 6cf35ba8..2e09414c 100644 --- a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2021.yaml +++ b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2021.yaml @@ -49,6 +49,7 @@ query_groups: starting_delay: 70 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: "alibaba_microservice_cpu_usage" diff --git a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2022.yaml b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2022.yaml index 3d13fd21..46a88a3e 100644 --- a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2022.yaml +++ b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_msresource_2022.yaml @@ -49,6 +49,7 @@ query_groups: starting_delay: 70 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: "alibaba_microservice_cpu_usage" diff --git a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2021.yaml b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2021.yaml index 99d32fbe..4d21eabb 100644 --- a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2021.yaml +++ b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2021.yaml @@ -60,6 +60,7 @@ query_groups: starting_delay: 70 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: "alibaba_node_cpu_usage" diff --git a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2022.yaml b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2022.yaml index 42911b88..ea1dc644 100644 --- a/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2022.yaml +++ b/asap-tools/experiments/config/experiment_type/cluster_data_alibaba_node_2022.yaml @@ -52,6 +52,7 @@ query_groups: starting_delay: 70 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: "alibaba_node_cpu_usage" diff --git a/asap-tools/experiments/config/experiment_type/cluster_data_google.yaml b/asap-tools/experiments/config/experiment_type/cluster_data_google.yaml index 7c2942b2..6c3e209f 100644 --- a/asap-tools/experiments/config/experiment_type/cluster_data_google.yaml +++ b/asap-tools/experiments/config/experiment_type/cluster_data_google.yaml @@ -66,6 +66,7 @@ query_groups: starting_delay: 70 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: # Google metrics with aggregation_type=0 diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_default.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_default.yaml index 5dfd5968..3adde0c4 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_default.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_default.yaml @@ -35,6 +35,7 @@ experiment_params: starting_delay: 390 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: alibaba_microservice_cpu_usage labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_recommended.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_recommended.yaml index 005f51e4..d372d21e 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_recommended.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_5m_recommended.yaml @@ -35,6 +35,7 @@ experiment_params: starting_delay: 390 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: alibaba_microservice_cpu_usage labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_default.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_default.yaml index a1425e93..3fbb04ed 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_default.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_default.yaml @@ -35,6 +35,7 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: alibaba_microservice_cpu_usage labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_recommended.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_recommended.yaml index 8ad6b078..72d6d54e 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_recommended.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/alibaba_v2022_ms_cpu_by_msname_instant_recommended.yaml @@ -35,6 +35,7 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: alibaba_microservice_cpu_usage labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_default.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_default.yaml index f83f1a69..78ed3c79 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_default.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_default.yaml @@ -34,6 +34,7 @@ experiment_params: starting_delay: 390 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_recommended.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_recommended.yaml index bff8c5c4..ea34015f 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_recommended.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_5m_recommended.yaml @@ -34,6 +34,7 @@ experiment_params: starting_delay: 390 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_default.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_default.yaml index 09ec1088..1195e9f5 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_default.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_default.yaml @@ -34,6 +34,7 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_recommended.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_recommended.yaml index 155df666..6fc64b5e 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_recommended.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_by_job_id_instant_recommended.yaml @@ -34,6 +34,7 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_default.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_default.yaml index 266b1d91..b9711d75 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_default.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_default.yaml @@ -34,6 +34,7 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_recommended.yaml b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_recommended.yaml index 52f5603a..c4aef968 100644 --- a/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_recommended.yaml +++ b/asap-tools/experiments/config/experiment_type/recommended_sketch_configs/google_2011_cpu_p99_instant_recommended.yaml @@ -34,6 +34,7 @@ experiment_params: starting_delay: 90 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 metrics: - metric: google_mean_cpu_usage_rate_0 labels: diff --git a/asap-tools/experiments/experiment_utils/config.py b/asap-tools/experiments/experiment_utils/config.py index cf436ac3..2249ca22 100644 --- a/asap-tools/experiments/experiment_utils/config.py +++ b/asap-tools/experiments/experiment_utils/config.py @@ -15,6 +15,8 @@ # Keys the planner's `ControllerOptions` accepts. CONTROLLER_OPTION_KEYS = {"accuracy_sla", "latency_sla_ms"} +# Per-query latency ceiling sent to the planner when a SQL query group omits one. +DEFAULT_LATENCY_SLA_MS = 1000 def validate_basic_config( @@ -863,7 +865,7 @@ def generate_sql_planner_input( query_groups: ListConfig of query group dicts. Each entry must have ``sql_file``, ``repetition_delay_ms``, and ``controller_options`` (``accuracy_sla``, optional - ``latency_sla_ms``). + ``latency_sla_ms`` defaulting to ``DEFAULT_LATENCY_SLA_MS``). dataset_cfg: DictConfig with ``table``/``name``, and ``precompute`` sub-config (``timestamp_col``, ``value_col``, ``label_cols``). sketch_parameters: Optional DictConfig/dict mirroring ``config.yaml``'s @@ -922,9 +924,10 @@ def generate_sql_planner_input( planner_ctrl_opts = { "accuracy_sla": float(ctrl_opts.get("accuracy_sla", 0.95)), } - # Omitted latency_sla_ms means no latency limit in the planner. - if ctrl_opts.get("latency_sla_ms") is not None: - planner_ctrl_opts["latency_sla_ms"] = float(ctrl_opts["latency_sla_ms"]) + # An explicit null means no latency limit, as in the planner. + latency_sla_ms = ctrl_opts.get("latency_sla_ms", DEFAULT_LATENCY_SLA_MS) + if latency_sla_ms is not None: + planner_ctrl_opts["latency_sla_ms"] = float(latency_sla_ms) planner_query_groups.append( { "id": idx + 1, diff --git a/asap-tools/experiments/generate_workload.py b/asap-tools/experiments/generate_workload.py index 2b855d78..26744064 100644 --- a/asap-tools/experiments/generate_workload.py +++ b/asap-tools/experiments/generate_workload.py @@ -433,7 +433,7 @@ def get_base_config() -> Dict: "query_time_offset": 10, "starting_delay": 60, }, - "controller_options": {"accuracy_sla": 0.99}, + "controller_options": {"accuracy_sla": 0.99, "latency_sla_ms": 1000}, } ], "metrics": [ diff --git a/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py b/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py index 9cd15516..937a997e 100644 --- a/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py +++ b/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py @@ -238,7 +238,7 @@ def build_experiment_config( "query_time_offset": 10, "starting_delay": starting_delay, }, - "controller_options": {"accuracy_sla": 0.99}, + "controller_options": {"accuracy_sla": 0.99, "latency_sla_ms": 1000}, } ], "metrics": [ diff --git a/asap-tools/experiments/tests/test_sql_planner_input.py b/asap-tools/experiments/tests/test_sql_planner_input.py index 0b6efc70..25001a27 100644 --- a/asap-tools/experiments/tests/test_sql_planner_input.py +++ b/asap-tools/experiments/tests/test_sql_planner_input.py @@ -1,10 +1,13 @@ """Tests for generating the SQL planner input.""" +import os +import tempfile import unittest +import yaml from omegaconf import OmegaConf -from experiment_utils.config import generate_sql_planner_input +from experiment_utils.config import DEFAULT_LATENCY_SLA_MS, generate_sql_planner_input class ControllerOptionKeysTest(unittest.TestCase): @@ -32,5 +35,53 @@ def test_unknown_controller_option_is_rejected(self): generate_sql_planner_input(groups, dataset_cfg) +class LatencySlaMsTest(unittest.TestCase): + def _planner_latency(self, controller_options): + with tempfile.TemporaryDirectory() as tmp: + sql_path = os.path.join(tmp, "q.sql") + with open(sql_path, "w") as f: + f.write("SELECT 1;") + groups = [ + { + "sql_file": {"baseline": sql_path}, + "repetition_delay_ms": 60000, + "controller_options": controller_options, + } + ] + dataset_cfg = OmegaConf.create( + { + "name": "t", + "precompute": { + "timestamp_col": "ts", + "value_col": "v", + "label_cols": ["job"], + }, + } + ) + planner_input = yaml.safe_load( + generate_sql_planner_input(groups, dataset_cfg) + ) + return planner_input["query_groups"][0]["controller_options"].get( + "latency_sla_ms" + ) + + def test_omitted_latency_sla_ms_uses_default(self): + self.assertEqual( + self._planner_latency({"accuracy_sla": 0.99}), + float(DEFAULT_LATENCY_SLA_MS), + ) + + def test_explicit_latency_sla_ms_is_kept(self): + self.assertEqual( + self._planner_latency({"accuracy_sla": 0.99, "latency_sla_ms": 250}), + 250.0, + ) + + def test_null_latency_sla_ms_means_no_limit(self): + self.assertIsNone( + self._planner_latency({"accuracy_sla": 0.99, "latency_sla_ms": None}) + ) + + if __name__ == "__main__": unittest.main() diff --git a/benchmarks/config/controller-config.yaml b/benchmarks/config/controller-config.yaml index 00483bdc..b90204d6 100644 --- a/benchmarks/config/controller-config.yaml +++ b/benchmarks/config/controller-config.yaml @@ -12,6 +12,7 @@ query_groups: repetition_delay_ms: 10000 controller_options: accuracy_sla: 0.99 + latency_sla_ms: 1000 # Metric metadata - includes the 'pattern' label metrics: diff --git a/docs/03-how-to-guides/operations/try-asap-planner-promql.md b/docs/03-how-to-guides/operations/try-asap-planner-promql.md index acdad6dc..a09861fd 100644 --- a/docs/03-how-to-guides/operations/try-asap-planner-promql.md +++ b/docs/03-how-to-guides/operations/try-asap-planner-promql.md @@ -23,6 +23,7 @@ query_groups: repetition_delay_ms: 300000 # ms between repeats of this query controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - "sum by (job) (rate(http_requests_total[5m]))" aggregate_cleanup: diff --git a/docs/03-how-to-guides/operations/try-asap-planner-sql.md b/docs/03-how-to-guides/operations/try-asap-planner-sql.md index 431a49d8..3052f033 100644 --- a/docs/03-how-to-guides/operations/try-asap-planner-sql.md +++ b/docs/03-how-to-guides/operations/try-asap-planner-sql.md @@ -25,6 +25,7 @@ query_groups: repetition_delay: 300 # seconds between repeats of this query controller_options: accuracy_sla: 0.95 + latency_sla_ms: 1000 queries: - >- SELECT avg(cpu_usage) FROM metrics_table diff --git a/promql-compliance/runner/run.go b/promql-compliance/runner/run.go index 2b8b7a36..c229a4eb 100644 --- a/promql-compliance/runner/run.go +++ b/promql-compliance/runner/run.go @@ -332,7 +332,8 @@ type plannerQueryGroup struct { } type plannerController struct { - AccuracySLA float64 `yaml:"accuracy_sla"` + AccuracySLA float64 `yaml:"accuracy_sla"` + LatencySLAMs float64 `yaml:"latency_sla_ms"` } type plannerMetric struct { @@ -376,7 +377,7 @@ func writeGeneratedConfigs(directory string, fixture seeder.Fixture, suite Suite } group := plannerQueryGroup{ ID: index + 1, Queries: []string{query.Expr}, RepetitionDelayMS: repetitionDelayMS, - ControllerOptions: plannerController{AccuracySLA: 0.99}, + ControllerOptions: plannerController{AccuracySLA: 0.99, LatencySLAMs: 1000}, } if query.Range != nil { stepMS := int(query.Range.StepSeconds * float64(time.Second/time.Millisecond)) diff --git a/tools/run_metrics_observability_benchmark.py b/tools/run_metrics_observability_benchmark.py index 056c962e..8dbb0cef 100644 --- a/tools/run_metrics_observability_benchmark.py +++ b/tools/run_metrics_observability_benchmark.py @@ -165,7 +165,7 @@ def make_workload(queries, path, scrape_ms, repeat_ms): { "id": 1, "repetition_delay_ms": repeat_ms, - "controller_options": {"accuracy_sla": 0.95}, + "controller_options": {"accuracy_sla": 0.95, "latency_sla_ms": 1000}, "queries": [ entry["query"] for entry in queries From 8d79801ec93cf3052012cdd69573bbefb33addd5 Mon Sep 17 00:00:00 2001 From: Milind Srivastava Date: Tue, 6 Oct 2026 18:10:50 -0400 Subject: [PATCH 4/4] fix(planner): consistent latency_sla_ms defaults and stricter config parsing - SQL experiment planner input no longer defaults `latency_sla_ms`; omitted means no limit, as on the PromQL path and in the planner. - asap-tools rejects non-numeric, boolean, non-finite or non-positive `latency_sla_ms` when generating SQL planner input. - Leave `query_groups` out of the planner input when the experiment has none, so the planner reports it missing instead of planning nothing. - SQL and Elastic DSL configs and query groups deny unknown fields, like PromQL ones. Co-Authored-By: Claude Opus 5.5 --- asap-planner-rs/src/config/input.rs | 41 +++++++++++++++- .../CONFIG_PARAMETERS_REFERENCE.md | 2 +- .../experiments/experiment_utils/config.py | 38 ++++++++++---- .../tests/test_controller_client_configs.py | 49 +++++++++++++++++++ .../tests/test_sql_planner_input.py | 21 +++++--- 5 files changed, 130 insertions(+), 21 deletions(-) create mode 100644 asap-tools/experiments/tests/test_controller_client_configs.py diff --git a/asap-planner-rs/src/config/input.rs b/asap-planner-rs/src/config/input.rs index 7f63b10a..c76b55cf 100644 --- a/asap-planner-rs/src/config/input.rs +++ b/asap-planner-rs/src/config/input.rs @@ -226,6 +226,7 @@ pub struct HllParams { } #[derive(Debug, Clone, Deserialize)] +#[serde(deny_unknown_fields)] pub struct SQLControllerConfig { pub query_groups: Vec, pub tables: Vec, @@ -235,6 +236,7 @@ pub struct SQLControllerConfig { } #[derive(Debug, Clone, Deserialize)] +#[serde(deny_unknown_fields)] pub struct SQLQueryGroup { pub id: Option, pub queries: Vec, @@ -252,6 +254,7 @@ pub struct TableDefinition { } #[derive(Debug, Clone, Deserialize)] +#[serde(deny_unknown_fields)] pub struct ElasticDSLControllerConfig { pub query_groups: Vec, pub sketch_parameters: Option, @@ -259,6 +262,7 @@ pub struct ElasticDSLControllerConfig { } #[derive(Debug, Clone, Deserialize)] +#[serde(deny_unknown_fields)] pub struct ElasticDSLQueryGroup { pub id: Option, pub queries: Vec, @@ -323,8 +327,7 @@ query_groups: ); } - // The unitless `latency_sla` key was never enforced; reject it so stale - // configs fail loudly instead of silently losing their latency limit. + // Reject the unitless `latency_sla` key so it can't be silently ignored. #[test] fn rejects_legacy_latency_sla_key() { let yaml = r#" @@ -362,6 +365,40 @@ query_groups: ); } + #[test] + fn sql_and_elastic_configs_reject_unknown_group_keys() { + let sql = r#" +tables: [] +query_groups: + - queries: ["SELECT 1"] + repetition_delay_ms: 60000 + latency_sla: 1.0 + controller_options: + accuracy_sla: 0.99 +"#; + let error = serde_yaml::from_str::(sql) + .expect_err("unknown SQL group key must be rejected") + .to_string(); + assert!(error.contains("unknown field `latency_sla`"), "{error}"); + + let elastic = r#" +query_groups: + - queries: ["{}"] + repetition_delay_ms: 60000 + index: i + time_field: t + controler_options: + accuracy_sla: 0.99 +"#; + let error = serde_yaml::from_str::(elastic) + .expect_err("unknown Elastic group key must be rejected") + .to_string(); + assert!( + error.contains("unknown field `controler_options`"), + "{error}" + ); + } + #[test] fn rejects_non_positive_or_non_finite_latency_sla_ms() { for bad in ["0.0", "-5.0", ".inf", ".nan"] { diff --git a/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md b/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md index f27983cc..35a8afed 100644 --- a/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md +++ b/asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md @@ -515,7 +515,7 @@ These parameters come from the `experiment_type` config group and are prefixed w #### `experiment_params.query_groups[].controller_options.latency_sla_ms` (float, optional) - **Description**: Maximum modeled query latency in milliseconds -- **Default**: `1000` for SQL experiments (`DEFAULT_LATENCY_SLA_MS` in `experiment_utils/config.py`); for PromQL experiments, omitted means no latency limit +- **Default**: omitted (no latency limit) - **Range**: finite and > 0 - **Example**: `250` - **Usage**: Intended as a hard ceiling on query latency for the planner. Not yet enforced: plans are not rejected for exceeding it. diff --git a/asap-tools/experiments/experiment_utils/config.py b/asap-tools/experiments/experiment_utils/config.py index 2249ca22..a731c005 100644 --- a/asap-tools/experiments/experiment_utils/config.py +++ b/asap-tools/experiments/experiment_utils/config.py @@ -3,6 +3,7 @@ Contains functions for validating configs, generating controller configs, etc. """ +import math import os import copy import yaml @@ -15,8 +16,6 @@ # Keys the planner's `ControllerOptions` accepts. CONTROLLER_OPTION_KEYS = {"accuracy_sla", "latency_sla_ms"} -# Per-query latency ceiling sent to the planner when a SQL query group omits one. -DEFAULT_LATENCY_SLA_MS = 1000 def validate_basic_config( @@ -419,10 +418,11 @@ def generate_controller_client_configs( } # Only the query client reads `client_options`; any other unknown group # key reaches the planner and is rejected there. - controller_only_config["query_groups"] = [ - {k: v for k, v in group.items() if k != "client_options"} - for group in controller_only_config.get("query_groups", []) - ] + if "query_groups" in controller_only_config: + controller_only_config["query_groups"] = [ + {k: v for k, v in group.items() if k != "client_options"} + for group in controller_only_config["query_groups"] + ] with open( os.path.join( output_dir, "{}_controller_input.yaml".format(experiment_mode["mode"]) @@ -840,6 +840,22 @@ def generate_clickhouse_client_configs( return modes +def _positive_latency_sla_ms(value: Any, idx: int) -> float: + """Fail at generation time rather than on the remote planner.""" + # bool is an int subclass; `true` would otherwise become 1.0. + if isinstance(value, bool) or not isinstance(value, (int, float)): + raise ValueError( + f"query_groups[{idx}].controller_options.latency_sla_ms must be a " + f"number, got {value!r}" + ) + if not (math.isfinite(value) and value > 0): + raise ValueError( + f"query_groups[{idx}].controller_options.latency_sla_ms must be " + f"finite and > 0, got {value!r}" + ) + return float(value) + + def generate_sql_planner_input( query_groups: Any, dataset_cfg: Any, @@ -865,7 +881,7 @@ def generate_sql_planner_input( query_groups: ListConfig of query group dicts. Each entry must have ``sql_file``, ``repetition_delay_ms``, and ``controller_options`` (``accuracy_sla``, optional - ``latency_sla_ms`` defaulting to ``DEFAULT_LATENCY_SLA_MS``). + ``latency_sla_ms``; omitted or null means no latency limit). dataset_cfg: DictConfig with ``table``/``name``, and ``precompute`` sub-config (``timestamp_col``, ``value_col``, ``label_cols``). sketch_parameters: Optional DictConfig/dict mirroring ``config.yaml``'s @@ -924,10 +940,12 @@ def generate_sql_planner_input( planner_ctrl_opts = { "accuracy_sla": float(ctrl_opts.get("accuracy_sla", 0.95)), } - # An explicit null means no latency limit, as in the planner. - latency_sla_ms = ctrl_opts.get("latency_sla_ms", DEFAULT_LATENCY_SLA_MS) + # Omitted or null means no latency limit, as in the planner. + latency_sla_ms = ctrl_opts.get("latency_sla_ms") if latency_sla_ms is not None: - planner_ctrl_opts["latency_sla_ms"] = float(latency_sla_ms) + planner_ctrl_opts["latency_sla_ms"] = _positive_latency_sla_ms( + latency_sla_ms, idx + ) planner_query_groups.append( { "id": idx + 1, diff --git a/asap-tools/experiments/tests/test_controller_client_configs.py b/asap-tools/experiments/tests/test_controller_client_configs.py new file mode 100644 index 00000000..96a92fc1 --- /dev/null +++ b/asap-tools/experiments/tests/test_controller_client_configs.py @@ -0,0 +1,49 @@ +"""Tests for the planner input written from experiment parameters.""" + +import os +import tempfile +import unittest + +import yaml +from omegaconf import OmegaConf + +from experiment_utils.config import generate_controller_client_configs + + +def _controller_input(experiment_params): + with tempfile.TemporaryDirectory() as tmp: + generate_controller_client_configs(OmegaConf.create(experiment_params), tmp) + path = os.path.join( + tmp, "controller_client_configs", "sketchdb_controller_input.yaml" + ) + with open(path) as f: + return yaml.safe_load(f) + + +BASE = { + "servers": [{"name": "sketchdb", "url": "http://localhost:8088"}], + "experiment": [{"mode": "sketchdb", "server": "sketchdb"}], + "metrics": [{"metric": "m", "labels": ["job"], "exporter": "fake"}], +} + + +class ControllerInputTest(unittest.TestCase): + def test_client_options_are_stripped_from_query_groups(self): + group = { + "id": 1, + "queries": ["sum(m)"], + "repetition_delay_ms": 60000, + "client_options": {"repetitions": 1}, + "controller_options": {"accuracy_sla": 0.99}, + } + planner_input = _controller_input({**BASE, "query_groups": [group]}) + self.assertNotIn("client_options", planner_input["query_groups"][0]) + self.assertIn("controller_options", planner_input["query_groups"][0]) + + def test_missing_query_groups_stays_missing(self): + # An empty list would parse and plan nothing; a missing key fails loudly. + self.assertNotIn("query_groups", _controller_input(BASE)) + + +if __name__ == "__main__": + unittest.main() diff --git a/asap-tools/experiments/tests/test_sql_planner_input.py b/asap-tools/experiments/tests/test_sql_planner_input.py index 25001a27..007c67b9 100644 --- a/asap-tools/experiments/tests/test_sql_planner_input.py +++ b/asap-tools/experiments/tests/test_sql_planner_input.py @@ -7,13 +7,13 @@ import yaml from omegaconf import OmegaConf -from experiment_utils.config import DEFAULT_LATENCY_SLA_MS, generate_sql_planner_input +from experiment_utils.config import generate_sql_planner_input class ControllerOptionKeysTest(unittest.TestCase): def test_unknown_controller_option_is_rejected(self): - # A stale `latency_sla` used to be dropped here, so the planner ran - # with no latency limit and never saw the bad key. + # Unknown keys must fail here: dropping them would hide them from the + # planner's strict parse. groups = [ { "sql_file": "unused.sql", @@ -65,11 +65,16 @@ def _planner_latency(self, controller_options): "latency_sla_ms" ) - def test_omitted_latency_sla_ms_uses_default(self): - self.assertEqual( - self._planner_latency({"accuracy_sla": 0.99}), - float(DEFAULT_LATENCY_SLA_MS), - ) + def test_omitted_latency_sla_ms_means_no_limit(self): + # Same meaning as the PromQL path and the planner. + self.assertIsNone(self._planner_latency({"accuracy_sla": 0.99})) + + def test_invalid_latency_sla_ms_is_rejected(self): + for bad in [0, -5, float("inf"), float("nan"), True, "1000"]: + with self.subTest(bad=bad), self.assertRaisesRegex( + ValueError, "latency_sla_ms" + ): + self._planner_latency({"accuracy_sla": 0.99, "latency_sla_ms": bad}) def test_explicit_latency_sla_ms_is_kept(self): self.assertEqual(