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

Set OpenMetrics content header #1974

Merged
merged 1 commit into from
Feb 9, 2023
Merged

Conversation

mrueg
Copy link
Member

@mrueg mrueg commented Feb 3, 2023

What this PR does / why we need it:

This change will expose metrics in openmetrics' format (basically just adding the right content header), as otherwise info and stateset type metrics won't be recognized by prometheus.

See: https://github.com/prometheus/common/blob/main/expfmt/encode.go#L86

See: #1973

How does this change affect the cardinality of KSM: (increases, decreases or does not change cardinality)
None

Which issue(s) this PR fixes (optional, in fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when PR gets merged):
Fixes #1973

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. labels Feb 3, 2023
@k8s-ci-robot
Copy link
Contributor

This issue is currently awaiting triage.

If kube-state-metrics contributors determine this is a relevant issue, they will accept it by applying the triage/accepted label and provide further guidance.

The triage/accepted label can be added by org members by writing /triage accepted in a comment.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@k8s-ci-robot k8s-ci-robot added approved Indicates a PR has been approved by an approver from all required OWNERS files. size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. labels Feb 3, 2023
@dgrisonnet
Copy link
Member

Can we really support OpenMetrics without changing the output of kube-state-metrics? The OpenMetrics format is slighly different from the Prometheus one that we currently hardcode

@mrueg
Copy link
Member Author

mrueg commented Feb 3, 2023

@dgrisonnet good idea to check it again.

https://www.robustperception.io/checking-openmetrics-output-is-valid/

I used the check above and added a # EOF to our custom metrics writing path.

Edit:
I've disabled OpenMetrics on the telemetry exporter due to prometheus/client_golang#829

@mrueg mrueg force-pushed the openmetrics branch 2 times, most recently from b0b4b7b to 47c7427 Compare February 3, 2023 15:00
@@ -183,7 +183,7 @@ func (m *MetricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
resHeader := w.Header()
var writer io.Writer = w

resHeader.Set("Content-Type", `text/plain; version=`+"0.0.4")
resHeader.Set("Content-Type", `application/openmetrics-text; version=`+"0.0.1"+`; charset=utf-8`)
Copy link
Member

@dgrisonnet dgrisonnet Feb 3, 2023

Choose a reason for hiding this comment

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

I wonder if we should really do that by default. I would only expect us to modify the content type when an OpenMetrics option is enabled. Otherwise we could break existing proxies only allowing text/plain content type.

Copy link
Member Author

@mrueg mrueg Feb 3, 2023

Choose a reason for hiding this comment

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

moved it to the main thread, since this change is outdated.

@k8s-ci-robot k8s-ci-robot added size/S Denotes a PR that changes 10-29 lines, ignoring generated files. and removed size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. labels Feb 3, 2023
@mrueg
Copy link
Member Author

mrueg commented Feb 3, 2023

I've changed the implementation to use the expfmt negotiation.

You can test it with:
curl -v --header "Accept: application/openmetrics-text"

curl -v --header "Accept:text/plain"

Be aware that this can still generate invalid prometheus format (see #1973) in case the client requests application/text and info/stateset metrics are requested. This might be more difficult to solve as we would need to go through all metrics before writing them and replace the metric type based on the client's request.

@CatherineF-dev
Copy link
Contributor

CatherineF-dev commented Feb 7, 2023

Once encountered some issues with open-telemetry + openmetrics. Maybe add a feature-gate for OpenMetrics content header?
(In remembering which tricky issue)

@mrueg
Copy link
Member Author

mrueg commented Feb 7, 2023

Once encountered some issues with open-telemetry + openmetrics. Maybe add a feature-gate for OpenMetrics content header? (In remembering which tricky issue)

I would like to avoid adding that if possible as the client already has a way to negotiate by presenting the txtFmt Accept Header.

Copy link
Member

@dgrisonnet dgrisonnet left a comment

Choose a reason for hiding this comment

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

Nice one. I was gonna suggest to use expfmt negociation but you already made that change.

We should add a simple e2e test as a follow-up.

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Feb 9, 2023
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: dgrisonnet, mrueg

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@Joseph-Irving
Copy link
Member

I just thought I'd mention this issue prometheus/prometheus#12121 as I think it may be related to this PR.

@CatherineF-dev
Copy link
Contributor

Could you help test the issue will be gone without this PR? cc @Joseph-Irving

@CatherineF-dev
Copy link
Contributor

Or could provide steps to reproduce this issue? Thanks!

@Joseph-Irving
Copy link
Member

So I can reproduce this just on minikube with the standard helm prometheus, chart https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus

I ran

helm install prometheus prometheus-community/prometheus --set server.extraFlags={"enable-feature=native-histograms"} --version=19.7.2

This deploys kube-state-metrics version: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.8.0
And Prometheus version: quay.io/prometheus/prometheus:v2.41.0
With the --enable-feature=native-histograms set.

This Prometheus fails to scrape Kube-state-metrics with the error: proto: wrong wireType = 0 for field Metric
I rebuilt Kube-state-metrics without this PR and it started working as normal.

As I mentioned in the Prom issue prometheus/prometheus#12121 (comment) when this feature is turned on it changes the headers for Prometheus scrapes.

@Joseph-Irving
Copy link
Member

Joseph-Irving commented Mar 13, 2023

So I think the issue, is that when you enable Native Histograms Prometheus is sending headers with a content type of:

content type: %v application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited

Which we're then mirroring in our headers:

resHeader.Set("Content-Type", string(contentType))

But we're not actually changing our response so we're replying with invalid protobuf hence the error from Prometheus.

I did this as a simple workaround and it fixed the issue:

if contentType == expfmt.FmtProtoDelim {
    resHeader.Set("Content-Type", `text/plain; version=`+"0.0.4")
} else {
    resHeader.Set("Content-Type", string(contentType))
}

However I'm not sure this is the right approach, is it intended that kube-state-metrics always responds with content headers that match the request? Or was this just a change for Open Metrics? In which case perhaps the header should only get changed if the contentType == expfmt.FmtOpenMetric?

@Joseph-Irving
Copy link
Member

I can create a new issue for this if desired btw, sorry for hijacking this old PR

@CatherineF-dev
Copy link
Contributor

Yes, could you create a new issue? Thx!

@Joseph-Irving
Copy link
Member

Ok I've opened a new issue #2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. size/S Denotes a PR that changes 10-29 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CustomResourceMetrics info and stateset are now broken in main when scraping with prometheus
5 participants