Skip to content

app/vmestimator: add filter field to stream config - #29

Open
makasim wants to merge 8 commits into
mainfrom
stream-filters
Open

app/vmestimator: add filter field to stream config#29
makasim wants to merge 8 commits into
mainfrom
stream-filters

Conversation

@makasim

@makasim makasim commented Jul 31, 2026

Copy link
Copy Markdown
Member

Add an optional filter field to stream config. It accepts a MetricsQL label selector (e.g. {job="api",env!~"dev|staging"}). Only time series matching all matchers are counted. Supports =, !=, =~, !~ operators.

Config:

# streams.yaml

- interval: '5m'
  filter: '{job="api"}'
  group_by: ['__name__']

The filter is exposed as a filter label on every cardinality_estimate metric to prevent label collisions between streams that share the same group_by and interval but target different subsets of series.

I don't expect filters to be used frequently via the -config flag. Their primary purpose is to support ad hoc profiling. For example, if an alert indicates that a particular job is experiencing a cardinality spike, the user could start a more detailed analysis for just that job. For example, by estimating label values cardinality or per metric name one. vmestimator would create temporary estimators with the specified filter, run them for a few minutes, and then return the results.

@makasim
makasim force-pushed the stream-filters branch 2 times, most recently from cf57145 to 0982af8 Compare July 31, 2026 20:00
Add optional `filter` field to `EstimatorConfig` accepting a MetricsQL
label selector (e.g. `{job="api",env!~"dev|staging"}`). Only time series
matching all matchers are counted. Supports =, !=, =~, !~ operators.

The compiled filters are applied in `insertMany` before any HLL
insertion, with a fast path that skips the check entirely when no filter
is configured.

The active filter is exposed as a `filter` label on every
`cardinality_estimate` metric to prevent label collisions between
streams that share the same `group_by` and `interval` but target
different subsets of series.

revert

go fmt
@makasim
makasim marked this pull request as ready for review July 31, 2026 20:08
@makasim makasim self-assigned this Jul 31, 2026

@cubic-dev-ai cubic-dev-ai Bot 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.

2 issues found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/vmestimator/estimator.go">

<violation number="1" location="app/vmestimator/estimator.go:57">
P2: Streams differing only by `filter` emit duplicate internal estimator metric label sets on `/metrics`, so Prometheus can reject the scrape as duplicate samples. Include `filter` in these four estimator metric names as well, or avoid registering per-filter copies.</violation>

<violation number="2" location="app/vmestimator/estimator.go:80">
P1: A MetricsQL selector containing `or` silently drops every branch after the first, producing an underestimate rather than rejecting unsupported syntax. Reject filters with multiple `LabelFilterss` or implement OR matching before constructing the estimator.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread app/vmestimator/estimator.go Outdated
Comment thread app/vmestimator/estimator.go
@makasim

makasim commented Aug 1, 2026

Copy link
Copy Markdown
Member Author

@cubic-dev-ai

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai

@makasim I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot 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.

2 issues found across 8 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/vmestimator/config.go">

<violation number="1" location="app/vmestimator/config.go:105">
P3: Creating streams recompiles each regexp after `metricsql.Parse` already validated it and bypasses MetricsQL's shared regexp cache. Reuse `metricsql.CompileRegexpAnchored` to preserve identical anchoring without duplicate compilation.</violation>
</file>

<file name="app/vmestimator/snapshot.go">

<violation number="1" location="app/vmestimator/snapshot.go:101">
P2: In cluster/aggregation mode, snapshots are merged in snapshots.add using only GroupByKeysLabel as the key (not the new filter field). When two streams share the same group_by+interval but different filter values — exactly the scenario this PR introduces — their snapshots collapse into one entry, and Filter/MetricPrefix become last-wins (s.Filter = other.Filter). Per-group metrics remain correct because each sketch key embeds its own filter= prefix, but the single __group__ aggregate and group_limit lines are emitted with only one snapshot's filter, so the aggregate cardinality/limit for the other filtered stream is lost or mislabeled. Consider incorporating the filter into the aggregation key so distinct-filter streams are aggregated separately.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

}

s.Interval = other.Interval
s.Filter = other.Filter

@cubic-dev-ai cubic-dev-ai Bot Aug 1, 2026

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.

P2: In cluster/aggregation mode, snapshots are merged in snapshots.add using only GroupByKeysLabel as the key (not the new filter field). When two streams share the same group_by+interval but different filter values — exactly the scenario this PR introduces — their snapshots collapse into one entry, and Filter/MetricPrefix become last-wins (s.Filter = other.Filter). Per-group metrics remain correct because each sketch key embeds its own filter= prefix, but the single group aggregate and group_limit lines are emitted with only one snapshot's filter, so the aggregate cardinality/limit for the other filtered stream is lost or mislabeled. Consider incorporating the filter into the aggregation key so distinct-filter streams are aggregated separately.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/vmestimator/snapshot.go, line 101:

<comment>In cluster/aggregation mode, snapshots are merged in snapshots.add using only GroupByKeysLabel as the key (not the new filter field). When two streams share the same group_by+interval but different filter values — exactly the scenario this PR introduces — their snapshots collapse into one entry, and Filter/MetricPrefix become last-wins (s.Filter = other.Filter). Per-group metrics remain correct because each sketch key embeds its own filter= prefix, but the single __group__ aggregate and group_limit lines are emitted with only one snapshot's filter, so the aggregate cardinality/limit for the other filtered stream is lost or mislabeled. Consider incorporating the filter into the aggregation key so distinct-filter streams are aggregated separately.</comment>

<file context>
@@ -97,6 +98,7 @@ func (s *snapshot) merge(other *snapshot) {
 	}
 
 	s.Interval = other.Interval
+	s.Filter = other.Filter
 	s.MetricPrefix = other.MetricPrefix
 	s.GroupLimit = other.GroupLimit
</file context>
Fix with cubic

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

fixed in be56586

Comment thread app/vmestimator/config.go Outdated
@makasim

makasim commented Aug 1, 2026

Copy link
Copy Markdown
Member Author

@cubic-dev-ai

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai

@makasim I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot 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.

1 issue found across 9 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/vmestimator/vmestimator.md">

<violation number="1" location="docs/vmestimator/vmestimator.md:195">
P3: The Cardinality Metrics prose still states that all `cardinality_estimate` metrics include only `interval`, `group_by_keys`, `group_by_values`, and static labels, but every example metric below it (updated in this PR) now also carries a `filter` label. Update the intro sentence to list `filter` so the prose matches the examples it is describing.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

For global estimates (no `group_by` configured), `group_by_keys` is `__global__` and `group_by_values` is omitted:
```
cardinality_estimate{interval="1h0m0s",group_by_keys="__global__"} 142300
cardinality_estimate{interval="1h0m0s",filter="",group_by_keys="__global__"} 142300

@cubic-dev-ai cubic-dev-ai Bot Aug 1, 2026

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.

P3: The Cardinality Metrics prose still states that all cardinality_estimate metrics include only interval, group_by_keys, group_by_values, and static labels, but every example metric below it (updated in this PR) now also carries a filter label. Update the intro sentence to list filter so the prose matches the examples it is describing.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docs/vmestimator/vmestimator.md, line 195:

<comment>The Cardinality Metrics prose still states that all `cardinality_estimate` metrics include only `interval`, `group_by_keys`, `group_by_values`, and static labels, but every example metric below it (updated in this PR) now also carries a `filter` label. Update the intro sentence to list `filter` so the prose matches the examples it is describing.</comment>

<file context>
@@ -181,15 +192,15 @@ All metrics include `interval`, `group_by_keys`, `group_by_values`, and any stat
 For global estimates (no `group_by` configured), `group_by_keys` is `__global__` and `group_by_values` is omitted:

-cardinality_estimate{interval="1h0m0s",group_by_keys="global"} 142300
+cardinality_estimate{interval="1h0m0s",filter="",group_by_keys="global"} 142300


</file context>
Fix with cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant