Skip to content

ROX-32449: include and exclude custom metric label filters#18327

Merged
parametalol merged 13 commits intomasterfrom
michael/ROX-32449-add-exclude-filters
Jan 16, 2026
Merged

ROX-32449: include and exclude custom metric label filters#18327
parametalol merged 13 commits intomasterfrom
michael/ROX-32449-add-exclude-filters

Conversation

@parametalol
Copy link
Contributor

@parametalol parametalol commented Dec 23, 2025

Description

  • include and exclude filters instead of only positive filters — proto change of not released feature
  • UI — adapting the filters column to the change
  • better metric HELP formatting — including the filters information

User-facing documentation

Testing and quality

  • the change is production ready: the change is GA, or otherwise the functionality is gated by a feature flag
  • CI results are inspected

Automated testing

  • added unit tests
  • added e2e tests
  • added regression tests
  • added compatibility tests
  • modified existing tests

How I validated my change

CI, manual.

Updated filters column

image

@rhacs-bot
Copy link
Contributor

rhacs-bot commented Dec 23, 2025

Images are ready for the commit at aaf5871.

To use with deploy scripts, first export MAIN_IMAGE_TAG=4.10.x-790-gaaf5871135.

@codecov
Copy link

codecov bot commented Dec 23, 2025

Codecov Report

❌ Patch coverage is 87.12871% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 48.96%. Comparing base (a535eb8) to head (aaf5871).
⚠️ Report is 29 commits behind head on master.

Files with missing lines Patch % Lines
central/metrics/custom/tracker/tracker_base.go 83.33% 7 Missing ⚠️
central/metrics/custom/tracker/validator.go 85.71% 4 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #18327      +/-   ##
==========================================
+ Coverage   48.92%   48.96%   +0.03%     
==========================================
  Files        2633     2639       +6     
  Lines      197986   198355     +369     
==========================================
+ Hits        96870    97128     +258     
- Misses      93727    93811      +84     
- Partials     7389     7416      +27     
Flag Coverage Δ
go-unit-tests 48.96% <87.12%> (+0.03%) ⬆️

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • In formatMetricHelp, the include/exclude filter descriptions are built by iterating over maps, so the order of filters in the HELP string will be nondeterministic; consider sorting the label keys first to keep the help output stable and easier to read/debug.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `formatMetricHelp`, the include/exclude filter descriptions are built by iterating over maps, so the order of filters in the HELP string will be nondeterministic; consider sorting the label keys first to keep the help output stable and easier to read/debug.

## Individual Comments

