Skip to content
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

6178 matchers with label values #7496

Closed

Conversation

eklockare
Copy link
Contributor

@eklockare eklockare commented Jul 1, 2020

This PR is for issue #6178

This adds the ability to pass the ´match[]´ parameter to ´/api/v1/label/<label_name>/values´ endpoint.

Example:

curl -s 'http://localhost:9090/api/v1/label/code/values?match[]=promhttp_metric_handler_requests_total%7Bcode%3D%22200%22%7D'

( url decoded: promhttp_metric_handler_requests_total{code="200"} )

{
  "status": "success",
  "data": [
    "200"
  ]
}

Questions:

  • Should labelValuesByMatchers be a method of the queriers to be consistent with LabelValues? I tried that out but ran in to issues, but could have another go at it.
  • Is a seperate unittest for labelValuesByMatchers a good idea? From what I see tests are not run on specific functions of api.go. I did feel like having more labels in my tests but also didn't want to mess with all the other tests cases in api_test.go
  • Build fails, but seems to be unrelated?
Unable to find image 'quay.io/prometheus/golang-builder:1.14-base' locally

Error response from daemon: Get https://quay.io/v2/prometheus/golang-builder/manifests/1.14-base: Get https://quay.io/v2/auth?scope=repository%3Aprometheus%2Fgolang-builder%3Apull&service=quay.io: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

!! exit status 1

Signed-off-by: Erik Klockare <eklockare@gmail.com>
Signed-off-by: Erik Klockare <eklockare@gmail.com>
Signed-off-by: Erik Klockare <eklockare@gmail.com>
Copy link
Contributor

@brian-brazil brian-brazil 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 this is likely to run us into the performance problems in #5547, so we probably want my fix for that in before trying to further use Select purely for metadata.

@@ -320,6 +320,8 @@ URL query parameters:

- `start=<rfc3339 | unix_timestamp>`: Start timestamp. Optional.
- `end=<rfc3339 | unix_timestamp>`: End timestamp. Optional.
- `match[]=<series_selector>`: Repeated series selector argument that selects the
series from which to read the label's values
Copy link
Contributor

Choose a reason for hiding this comment

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

label values.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

// LabelValuesByMatchers uses matchers to filter out matching series, then label values are extracted.
func labelValuesByMatchers(sets []storage.SeriesSet, name string) ([]string, storage.Warnings, error) {
set := storage.NewMergeSeriesSet(sets, storage.ChainedSeriesMerge)
labelValuesMap := make(map[string]string)
Copy link
Contributor

Choose a reason for hiding this comment

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

A map[string]struct{} is the usual way to do a set.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Aha, didn't know, changed to map[string]struct{} 👍

for set.Next() {
series := set.At()
labelValue := series.Labels().Get(name)
// This is to avoid duplicates.
Copy link
Contributor

Choose a reason for hiding this comment

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

You can do a simple assignment and not worry about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, fixed

Signed-off-by: Erik Klockare <eklockare@gmail.com>
Signed-off-by: Erik Klockare <eklockare@gmail.com>
@eklockare
Copy link
Contributor Author

@brian-brazil I'm not familiar with the inner workings of the data loading yet. Does your hint solution make it so that less (or no) data is loaded (i.e. no chunks)? So that we get a larger proportion of metadata over actual data

_, ok := labelValuesMap[labelValue]
if !ok && labelValue != "" {
labelValuesMap[labelValue] = labelValue
if labelValue != "" {
Copy link
Contributor

Choose a reason for hiding this comment

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

The label value can't be empty, if it is that's a bug in the tsdb.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@brian-brazil
Copy link
Contributor

Does your hint solution make it so that less (or no) data is loaded (i.e. no chunks)?

It makes it so the chunks don't end up trashing the page cache. Basically due to this the feature in this PR could cause severe performance problems, so I think we need #5547 fixed first to be safe.

Signed-off-by: Erik Klockare <eklockare@gmail.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.

I would say, let's go for it. It's worth to mention it's not as fast and non-matcher function, but it will do the work just fine.

This PR looks fine to me LGTM! ❤️

I guess we want the same on label_name as well (:

@stale stale bot removed the stale label Oct 21, 2020
@bwplotka
Copy link
Member

Plus we need to fix tests (:

@bwplotka
Copy link
Member

are you available @eklockare ? sorry for long delay! (:

// Get all series which match matchers.
var sets []storage.SeriesSet
for _, mset := range matcherSets {
s := q.Select(false, nil, mset...)
Copy link
Contributor

Choose a reason for hiding this comment

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

You need to pass in a hint here with the series function, otherwise this could trash the page cache.

return nil, warnings, set.Err()
}
// Convert the map to an array.
labelValues := []string{}
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we can use labelValues := make([]string, 0, len(labelValueSet)) here.

@brancz
Copy link
Member

brancz commented Dec 7, 2020

Hey @eklockare, very nice contribution! This seems very close to completion. Do you think you'll have time to resolve the remaining comments? Otherwise I'm happy to continue your work! :)

s := q.Select(false, nil, mset...)
sets = append(sets, s)
}
vals, warnings, err = labelValuesByMatchers(sets, name)
Copy link
Member

Choose a reason for hiding this comment

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

Can we add TODO to extend LabelValues and LabelNames with matches?

Copy link
Member

Choose a reason for hiding this comment

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

I would also prefer if this was done on TSDB level. Last time we discussed this we decided against it, but I'm happy to have that discussion again (I realize that TSDB doesn't work that way today).

@brancz
Copy link
Member

brancz commented Dec 9, 2020

I guess we want the same on label_name as well (:

Side note, label-names are going to work slightly differently, as we need extra logic to ignore label-names that we have an exact matcher for.

@brian-brazil
Copy link
Contributor

Side note, label-names are going to work slightly differently, as we need extra logic to ignore label-names that we have an exact matcher for.

Why's that?

Copy link
Member

@codesome codesome left a comment

Choose a reason for hiding this comment

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

I was discussing this offline with @bwplotka and we think this should be part of TSDB to make it more efficient. Maybe introducing hints for LabelValues similar to Select() which remote storages can also make use of.

@brancz
Copy link
Member

brancz commented Dec 9, 2020

@brian-brazil it doesn't make sense to return a label name that we pass an exact matcher for, isn't that the whole point of passing matchers?

@brian-brazil
Copy link
Contributor

If I have a set of series per a selector, why wouldn't I return all of the label names that have non-empty values among those series?
What you propose doesn't make sense to me semantically. That it appeared as a matcher doesn't change that it is a relevant label name.

@brancz
Copy link
Member

brancz commented Dec 10, 2020

Yeah, thought about it again, and I agree.

@bwplotka
Copy link
Member

Looks like this PR is not active anymore, I heard @yeya24 want to continue this to get this merged 🤗

Hope @eklockare, you are ok with this, we will use your commits as a start 👍🏽

@brian-brazil
Copy link
Contributor

Superseded by #8301

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.

None yet

6 participants