Skip to content

Add label-matcher support to Rules API#10194

Merged
bwplotka merged 9 commits intoprometheus:mainfrom
saswatamcode:rules-matcher
Jul 10, 2024
Merged

Add label-matcher support to Rules API#10194
bwplotka merged 9 commits intoprometheus:mainfrom
saswatamcode:rules-matcher

Conversation

@saswatamcode
Copy link
Member

@saswatamcode saswatamcode commented Jan 22, 2022

This PR adds support for label matchers as URL query params to the api/v1/rules endpoint of Prometheus API. This will not break existing functionality.

It filters both recording and alerting rules via their labels (both templated and non-templated).

Open question on whether active alerts should be handled differently?

A major use case for this is multi-tenant applications built on Prometheus which require a way to isolate tenant rules. Currently, one possible way of doing this is by filtering the API response. But, for endpoints like api/v1/labels, only a matcher needs to be added to URL params. So this PR aims to bring the same convenience to rules.

Fixes #9627.

@roidelapluie
Copy link
Member

While it makes sense to filter active alerts, it does not make sense to filter alert and rules definition as the label value is a templated string. I am against adding this feature.

@roidelapluie
Copy link
Member

I have also commented on the issue.

Copy link
Member

@bwplotka bwplotka left a comment

Choose a reason for hiding this comment

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

Thanks @saswatamcode for this PR and @roidelapluie for review.

Let's start with Rules API first as this is the API that matters the most.

And as per your point @roidelapluie I see this being weird from the first glance, but what if we provide the most straightforward mechanism that will be expected by everyone. Rules API is all about loaded configured, so to me we should filter by non-rendered, configured labels. This is also how it is implemented right now in this PR. I proposed a doc entry. What's wrong with that @roidelapluie 🤔

@roidelapluie
Copy link
Member

roidelapluie commented Jan 26, 2022

What is wrong is the semantic. I'd rather have match[] only match labels, and not templates in one API and label values in another API. I'd be okay if we would make this available in a different way, but not via a "promql-like" selector, because it does not make sense to apply regex on golang templates like if they were metrics, it's mixing apples and oranges.

@saswatamcode
Copy link
Member Author

saswatamcode commented Jan 27, 2022

As @bwplotka suggested then, maybe we can keep it in the simplest form and match only non-templated labels in rules (with a change in docs to highlight this)? That way match[] doesn't behave differently from other APIs and we don't apply regex on templates. So match[] in api/v1/rules will only match non-templated labels in rules (currently not adding it in /api/v1/alerts). WDYT @roidelapluie? 🙂

@roidelapluie
Copy link
Member

I trust Bartek's judgment, let's document this properly.

@saswatamcode
Copy link
Member Author

saswatamcode commented Jan 28, 2022

I have updated this PR with a doc change. Now only api/v1/rules support matchers and that too for non-templated label values only (approach for detecting templating is using parser node type, but can be changed to a regex-based one)! 🙂

Also, test failure seems unrelated, TestQueryConcurrency in promql/engine_test.go fails in test_windows but haven't been able to reproduce it locally. Relevant log lines here. Maybe running into #6672?

@saswatamcode
Copy link
Member Author

Is there anything else that seems to be missing or is blocking this PR, @roidelapluie? Would love to progress on this! 🙂

@gotjosh gotjosh self-requested a review May 25, 2023 16:59
@roidelapluie roidelapluie self-assigned this Aug 8, 2023
@qinxx108
Copy link
Contributor

qinxx108 commented Oct 3, 2023

Regarding to only match non-templated labels in rules. From user usage perspective, i should be able to filter based on what i configured? For example as in the test cases, if my rule have a label
Name: "templatedlabel", Value: "{{ $externalURL }}"
If i search for templatedlabel= {{ $externalURL }}, it should return to me the rules that has templatedlabel= {{ $externalURL }}

@saswatamcode
Copy link
Member Author

Hmm, not sure why the test/build fails here...maybe due to stringlabels?

@alvinlin123
Copy link
Contributor