### Comment 1
<location> `central/metrics/custom/tracker/aggregator_test.go:205-156` </location>
<code_context>
+func Test_includeAndExcludeFilter(t *testing.T) {
</code_context>

<issue_to_address>
**suggestion (testing):** Add a test where the same label has both include and exclude filters to verify precedence and semantics

`Test_includeAndExcludeFilter` currently covers interaction across different labels (`Severity` vs `Cluster`). It would be useful to also cover the case where the *same* label has both include and exclude filters (e.g., include `Severity` = `CRITICAL|HIGH`, exclude `Severity` = `CRITICAL`). This would verify the intended precedence (include first, then exclude) and guard against regressions. Consider adding a `Test_includeAndExcludeFilterSameLabel` that asserts the exclude filter wins when patterns overlap.

Suggested implementation:

```golang
func Test_includeAndExcludeFilter(t *testing.T) {
	// Include filter to keep only CRITICAL and HIGH severity.
	severityInclude := make(map[Label]*regexp.Regexp)
	severityInclude[Label("Severity")] = regexp.MustCompile("^CRITICAL|HIGH$")

	// Exclude filter to drop cluster 1 findings.
	clusterExclude := make(map[Label]*regexp.Regexp)
	clusterExclude[Label("Cluster")] = regexp.MustCompile("^cluster 1$")

	incFilters := make(LabelFilters)
	incFilters[MetricName("test_Test_includeAndExcludeFilter_metric1")] = severityInclude
}

func Test_includeAndExcludeFilterSameLabel(t *testing.T) {
	// Include filter to keep only CRITICAL and HIGH severity.
	severityInclude := make(map[Label]*regexp.Regexp)
	severityInclude[Label("Severity")] = regexp.MustCompile("^CRITICAL|HIGH$")

	// Exclude filter on the same label to drop CRITICAL.
	severityExclude := make(map[Label]*regexp.Regexp)
	severityExclude[Label("Severity")] = regexp.MustCompile("^CRITICAL$")

	incFilters := make(LabelFilters)
	incFilters[MetricName("test_Test_includeAndExcludeFilterSameLabel_metric1")] = severityInclude

	excFilters := make(LabelFilters)
	excFilters[MetricName("test_Test_includeAndExcludeFilterSameLabel_metric1")] = severityExclude

	a := &aggregator{
		includeFilters: incFilters,
		excludeFilters: excFilters,
		result:         make(map[string]*aggregatedRecord),
	}

	// Record with Severity=CRITICAL should be excluded because exclude wins.
	a.aggregate("test_Test_includeAndExcludeFilterSameLabel_metric1", prometheus.Labels{
		"Severity": "CRITICAL",
	})
	// Record with Severity=HIGH should be included.
	a.aggregate("test_Test_includeAndExcludeFilterSameLabel_metric1", prometheus.Labels{
		"Severity": "HIGH",
	})

	// We expect only the HIGH record to be present.
	require.Len(t, a.result, 1)
	record, ok := a.result["test_Test_includeAndExcludeFilterSameLabel_metric1"]
	require.True(t, ok)
	require.Equal(t, prometheus.Labels{"Severity": "HIGH"}, record.labels)
	require.Equal(t, 1, record.total)

```

Because I only see part of the file, please verify and, if needed, adjust the following to match existing patterns in `aggregator_test.go`:

1. **Tracker construction pattern**: If existing tests construct the `aggregator` (or tracker) through a helper (e.g., `newAggregator(...)` or `newTracker(...)`) rather than instantiating `aggregator` directly, mirror that pattern in `Test_includeAndExcludeFilterSameLabel` instead of using the inline struct literal.
2. **Metric keying pattern**: If `a.result` is keyed by something other than the metric name string (e.g., a composite key or namespace), adapt the lookup and expected key accordingly.
3. **Expectation helpers**: If the file consistently uses `assert` instead of `require` (or uses `t.Helper()` wrappers), adjust the new test’s assertions to use the same assertion style and helpers.
4. **Label set shape**: If `aggregatedRecord.labels` in other tests includes additional fixed labels besides `Severity`, extend the expected `prometheus.Labels` map in the new test to include those labels as well.
</issue_to_address>

### Comment 2
<location> `central/metrics/custom/tracker/validator_test.go:93-102` </location>
<code_context>
+	config = map[string]*storage.PrometheusMetrics_Group_Labels{
</code_context>

<issue_to_address>
**suggestion (testing):** Add tests covering exclude_filter parsing errors and messaging for translateStorageConfiguration/parseFilters

The new tests cover invalid include filter labels and patterns, but `translateStorageConfiguration` also uses `parseFilters` for `ExcludeFilters` with a different error prefix. Please add analogous `ExcludeFilters` cases: one with an unknown label (validated via `validateLabel`, asserting the label/metric appear in the error) and one with an invalid regex (asserting the `bad exclude_filter expression` message). This will exercise the new `filterType` argument and protect against regressions in exclude filter error handling.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@parametalol parametalol requested a review from a team December 23, 2025 21:06
Copy link
Contributor

@sachaudh sachaudh left a comment

Choose a reason for hiding this comment

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

Thanks for taking this on @parametalol. I have a few comments/suggestions for you on the UI code. Let me know if you have any questions.

@parametalol parametalol force-pushed the michael/ROX-32449-add-exclude-filters branch from 3d0daf8 to 74c7c53 Compare January 14, 2026 09:36
@janisz janisz self-requested a review January 15, 2026 13:37
Copy link
Contributor

@sachaudh sachaudh left a comment

Choose a reason for hiding this comment

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

I think converting relevant functions to components in the next PR would be highly encouraged, and I believe you intend to do so. So LGTM 👍🏼

@parametalol parametalol merged commit 5daa25d into master Jan 16, 2026
99 of 103 checks passed
@parametalol parametalol deleted the michael/ROX-32449-add-exclude-filters branch January 16, 2026 13:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants