Skip to content

Feature/metric expression array support - #77

Open
adefabian wants to merge 9 commits into
mainfrom
feature/metric_expression_array_support
Open

Feature/metric expression array support#77
adefabian wants to merge 9 commits into
mainfrom
feature/metric_expression_array_support

Conversation

@adefabian

@adefabian adefabian commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds array-membership filter operators to MetricExpression for querying
POI-backed metrics whose values are stored as arrays, and removes the now-unused
pandas evaluation path from metric expressions.

Changes

  • Array operators on MetricExpression (metric_expression.py):
  • .contains(value) — array membership (F.array_contains)
  • .contains_any([...]) — non-empty intersection (OR); empty list matches nothing
  • .contains_all([...]) — superset (AND); empty list matches everything

e.g. q.metric("poi_defect_values").contains_any(["B1024-43", "U0046-13"]).
They compose with the existing scalar comparisons and &/|, and evaluate in
Spark via get_selector_expr.

  • Removed build_pandas from MetricExpression/MetricSelector/MetricOp.
    It was dead code for metrics — metric filters run through Spark, and the only
    build_pandas callers (TimeSeriesCache.resolve) only ever receive a
    TagExpression. TagExpression.build_pandas is untouched.
  • Docstring fix: SeriesCache.resolve (and the blob/default/empty caches)
    said it resolves "tags/metrics"; it only ever resolves a TimeSeriesSelector's
    tag expression. Corrected to say so.

Test Plan

  • Unit tests added/updated
  • Manual testing completed
  • Documentation updated (if applicable)

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • No new linter warnings introduced

@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.94%. Comparing base (d0418d9) to head (f092bc0).

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #77      +/-   ##
==========================================
+ Coverage   88.83%   88.94%   +0.10%     
==========================================
  Files          61       61              
  Lines        5170     5175       +5     
  Branches      621      623       +2     
==========================================
+ Hits         4593     4603      +10     
+ Misses        466      461       -5     
  Partials      111      111              
Flag Coverage Δ
query_engine 84.77% <100.00%> (+0.20%) ⬆️
reporting 94.16% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...query_engine/analyze/metadata/metric_expression.py 86.90% <100.00%> (+7.15%) ⬆️
..._query_engine/analyze/query/solvers/blob_solver.py 49.09% <ø> (ø)
...ery_engine/analyze/query/solvers/default_solver.py 96.97% <ø> (ø)
..._query_engine/analyze/query/solvers/empty_cache.py 88.88% <ø> (ø)
...query_engine/analyze/query/solvers/series_cache.py 80.00% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@adefabian
adefabian marked this pull request as ready for review August 12, 2026 04:58
@adefabian
adefabian requested a review from a team as a code owner August 12, 2026 04:58
Comment thread src/impulse_query_engine/analyze/metadata/metric_expression.py Outdated
Comment thread tests/impulse_query_engine/unit/model/expressions/metric_expression_test.py Outdated
tombonfert
tombonfert previously approved these changes Aug 12, 2026

@tombonfert tombonfert left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM. Please remove test 'test_metric_expression_is_spark_evaluated_not_pandas'

The SeriesCache.resolve() docstrings claimed to resolve "tags/metrics",
but resolve() is only ever called from TimeSeriesSelector.build() and
handles a channel selector's TagExpression — metric filters are evaluated
in Spark via get_selector_expr, never through this pandas path. Corrected
the wording in series_cache, blob_solver, default_solver, and empty_cache.

Added tests:
- metric_expression_test: guard that MetricExpression evaluates via
  get_selector_expr and has no build_pandas / serialization surface, so
  it can never reach the pandas resolve() path (the removed build_pandas
  stays unreachable).
- metric_array_filter_test: duplicate-element handling for contains_all,
  numeric (array<long>) columns, and value-list snapshot semantics for
  contains_any/contains_all.

Co-authored-by: Isaac
@adefabian
adefabian force-pushed the feature/metric_expression_array_support branch from f7145ae to f092bc0 Compare August 13, 2026 11:46

@tombonfert tombonfert left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

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