-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[metrics_transform_processor] Add filtering capabilities matching metric label values for applying changes #3201
[metrics_transform_processor] Add filtering capabilities matching metric label values for applying changes #3201
Conversation
Codecov Report
@@ Coverage Diff @@
## main #3201 +/- ##
==========================================
- Coverage 91.92% 91.92% -0.01%
==========================================
Files 493 493
Lines 23946 23973 +27
==========================================
+ Hits 22013 22037 +24
- Misses 1427 1429 +2
- Partials 506 507 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
Thanks for this PR @hossain-rayhan, unfortunately we don't want to add new functionality to the metrics transform processor until we change it to use the new pdata instead of the old opencensus |
Hi @bogdandrutu, this is a small addition. I understand the concern but this change truely belongs to this |
Hi @bogdandrutu, expecting a second thought from you considering my reply on your comment. Let me know if it sounds convincing. |
According to our todays (04/28) Collector SIG meetings decision, we will move forward with this PR. I created an issue to rewrite this part to use OTLP metrics instead of OpenCensus metric type. I will work on this when we plan to rewrite the Issue Link to track: #3269 Thanks @bogdandrutu and @alolita |
@bogdandrutu re-assigning to you since you discussed this in SIG meeting. |
Hi @bogdandrutu its blocking our release. A review would be highly appreciated. |
@@ -88,15 +91,18 @@ func (f internalFilterStrict) getSubexpNames() []string { | |||
} | |||
|
|||
type internalFilterRegexp struct { | |||
include *regexp.Regexp | |||
include *regexp.Regexp | |||
matchLabels map[string]string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
matchLabels map[string]string | |
matchLabels map[string]*regexp.Regexp |
Presuming that this internalFilterRegexp
is re-used, it would be better to transform the label matching map values to *regexp.Regexp
once up-front rather than every time we call labelMatched()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
keyFound = true | ||
for _, timeseries := range metric.Timeseries { | ||
if isRegexp { | ||
re := regexp.MustCompile(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be done in the outer loop, not multiple times per filtered label. Ideally, as mentioned above, it would be done once on initialization and re-used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
for idx, label := range metric.MetricDescriptor.LabelKeys { | ||
if label.Key != key { | ||
continue | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the same label key appear multiple times? If not, it might make sense to build a map from label keys to indexes once at the top of this function and look up indexes directly rather than iterating over the label keys array for every filtered label.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically it won't repeat. But as its not a map, we cannot garuntee I think.
} | ||
|
||
// if a label-key is not found and the label-value is non-empty, return false | ||
if !keyFound && !(value == "" || isEmptyExp(value)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this logic matches the description in the comment. It looks like a non-empty label value that is matched by a regexp that could also match an empty label value will hit this condition. What is intended to be tested here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have two different use case here. Say, in our config file we have the following labels to match,
{"container": "my-container"}
where the value of the keycontainer
is non-empty.{"container": ""}
where the value of the keycontainer
is empty-string.
For first case, if we don't find a key, we return false. But for the second case, if we don't find the key, we need to return true which is expected.
As we don't have a way to make sure a given key is not present, I wrote this logic as alternative. If we want to confirm that a given label is not present, we set the value as empty-string.
Hope it helps to explain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the comment to make it more clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
@alolita can you please add the |
if timeseries.LabelValues[idx].Value != value { | ||
return false | ||
} | ||
break |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of this break, isn't only the first time series checked?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. That's I checked for. If the first timeseries matches the label, we will add the metric.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to be explicit about that than use a loop then, loop is for looping
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please rephrase for me? I don't think I understand what you meant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you only want to check the first one can't you use metric.Timeseries[0]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see. Makes sense. Will update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated, thanks.
Hi @anuraaga I need your approval. Would you please have another look. Thanks. |
@tigrannajaryan can we get this merged! Thanks. |
@bogdandrutu what's the resolution on this? I was not present in the SIG meeting where you discussed this (the meeting notes say that it was discussed, but doesn't tell what was decided). |
@bogdandrutu We need to get this merged today (05/10). Can you please merge this. Thanks. |
Signed-off-by: Rayhan Hossain <[email protected]>
Signed-off-by: Rayhan Hossain <[email protected]>
Signed-off-by: Rayhan Hossain <[email protected]>
Signed-off-by: Rayhan Hossain <[email protected]>
Signed-off-by: Rayhan Hossain <[email protected]>
Signed-off-by: Rayhan Hossain <[email protected]>
Signed-off-by: Rayhan Hossain <[email protected]>
Signed-off-by: Rayhan Hossain <[email protected]>
9c29946
to
894f54e
Compare
I just rebased the code so that it passes windows/trace unit tests. |
👍 |
…le (#3201) Signed-off-by: Bogdan Drutu <[email protected]>
Description:
This change adds a new feature which will support to filter metrics and apply changes matching metric names and label values together. Earlier, we were able to filter metrics using only metric names and apply our transforms to all the metrics. This enhanced filtering feature will give a new option to apply changes to a certain set of metrics where we have a match for metric name and specific set of metric labels.
Can you share a use case?
Yes. Using prometheus receiver in Kubernetes, we get same metrics (same name) for containers as well as pods. We can differentiate the metrics using metric label values. In our use cases we need to rename some of the pod level metrics without affecting the container level metrics. Hence, we need an option for applying changes to metircs based on metric names and metric label values together.
Why did you put this change in metricstransformprocessor?
Metrics transform processor already have the insert and update functions. It applies changes to metrics matching the metric name. Its super easy and meaningful to add couple of lines to the filtering options to match metrics using metric label values besides metric names.
Testing:
Wrote Unit tests and tested manually on local machine.
Documentation:
Updated README with proper config examples.