Skip to content

feat: Elastic DSL in asap-planner-rs#327

Merged
milindsrivastava1997 merged 11 commits into
mainfrom
elastic-dsl-planner
May 21, 2026
Merged

feat: Elastic DSL in asap-planner-rs#327
milindsrivastava1997 merged 11 commits into
mainfrom
elastic-dsl-planner

Conversation

@Kolleida

@Kolleida Kolleida commented May 6, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@Kolleida Kolleida marked this pull request as ready for review May 12, 2026 21:10
@milindsrivastava1997

Copy link
Copy Markdown
Contributor

Code Review

infer_time_field heuristics are overly broad (extract_info.rs)

let looks_like_time_field = field == "@timestamp"
    || field.contains("time")
    || field.contains("timestamp")
    || bound_is_time_like;

field.contains("time") matches response_time, uptime, idle_time, etc. A query with range: { response_time: { gte: "now-5m" } } would be incorrectly inferred as the time field even though bound_is_time_like already handles the datetime-bound case. The substring checks and bound_is_time_like are partially redundant — consider replacing the open-ended contains with more precise patterns (e.g. field.ends_with("_time") || field == "timestamp").


t_lookback ignores the query's actual time range (elastic_dsl.rs)

let t_lookback = self.t_repeat; // Default to repetition delay

For a query with "gte": "now-5m" and repetition_delay: 60, the lookback is 300s but t_lookback = 60. The SQL path derives the lookback from the query's time window; using t_repeat here will produce too-aggressive cleanup and evict data that queries still need. The actual [gte, lte] bounds from the parsed predicates should drive this value.


streaming_engine is stored but never used (elastic_dsl.rs)

#[allow(dead_code)]
streaming_engine: StreamingEngine,

In the PromQL/SQL planners, StreamingEngine affects which aggregation types are emitted. If the same distinction doesn't apply here, a comment explaining why would help. If it does apply, this is a bug.


spatial_output and rollup are always identical (elastic_dsl.rs)

let spatial = KeyByLabelNames::new(group_fields);
(spatial.clone(), spatial) // rollup == spatial_output

The comment above says "all potentially available fields become rollup when they're not in the group by" but the code sets rollup equal to spatial_output, not to the complement. Comment and implementation contradict each other — one of them needs to change.


_config parameters suggest incomplete extraction (generator.rs)

Both build_elastic_streaming_yaml and build_elastic_inference_yaml accept _config: &ElasticDSLControllerConfig but never use it. Either wire it in or drop the parameter.


Minor

  • get_group_by_fields for GroupBySpec::Filters deduplicates with Vec::contains (O(n)) while collect_elastic_metadata_fields in the same file uses IndexSet — worth making consistent.
  • ElasticMappingSchema::add_index consumes self (builder pattern) but ElasticIndexSchema::new doesn't — minor API surface inconsistency.

Test gaps worth filling

  • Conflicting time fields across queries on the same index (error path in generator.rs)
  • repetition_delay % data_ingestion_interval != 0 validation error
  • infer_time_field fallback when no @timestamp-like range field is present

Kolleida added 3 commits May 19, 2026 13:45
…her be

  "@timestamp", "timestamp", or end with "_time", and the range
predicate must be datetime like.
- Fix issue where lookback duration was not using time range specified
  by parsed ES DSL query.
- Fix issue where rollup labels were same as group by labels for agg
  config -> should be all non group by (non metric) labels.
@Kolleida

Copy link
Copy Markdown
Contributor Author

Most of the nontrivial logic issues (e.g. rollup and lookback window) should be addressed.

@milindsrivastava1997 milindsrivastava1997 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


Issue 1 — src/output/mod.rs is orphaned

asap-planner-rs/src/output/mod.rs declares three submodules (generator, sql_generator, elastic_generator) but none of those files exist inside output/, and lib.rs never declares pub mod output;. The
compiler never touches this directory, so it doesn't break the build — but it looks like an abandoned mid-refactor stub. Either delete the file or complete the move before merging.


Issue 2 — Time range extraction uses .first() instead of matching the time field

let time_range = query_info
.predicates
.first()
.and_then(|p| range_query_to_time_range(p, 0));

If a Term predicate (e.g. a service/datacenter filter) appears before the range predicate in the query, this returns None and silently falls back to t_repeat as the lookback window. Should scan for the
predicate whose field matches query_info.time_field:

let time_range = query_info.predicates.iter()
.find(|p| matches!(p, Predicate::Range { field, .. } if field == &query_info.time_field))
.and_then(|p| range_query_to_time_range(p, 0));


…Reject queries that use filter group by (not supported right now).
@milindsrivastava1997 milindsrivastava1997 merged commit 85455ac into main May 21, 2026
10 checks passed
@milindsrivastava1997 milindsrivastava1997 deleted the elastic-dsl-planner branch May 21, 2026 23:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants