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

Adding an "instance" tag for the prometheus scraper #9322

Closed
jszwedko opened this issue Sep 23, 2021 Discussed in #9321 · 7 comments · Fixed by #9330
Closed

Adding an "instance" tag for the prometheus scraper #9322

jszwedko opened this issue Sep 23, 2021 Discussed in #9321 · 7 comments · Fixed by #9330
Assignees
Labels
source: prometheus_scrape Anything `prometheus_scrape` source related type: enhancement A value-adding code change that enhances its existing functionality.
Milestone

Comments

@jszwedko
Copy link
Member

Discussed in #9321

Originally posted by candlerb September 23, 2021
I've been playing with the prometheus scraper, and it's pretty awesome:

[sources.node_exporter]
type = "prometheus_scrape"
endpoints = [
  "http://host1:9100/metrics",
  "http://host2:9100/metrics",
]
scrape_interval_secs = 60

# Print scraped metrics to stdout
[sinks.print]
type = "console"
inputs = ["node_exporter"]
encoding.codec = "json"

Scraping works instantly. The problem is that I can't see how to distinguish the metrics originating from different hosts. e.g.

$ vector --config vector-scrape.toml  | grep node_memory_Active_bytes
{"name":"node_memory_Active_bytes","timestamp":"2021-09-23T17:14:30.775368953Z","kind":"absolute","gauge":{"value":1648369664.0}}
{"name":"node_memory_Active_bytes","timestamp":"2021-09-23T17:14:30.817781032Z","kind":"absolute","gauge":{"value":305164288.0}}

Which host does each metric belong to??

With a "real" prometheus server, it would add a label instance="...", which defaults to the __address__ which was scraped.

What's the standard way in Vector of distinguish the same metric from multiple sources: a tag? A namespace? Does that association already exist for prometheus scrapes, but is hidden in the "console" sink output?

I can see that internal metrics have tags.host_key and tags.pid_key, but I don't see anything equivalent for prometheus scraping.

I'm only just getting to grips with the Vector data model, so I apologise if I've missed something obvious.

@jszwedko jszwedko added source: prometheus_scrape Anything `prometheus_scrape` source related type: enhancement A value-adding code change that enhances its existing functionality. labels Sep 23, 2021
@jszwedko jszwedko self-assigned this Sep 23, 2021
@jszwedko jszwedko added this to the Vector 0.17.0 milestone Sep 23, 2021
jszwedko added a commit that referenced this issue Sep 23, 2021
This adds a new configuration, `instance_key`, to the
`prometheus_scrape` source. If set, it will tag scraped metrics with their
instance in the same fashion as the prometheus scraper.

I opted to let users opt into this as this source has been around for
a while and I could see the extra tag causing some users some surprise
as Prometheus, when scraping, if the metric already has `instance`, will
avoid resetting it based on its `honor_labels` configuration.

Ref: https://prometheus.io/docs/concepts/jobs_instances/#automatically-generated-labels-and-time-series

Closes: #9322

Signed-off-by: Jesse Szwedko <jesse@szwedko.me>
@candlerb
Copy link

candlerb commented Sep 24, 2021

If I read the code in #9330 correctly, it is extracting just the host and port out of the endpoint url, correct?

I don't think this logic necessarily needs to be hard-coded. You could have an "endpoint" tag, and let VRL massage it if the user wants it to be more prometheus-like, using parse_url.

However, if this logic is going to be built-in, I have a suggestion: if the URL contains a fragment identifier, then use the fragment as the instance tag instead of the address:port. For example:

endpoints = [
  'http://192.0.2.1:9100/metrics#foo',
  'http://192.0.2.2:9100/metrics#bar',
]

This would set the instance tag to 'foo' and 'bar' respectively for those scrapes, giving meaningful instance labels.

This is the sort of thing which you can do using relabelling in prometheus, but you wouldn't be able to do if the "instance" label has already been stripped down to host and port.

Or you could provide both endpoint_tag and instance_tag.

EDIT: a quick test shows that the fragment is already correctly removed from the path in the HTTP request, i.e. tcpdump shows GET /metrics HTTP/1.1

@jszwedko
Copy link
Member Author

Thanks for the thoughts @candlerb . I was thinking it'd be nice to match the prometheus scraper's concept of instance specifically since Prometheus users are likely to be familiar with it already. I could see adding support for labeling endpoint as well though and then users could use VRL to extract the info they want as usual.

@nivekuil
Copy link

I think this would also address #6953?

I wonder if this would be enough information to infer the job label and be truly prometheus compatible. Can I have a transform that's like a map from endpoint to job name?

@candlerb
Copy link

It looks like this issue is indeed a dupe of #6953, yes.

When you say "infer the job label": the job label is static in prometheus, fixed for all targets in the scrape job. You can do it like this in VRL:

[sources.scrape_node]
type = "prometheus_scrape"
endpoints = [
  'http://192.0.2.1:9100/metrics#foo',
  'http://192.0.2.2:9100/metrics#bar',
]
scrape_interval_secs = 60

[transforms.tag_node]
type = "remap"
inputs = ["scrape_node"]
source = '''
.tags.job = "node"
'''

This ticket is about the instance label, which identifies the individual scraped endpoint.

I'm proposing:

  1. If you set endpoint_tag = "endpoint" then you get the whole URL as the tag
  2. If you set instance_tag = "instance" then you get the URL fragment, or if that doesn't exist, the address and port.

Given (1) you could implement (2) yourself in VRL, using the parse_url() function

@nivekuil
Copy link

nivekuil commented Sep 26, 2021 via email

@candlerb
Copy link

With prometheus, normally you'd set the instance label dynamically using relabelling.

For Vector: yes, if you've captured the whole endpoint URL in a tag, then using VRL to extract just the part that you want to appear in the instance label is straightforward enough. (Or in the job label if you want, or any other label - the logic is whatever you put in VRL)

In some cases, you want the instance label to be different to the target endpoint (e.g. you want a meaningful name in instance but the scrape to be done to a particular IP address and port). Prometheus lets you do this by using relabelling with regexp matches to split __address__ and then create a new __address__ to be scraped.

For Vector, since the endpoint is a URL, there is the "fragment" part of the URL (the bit after #) which can be used for that purpose, as it's not used when generating a scrape.

@jszwedko
Copy link
Member Author

👍 #9330 should satisfy both requirements mentioned in #9322 (comment) . Namely it adds an instance_tag and endpoint_tag configuration.

jszwedko added a commit that referenced this issue Oct 1, 2021
…instance and endpoint (#9330)

* enhancement(prometheus_scrape source): Tag metrics with instance and endpoint

This adds:

* instance_tag to the `prometheus_scrape` source. If set, it will tag scraped metrics with their
instance in the same fashion as the prometheus scraper.
* endpoint_tag which optionally adds the scraped endpoint as a tag per discussion in Adding an "instance" tag for the prometheus scraper #9322 (comment)
* an honor_labels config option which mimics Prometheus's https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config to rename conflicting tags if the scraped source already has them. This is useful if Vector is scraping metrics from another scraper that has already added these tags (e.g. another Vector).

I opted to let users opt into these new tags as this source has been around for
a while and I could see the extra tags causing some users some surprise
as Prometheus, when scraping, if the metric already has `instance`, will
avoid resetting it based on its `honor_labels` configuration.

Ref: https://prometheus.io/docs/concepts/jobs_instances/#automatically-generated-labels-and-time-series

Closes: #9322 

Signed-off-by: Jesse Szwedko <jesse@szwedko.me>
jszwedko added a commit that referenced this issue Oct 8, 2021
…instance and endpoint (#9330)

* enhancement(prometheus_scrape source): Tag metrics with instance and endpoint

This adds:

* instance_tag to the `prometheus_scrape` source. If set, it will tag scraped metrics with their
instance in the same fashion as the prometheus scraper.
* endpoint_tag which optionally adds the scraped endpoint as a tag per discussion in Adding an "instance" tag for the prometheus scraper #9322 (comment)
* an honor_labels config option which mimics Prometheus's https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config to rename conflicting tags if the scraped source already has them. This is useful if Vector is scraping metrics from another scraper that has already added these tags (e.g. another Vector).

I opted to let users opt into these new tags as this source has been around for
a while and I could see the extra tags causing some users some surprise
as Prometheus, when scraping, if the metric already has `instance`, will
avoid resetting it based on its `honor_labels` configuration.

Ref: https://prometheus.io/docs/concepts/jobs_instances/#automatically-generated-labels-and-time-series

Closes: #9322 

Signed-off-by: Jesse Szwedko <jesse@szwedko.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
source: prometheus_scrape Anything `prometheus_scrape` source related type: enhancement A value-adding code change that enhances its existing functionality.
Projects
None yet
3 participants