Skip to content

Commit

Permalink
Fix ExternalLabels() for Prometheus v3.0 (#7893)
Browse files Browse the repository at this point in the history
Prometheus v3.0.0-rc.0 introduces a new scrape protocol
(`PrometheusText1.0.0`) which is present by default in the global
configuration. It breaks the Thanos sidecar when it wants to retrieve
the external labels.

This change replaces the use of the Prometheus `GlobalConfig` struct by
a minimal struct which unmarshals only the `external_labels` key.

See also prometheus-operator/prometheus-operator#7078

Signed-off-by: Simon Pasquier <[email protected]>
  • Loading branch information
simonpasquier authored Nov 8, 2024
1 parent 928bc7a commit bfbabbb
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re
- [#7852](https://github.com/thanos-io/thanos/pull/7852) Query Frontend: pass "stats" parameter forward to queriers and fix Prometheus stats merging.
- [#7832](https://github.com/thanos-io/thanos/pull/7832) Query Frontend: Fix cache keys for dynamic split intervals.
- [#7885](https://github.com/thanos-io/thanos/pull/7885) Store: Return chunks to the pool after completing a Series call.
- [#7893](https://github.com/thanos-io/thanos/pull/7893) Sidecar: Fix retrieval of external labels for Prometheus v3.0.0.

### Added
- [#7763](https://github.com/thanos-io/thanos/pull/7763) Ruler: use native histograms for client latency metrics.
Expand Down
7 changes: 4 additions & 3 deletions pkg/promclient/promclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"github.com/pkg/errors"
"github.com/prometheus/common/expfmt"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/config"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/timestamp"
"github.com/prometheus/prometheus/promql"
Expand Down Expand Up @@ -201,13 +200,15 @@ func (c *Client) ExternalLabels(ctx context.Context, base *url.URL) (labels.Labe
return labels.EmptyLabels(), errors.Wrapf(err, "unmarshal response: %v", string(body))
}
var cfg struct {
GlobalConfig config.GlobalConfig `yaml:"global"`
GlobalConfig struct {
ExternalLabels map[string]string `yaml:"external_labels"`
} `yaml:"global"`
}
if err := yaml.Unmarshal([]byte(d.Data.YAML), &cfg); err != nil {
return labels.EmptyLabels(), errors.Wrapf(err, "parse Prometheus config: %v", d.Data.YAML)
}

return cfg.GlobalConfig.ExternalLabels, nil
return labels.FromMap(cfg.GlobalConfig.ExternalLabels), nil
}

type Flags struct {
Expand Down
67 changes: 67 additions & 0 deletions pkg/promclient/promclient_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) The Thanos Authors.
// Licensed under the Apache License 2.0.

// Package promclient offers helper client function for various API endpoints.

package promclient

import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"testing"

"github.com/efficientgo/core/testutil"
)

func TestExternalLabels(t *testing.T) {
for _, tc := range []struct {
name string
response string
err bool
labels map[string]string
}{
{
name: "invalid payload",
response: `{`,
err: true,
},
{
name: "unknown scrape protocol",
response: `{"status":"success","data":{"yaml":"global:\n scrape_interval: 1m\n scrape_timeout: 10s\n scrape_protocols:\n - OpenMetricsText1.0.0\n - OpenMetricsText0.0.1\n - PrometheusText1.0.0\n - PrometheusText0.0.4\n - UnknownScrapeProto\n evaluation_interval: 1m\n external_labels:\n az: \"1\"\n region: eu-west\nruntime:\n gogc: 75\n"}}`,
labels: map[string]string{
"region": "eu-west",
"az": "1",
},
},
{
name: "no external labels",
response: `{"status":"success","data":{"yaml":"global:\n scrape_interval: 1m\n scrape_timeout: 10s\n scrape_protocols:\n - OpenMetricsText1.0.0\n - OpenMetricsText0.0.1\n - PrometheusText1.0.0\n - PrometheusText0.0.4\n - UnknownScrapeProto\n evaluation_interval: 1m\nruntime:\n gogc: 75\n"}}`,
labels: map[string]string{},
},
} {
t.Run(tc.name, func(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, tc.response)
}))
defer ts.Close()

u, err := url.Parse(ts.URL)
testutil.Ok(t, err)

ext, err := NewDefaultClient().ExternalLabels(context.Background(), u)
if tc.err {
testutil.NotOk(t, err)
return
}

testutil.Ok(t, err)
testutil.Equals(t, len(tc.labels), ext.Len())
for k, v := range tc.labels {
testutil.Equals(t, v, ext.Get(k))
}
})
}
}

0 comments on commit bfbabbb

Please sign in to comment.