Skip to content

Commit a4bf103

Browse files
authored
Upgrade Prometheus to LabelNames with matchers (#4380)
* Upgrade Prometheus to LabelNames with matchers Since prometheus/prometheus#9083 prometheus now provides matchers to the LabelNames method on the LabelQuerier interface, so in order to upgrade Prometheus we need to support that. This partially solves #3658 as now the block store queryable uses the LabelNames method with matchers. However, we're still using the ingesters' MetricsForLabelMatchers method to perform the LabelNames w/matchers call on the distributor. That change will be tackled separately as it breaks ingester's contracts and needs to be released with a feature flag to perform a backwards compatible release. Signed-off-by: Oleg Zaytsev <[email protected]> * Updated CHANGELOG.md Signed-off-by: Oleg Zaytsev <[email protected]>
1 parent 0fd5bdd commit a4bf103

31 files changed

+413
-109
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
* `-store-gateway.sharding-ring.heartbeat-period`
2727
* [ENHANCEMENT] Memberlist: optimized receive path for processing ring state updates, to help reduce CPU utilization in large clusters. #4345
2828
* [ENHANCEMENT] Memberlist: expose configuration of memberlist packet compression via `-memberlist.compression=enabled`. #4346
29+
* [ENHANCEMENT] Updated Prometheus to include changes from prometheus/prometheus#9083. Now whenever `/labels` API calls include matchers, blocks store is queried for `LabelNames` with matchers instead of `Series` calls which was inefficient. #4380
2930
* [BUGFIX] HA Tracker: when cleaning up obsolete elected replicas from KV store, tracker didn't update number of cluster per user correctly. #4336
3031
* [BUGFIX] Ruler: fixed counting of PromQL evaluation errors as user-errors when updating `cortex_ruler_queries_failed_total`. #4335
3132
* [BUGFIX] Ingester: When using block storage, prevent any reads or writes while the ingester is stopping. This will prevent accessing TSDB blocks once they have been already closed. #4304

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ require (
4949
github.com/prometheus/client_golang v1.11.0
5050
github.com/prometheus/client_model v0.2.0
5151
github.com/prometheus/common v0.29.0
52-
github.com/prometheus/prometheus v1.8.2-0.20210720084720-59d02b5ef003
52+
github.com/prometheus/prometheus v1.8.2-0.20210720123808-b1ed4a0a663d
5353
github.com/segmentio/fasthash v0.0.0-20180216231524-a72b379d632e
5454
github.com/sony/gobreaker v0.4.1
5555
github.com/spf13/afero v1.2.2

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,8 +1529,8 @@ github.com/prometheus/prometheus v1.8.2-0.20210215121130-6f488061dfb4/go.mod h1:
15291529
github.com/prometheus/prometheus v1.8.2-0.20210315220929-1cba1741828b/go.mod h1:MS/bpdil77lPbfQeKk6OqVQ9OLnpN3Rszd0hka0EOWE=
15301530
github.com/prometheus/prometheus v1.8.2-0.20210324152458-c7a62b95cea0/go.mod h1:sf7j/iAbhZahjeC0s3wwMmp5dksrJ/Za1UKdR+j6Hmw=
15311531
github.com/prometheus/prometheus v1.8.2-0.20210421143221-52df5ef7a3be/go.mod h1:WbIKsp4vWCoPHis5qQfd0QimLOR7qe79roXN5O8U8bs=
1532-
github.com/prometheus/prometheus v1.8.2-0.20210720084720-59d02b5ef003 h1:MYbsDV+OIFLkqwea5oC3jIUp/HxFyXQrvXpw/hooMRQ=
1533-
github.com/prometheus/prometheus v1.8.2-0.20210720084720-59d02b5ef003/go.mod h1:o6V+A4iPEWjLG0rSEKeev3OzfBZwP+ay+4iS4dkfLI4=
1532+
github.com/prometheus/prometheus v1.8.2-0.20210720123808-b1ed4a0a663d h1:UnqZFF2qXa+ctCfbss/J4yn9rTVoTiuawjrokqwt4Hg=
1533+
github.com/prometheus/prometheus v1.8.2-0.20210720123808-b1ed4a0a663d/go.mod h1:o6V+A4iPEWjLG0rSEKeev3OzfBZwP+ay+4iS4dkfLI4=
15341534
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
15351535
github.com/rafaeljusto/redigomock v0.0.0-20190202135759-257e089e14a1/go.mod h1:JaY6n2sDr+z2WTsXkOmNRUfDy6FN0L6Nk7x06ndm4tY=
15361536
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=

pkg/configs/legacy_promql/engine_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,10 @@ func (q *errQuerier) Select(bool, *storage.SelectHints, ...*labels.Matcher) stor
135135
func (q *errQuerier) LabelValues(name string, matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
136136
return nil, nil, q.err
137137
}
138-
func (q *errQuerier) LabelNames() ([]string, storage.Warnings, error) { return nil, nil, q.err }
139-
func (q *errQuerier) Close() error { return q.err }
138+
func (q *errQuerier) LabelNames(matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
139+
return nil, nil, q.err
140+
}
141+
func (q *errQuerier) Close() error { return q.err }
140142

141143
func TestQueryError(t *testing.T) {
142144
engine := NewEngine(nil, nil, 10, 10*time.Second)

pkg/querier/blocks_store_queryable.go

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,15 @@ type BlocksStoreQueryable struct {
136136
subservicesWatcher *services.FailureWatcher
137137
}
138138

139-
func NewBlocksStoreQueryable(stores BlocksStoreSet, finder BlocksFinder, consistency *BlocksConsistencyChecker, limits BlocksStoreLimits, queryStoreAfter time.Duration, logger log.Logger, reg prometheus.Registerer) (*BlocksStoreQueryable, error) {
139+
func NewBlocksStoreQueryable(
140+
stores BlocksStoreSet,
141+
finder BlocksFinder,
142+
consistency *BlocksConsistencyChecker,
143+
limits BlocksStoreLimits,
144+
queryStoreAfter time.Duration,
145+
logger log.Logger,
146+
reg prometheus.Registerer,
147+
) (*BlocksStoreQueryable, error) {
140148
manager, err := services.NewManager(stores, finder)
141149
if err != nil {
142150
return nil, errors.Wrap(err, "register blocks storage queryable subservices")
@@ -317,20 +325,21 @@ func (q *blocksStoreQuerier) Select(_ bool, sp *storage.SelectHints, matchers ..
317325
return q.selectSorted(sp, matchers...)
318326
}
319327

320-
func (q *blocksStoreQuerier) LabelNames() ([]string, storage.Warnings, error) {
328+
func (q *blocksStoreQuerier) LabelNames(matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
321329
spanLog, spanCtx := spanlogger.New(q.ctx, "blocksStoreQuerier.LabelNames")
322330
defer spanLog.Span.Finish()
323331

324332
minT, maxT := q.minT, q.maxT
325333

326334
var (
327-
resMtx sync.Mutex
328-
resNameSets = [][]string{}
329-
resWarnings = storage.Warnings(nil)
335+
resMtx sync.Mutex
336+
resNameSets = [][]string{}
337+
resWarnings = storage.Warnings(nil)
338+
convertedMatchers = convertMatchersToLabelMatcher(matchers)
330339
)
331340

332341
queryFunc := func(clients map[BlocksStoreClient][]ulid.ULID, minT, maxT int64) ([]ulid.ULID, error) {
333-
nameSets, warnings, queriedBlocks, err := q.fetchLabelNamesFromStore(spanCtx, clients, minT, maxT)
342+
nameSets, warnings, queriedBlocks, err := q.fetchLabelNamesFromStore(spanCtx, clients, minT, maxT, convertedMatchers)
334343
if err != nil {
335344
return nil, err
336345
}
@@ -693,6 +702,7 @@ func (q *blocksStoreQuerier) fetchLabelNamesFromStore(
693702
clients map[BlocksStoreClient][]ulid.ULID,
694703
minT int64,
695704
maxT int64,
705+
matchers []storepb.LabelMatcher,
696706
) ([][]string, storage.Warnings, []ulid.ULID, error) {
697707
var (
698708
reqCtx = grpc_metadata.AppendToOutgoingContext(ctx, cortex_tsdb.TenantIDExternalLabel, q.userID)
@@ -711,7 +721,7 @@ func (q *blocksStoreQuerier) fetchLabelNamesFromStore(
711721
blockIDs := blockIDs
712722

713723
g.Go(func() error {
714-
req, err := createLabelNamesRequest(minT, maxT, blockIDs)
724+
req, err := createLabelNamesRequest(minT, maxT, blockIDs, matchers)
715725
if err != nil {
716726
return errors.Wrapf(err, "failed to create label names request")
717727
}
@@ -870,10 +880,11 @@ func createSeriesRequest(minT, maxT int64, matchers []storepb.LabelMatcher, skip
870880
}, nil
871881
}
872882

873-
func createLabelNamesRequest(minT, maxT int64, blockIDs []ulid.ULID) (*storepb.LabelNamesRequest, error) {
883+
func createLabelNamesRequest(minT, maxT int64, blockIDs []ulid.ULID, matchers []storepb.LabelMatcher) (*storepb.LabelNamesRequest, error) {
874884
req := &storepb.LabelNamesRequest{
875-
Start: minT,
876-
End: maxT,
885+
Start: minT,
886+
End: maxT,
887+
Matchers: matchers,
877888
}
878889

879890
// Selectively query only specific blocks.

pkg/querier/chunk_store_queryable.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func (q *chunkStoreQuerier) LabelValues(name string, labels ...*labels.Matcher)
8585
return nil, nil, nil
8686
}
8787

88-
func (q *chunkStoreQuerier) LabelNames() ([]string, storage.Warnings, error) {
88+
func (q *chunkStoreQuerier) LabelNames(matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
8989
return nil, nil, nil
9090
}
9191

pkg/querier/distributor_queryable.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,44 @@ func (q *distributorQuerier) LabelValues(name string, matchers ...*labels.Matche
192192
return lvs, nil, err
193193
}
194194

195-
func (q *distributorQuerier) LabelNames() ([]string, storage.Warnings, error) {
196-
ln, err := q.distributor.LabelNames(q.ctx, model.Time(q.mint), model.Time(q.maxt))
195+
func (q *distributorQuerier) LabelNames(matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
196+
if len(matchers) > 0 {
197+
return q.labelNamesWithMatchers(matchers...)
198+
}
199+
200+
log, ctx := spanlogger.New(q.ctx, "distributorQuerier.LabelNames")
201+
defer log.Span.Finish()
202+
203+
ln, err := q.distributor.LabelNames(ctx, model.Time(q.mint), model.Time(q.maxt))
197204
return ln, nil, err
198205
}
199206

207+
// labelNamesWithMatchers performs the LabelNames call by calling ingester's MetricsForLabelMatchers method
208+
func (q *distributorQuerier) labelNamesWithMatchers(matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
209+
log, ctx := spanlogger.New(q.ctx, "distributorQuerier.labelNamesWithMatchers")
210+
defer log.Span.Finish()
211+
212+
ms, err := q.distributor.MetricsForLabelMatchers(ctx, model.Time(q.mint), model.Time(q.maxt), matchers...)
213+
if err != nil {
214+
return nil, nil, err
215+
}
216+
namesMap := make(map[string]struct{})
217+
218+
for _, m := range ms {
219+
for name := range m.Metric {
220+
namesMap[string(name)] = struct{}{}
221+
}
222+
}
223+
224+
names := make([]string, 0, len(namesMap))
225+
for name := range namesMap {
226+
names = append(names, name)
227+
}
228+
sort.Strings(names)
229+
230+
return names, nil, nil
231+
}
232+
200233
func (q *distributorQuerier) Close() error {
201234
return nil
202235
}

pkg/querier/distributor_queryable_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,30 @@ func verifySeries(t *testing.T, series storage.Series, l labels.Labels, samples
306306
require.False(t, it.Next())
307307
require.Nil(t, it.Err())
308308
}
309+
func TestDistributorQuerier_LabelNames(t *testing.T) {
310+
someMatchers := []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "foo", "bar")}
311+
labelNames := []string{"foo", "job"}
312+
313+
t.Run("with matchers", func(t *testing.T) {
314+
metrics := []metric.Metric{
315+
{Metric: model.Metric{"foo": "bar"}},
316+
{Metric: model.Metric{"job": "baz"}},
317+
{Metric: model.Metric{"job": "baz", "foo": "boom"}},
318+
}
319+
d := &mockDistributor{}
320+
d.On("MetricsForLabelMatchers", mock.Anything, model.Time(mint), model.Time(maxt), someMatchers).
321+
Return(metrics, nil)
322+
323+
queryable := newDistributorQueryable(d, false, nil, 0)
324+
querier, err := queryable.Querier(context.Background(), mint, maxt)
325+
require.NoError(t, err)
326+
327+
names, warnings, err := querier.LabelNames(someMatchers...)
328+
require.NoError(t, err)
329+
assert.Empty(t, warnings)
330+
assert.Equal(t, labelNames, names)
331+
})
332+
}
309333

310334
func convertToChunks(t *testing.T, samples []cortexpb.Sample) []client.Chunk {
311335
// We need to make sure that there is atleast one chunk present,

pkg/querier/duplicates_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func (m testQuerier) LabelValues(name string, matchers ...*labels.Matcher) ([]st
128128
return nil, nil, nil
129129
}
130130

131-
func (m testQuerier) LabelNames() ([]string, storage.Warnings, error) {
131+
func (m testQuerier) LabelNames(matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
132132
return nil, nil, nil
133133
}
134134

pkg/querier/error_translate_queryable.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ func (e errorTranslateQuerier) LabelValues(name string, matchers ...*labels.Matc
125125
return values, warnings, e.fn(err)
126126
}
127127

128-
func (e errorTranslateQuerier) LabelNames() ([]string, storage.Warnings, error) {
129-
values, warnings, err := e.q.LabelNames()
128+
func (e errorTranslateQuerier) LabelNames(matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
129+
values, warnings, err := e.q.LabelNames(matchers...)
130130
return values, warnings, e.fn(err)
131131
}
132132

@@ -149,8 +149,8 @@ func (e errorTranslateChunkQuerier) LabelValues(name string, matchers ...*labels
149149
return values, warnings, e.fn(err)
150150
}
151151

152-
func (e errorTranslateChunkQuerier) LabelNames() ([]string, storage.Warnings, error) {
153-
values, warnings, err := e.q.LabelNames()
152+
func (e errorTranslateChunkQuerier) LabelNames(matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
153+
values, warnings, err := e.q.LabelNames(matchers...)
154154
return values, warnings, e.fn(err)
155155
}
156156

0 commit comments

Comments
 (0)