Regarding to only match non-templated labels in rules. From user usage perspective, i should be able to filter based on what i configured? For example as in the test cases, if my rule have a label Name: "templatedlabel", Value: "{{ $externalURL }}" If i search for templatedlabel= {{ $externalURL }}, it should return to me the rules that has templatedlabel= {{ $externalURL }}

I agree with this. While I understand @roidelapluie view about the semantic of match for templated string, as @bwplotka said "...Rules API is all about loaded configured" so it makes perfect sense the filter parameter works against whatever is configured, which includes the templated string. As a system admin, there are legit use cases where I want to do something like "gimme all the rule definition that has {{ $someTypo }}" because I made a boo boo and I want to production impact analysis and fix the issue.

For

maybe we can keep it in the simplest form and match only non-templated labels in rules

I am against this because it's not intuitive. Sure we can document it, but I think it's simpler for the the suer to understand "the filter works against template string" than "if the value is a template string then ... otherwise ...". Math only non-templated labels seems like an inconsistent behaviour to me.

@roidelapluie
Copy link
Member

Okay.

@alvinlin123
Copy link
Contributor

Okay

Love the conciseness :D

@bboreham
Copy link
Member

bboreham commented Oct 9, 2023

Hmm, not sure why the test/build fails here...maybe due to stringlabels?

The error log says:

rules/manager.go:467:23: cannot range over l (variable of type labels.Labels)
rules/manager.go:485:24: cannot range over l (variable of type labels.Labels)

It was never a great idea to assume labels.Labels was a slice, and #10991 made this concrete.

You could use code like this:

func (s Selector) Matches(labels Labels) bool {
for _, m := range s {
if v := labels.Get(m.Name); !m.Matches(v) {
return false
}
}
return true
}

@saswatamcode
Copy link
Member Author

Thanks @bboreham!

@alvinlin123 / @roidelapluie let me know, if we should remove the templated labels check here then.

@roidelapluie
Copy link
Member

Yes please

@saswatamcode
Copy link
Member Author

Done!

rules/manager.go Outdated
var ok bool
for _, matchers := range matcherSets {
if matches(lbls, matchers...) {
ok = true
Copy link
Member

Choose a reason for hiding this comment

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

we should do the opposite. I expect that ALL matchers should match

Copy link
Contributor

@qinxx108 qinxx108 Dec 27, 2023

Choose a reason for hiding this comment

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

the other query parameters for example
rule_name[], rule_group[], and file[] are doing
"If the parameter is repeated, rules with any of the provided rule group names are returned." should we follow this behavior as well for the new match parameter?
Reference:
https://github.com/prometheus/prometheus/pull/12270/files

Copy link
Member

Choose a reason for hiding this comment

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

My expectation is that all the Matchers in each []*labels.Matcher will be ANDed, and then the set of those will be ORed. I think this is what we do elsewhere.
It could be made clearer in comments.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup, I think this is what we are doing here. matches ANDs all the matchers in each set i.e return false if any of them don't match, and then matchesMatcherSet takes the set of those results and ORs them i.e returns true if any of them are true. Added a comment for this.

rules/manager.go Outdated
return true
}

var ok bool
Copy link
Member

Choose a reason for hiding this comment

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

should be true by default

@qinxx108
Copy link
Contributor

@roidelapluie could you please take a look at this pr again? Thanks

Copy link
Member

@bboreham bboreham left a comment

Choose a reason for hiding this comment

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

Code looks broadly fine; I made some small notes in places.

A major use case for this is multi-tenant applications built on Prometheus

Having worked on Cortex and Mimir, I don't understand this part. Both of them take a tenant ID in the request, and return rules only for that tenant.

Can you plese update the description to match what you want to get merged?

rules/manager.go Outdated
var ok bool
for _, matchers := range matcherSets {
if matches(lbls, matchers...) {
ok = true
Copy link
Member

Choose a reason for hiding this comment

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

My expectation is that all the Matchers in each []*labels.Matcher will be ANDed, and then the set of those will be ORed. I think this is what we do elsewhere.
It could be made clearer in comments.

@alvinlin123
Copy link
Contributor

A major use case for this is multi-tenant applications built on Prometheus
Having worked on Cortex and Mimir, I don't understand this part. Both of them take a tenant ID in the request, and return rules only for that tenant.
Can you plese update the description to match what you want to get merged?

Hi @bboreham! Long time no "see"!

Yea initially I found this use case head scratching too. But I think the original author is implementing some kind of "poor man's multi-tenancy" on top of just Prometheus using just labelling convention for metrics and rules.

@saswatamcode
Copy link
Member Author

I think the original author is implementing some kind of "poor man's multi-tenancy" on top of just Prometheus using just labelling convention for metrics and rules

That's correct, this is what the PR aims to do! We already kind of have this in Thanos, and can just use a proxy in front to ensure rules with a particular tenant label get returned, without having to maintain the notion of tenancy internally.

This isn't a new pattern I guess and can extend beyond tenancy. Even projects like prom-label-proxy need to modify rules response and filter currently, when just setting a match[] param would be more convenient.

Can you please update the description to match what you want to get merged?

The original description would still be valid I think, but I'm happy to change it to something more suitable. Open to any suggestions cc: @qinxx108 🙂

@bboreham
Copy link
Member

The original description would still be valid I think,

I say this statement is not true, given Cortex etc. manage to do it:

multi-tenant applications built on Prometheus [...] Currently, this is only possible by filtering the API response

@bwplotka
Copy link
Member

(During Prometheus bug scrub meeting)

Just to make sure it's clear: Sounds like maintainers would accept such a change, looks like there are two use cases (workable UI and label-based multi-tenancy).

@saswatamcode
Copy link
Member Author

Thanks! Have updated it to:

Currently, one possible way of doing this is by filtering the API response.

@qinxx108
Copy link
Contributor

qinxx108 commented Feb 5, 2024

@saswatamcode @roidelapluie @bboreham I've addressed the comments. Please take another look if you have time!

Ty!

@yeya24
Copy link
Contributor

yeya24 commented Jul 9, 2024

Hi Prometheus maintainers @bboreham @roidelapluie @bwplotka, it looks like there is a concensus to accept this change. It would be great help if any of the maintainer could take a look. Thanks!

@bwplotka
Copy link
Member

(https://cloud-native.slack.com/archives/C01AUBA4PFE/p1720546903110739) discussion why it's not merged. TL;DR: Comments not adresseed (plus now needs rebase).

But generally looks good, just let's agree on implementation and defaults.

saswatamcode and others added 8 commits July 10, 2024 10:47
Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>
Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>
Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>
Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>
Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>
Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>
Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Copy link
Member

@bwplotka bwplotka left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@bwplotka bwplotka merged commit 398f42d into prometheus:main Jul 10, 2024
kushalShukla-web pushed a commit to kushalShukla-web/prometheus that referenced this pull request Jul 23, 2024
* Add label-matcher support to Rules API

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Implement suggestions

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Match any matcherSet instead of all

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Don't treat labels.Labels as slice

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Remove non-templated check and fix tests

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Update docs

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* fix comments

Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* fix comment

Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Add comment for matching logic, fix tests after rebase

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>

---------

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>
Co-authored-by: Yijie Qin <qinyijie@amazon.com>
Signed-off-by: kushagra Shukla <kushalshukla110@gmail.com>
kushalShukla-web pushed a commit to kushalShukla-web/prometheus that referenced this pull request Jul 25, 2024
* Add label-matcher support to Rules API

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Implement suggestions

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Match any matcherSet instead of all

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Don't treat labels.Labels as slice

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Remove non-templated check and fix tests

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Update docs

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* fix comments

Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* fix comment

Signed-off-by: Yijie Qin <qinyijie@amazon.com>

* Add comment for matching logic, fix tests after rebase

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>

---------

Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Yijie Qin <qinyijie@amazon.com>
Co-authored-by: Yijie Qin <qinyijie@amazon.com>
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.

Rules API: support label-based matcher. [Feature Request]

7 participants