diff --git a/tsdb/block.go b/tsdb/block.go index 83b86a58d..d2e7aa6fa 100644 --- a/tsdb/block.go +++ b/tsdb/block.go @@ -103,9 +103,9 @@ type IndexReader interface { // storage.ErrNotFound is returned as error. LabelValueFor(ctx context.Context, id storage.SeriesRef, label string) (string, error) - // LabelNamesFor returns all the label names for the series referred to by IDs. + // LabelNamesFor returns all the label names for the series referred to by the postings. // The names returned are sorted. - LabelNamesFor(ctx context.Context, ids ...storage.SeriesRef) ([]string, error) + LabelNamesFor(ctx context.Context, postings index.Postings) ([]string, error) // Close releases the underlying resources of the reader. Close() error @@ -551,10 +551,10 @@ func (r blockIndexReader) LabelValueFor(ctx context.Context, id storage.SeriesRe return r.ir.LabelValueFor(ctx, id, label) } -// LabelNamesFor returns all the label names for the series referred to by IDs. +// LabelNamesFor returns all the label names for the series referred to by the postings. // The names returned are sorted. -func (r blockIndexReader) LabelNamesFor(ctx context.Context, ids ...storage.SeriesRef) ([]string, error) { - return r.ir.LabelNamesFor(ctx, ids...) +func (r blockIndexReader) LabelNamesFor(ctx context.Context, postings index.Postings) ([]string, error) { + return r.ir.LabelNamesFor(ctx, postings) } type blockTombstoneReader struct { diff --git a/tsdb/head_read.go b/tsdb/head_read.go index c53e10956..689972f1b 100644 --- a/tsdb/head_read.go +++ b/tsdb/head_read.go @@ -267,15 +267,17 @@ func (h *headIndexReader) LabelValueFor(_ context.Context, id storage.SeriesRef, return value, nil } -// LabelNamesFor returns all the label names for the series referred to by IDs. +// LabelNamesFor returns all the label names for the series referred to by the postings. // The names returned are sorted. -func (h *headIndexReader) LabelNamesFor(ctx context.Context, ids ...storage.SeriesRef) ([]string, error) { +func (h *headIndexReader) LabelNamesFor(ctx context.Context, series index.Postings) ([]string, error) { namesMap := make(map[string]struct{}) - for _, id := range ids { - if ctx.Err() != nil { + i := 0 + for series.Next() { + i++ + if i%checkContextEveryNIterations == 0 && ctx.Err() != nil { return nil, ctx.Err() } - memSeries := h.head.series.getByID(chunks.HeadSeriesRef(id)) + memSeries := h.head.series.getByID(chunks.HeadSeriesRef(series.At())) if memSeries == nil { // Series not found, this happens during compaction, // when series was garbage collected after the caller got the series IDs. @@ -285,6 +287,9 @@ func (h *headIndexReader) LabelNamesFor(ctx context.Context, ids ...storage.Seri namesMap[lbl.Name] = struct{}{} }) } + if err := series.Err(); err != nil { + return nil, err + } names := make([]string, 0, len(namesMap)) for name := range namesMap { names = append(names, name) diff --git a/tsdb/index/index.go b/tsdb/index/index.go index 480e6a8fc..8172b81ce 100644 --- a/tsdb/index/index.go +++ b/tsdb/index/index.go @@ -1551,11 +1551,14 @@ func (r *Reader) LabelValues(ctx context.Context, name string, matchers ...*labe // LabelNamesFor returns all the label names for the series referred to by IDs. // The names returned are sorted. -func (r *Reader) LabelNamesFor(ctx context.Context, ids ...storage.SeriesRef) ([]string, error) { +func (r *Reader) LabelNamesFor(ctx context.Context, postings Postings) ([]string, error) { // Gather offsetsMap the name offsetsMap in the symbol table first offsetsMap := make(map[uint32]struct{}) - for _, id := range ids { - if ctx.Err() != nil { + i := 0 + for postings.Next() { + id := postings.At() + + if i%checkContextEveryNIterations == 0 && ctx.Err() != nil { return nil, ctx.Err() } diff --git a/tsdb/ooo_head_read.go b/tsdb/ooo_head_read.go index af431d678..3b5adf80c 100644 --- a/tsdb/ooo_head_read.go +++ b/tsdb/ooo_head_read.go @@ -483,7 +483,7 @@ func (ir *OOOCompactionHeadIndexReader) LabelValueFor(context.Context, storage.S return "", errors.New("not implemented") } -func (ir *OOOCompactionHeadIndexReader) LabelNamesFor(ctx context.Context, ids ...storage.SeriesRef) ([]string, error) { +func (ir *OOOCompactionHeadIndexReader) LabelNamesFor(ctx context.Context, postings index.Postings) ([]string, error) { return nil, errors.New("not implemented") } diff --git a/tsdb/querier.go b/tsdb/querier.go index 1071c4a71..fb4a87cc8 100644 --- a/tsdb/querier.go +++ b/tsdb/querier.go @@ -447,16 +447,7 @@ func labelNamesWithMatchers(ctx context.Context, r IndexReader, matchers ...*lab if err != nil { return nil, err } - - var postings []storage.SeriesRef - for p.Next() { - postings = append(postings, p.At()) - } - if err := p.Err(); err != nil { - return nil, fmt.Errorf("postings for label names with matchers: %w", err) - } - - return r.LabelNamesFor(ctx, postings...) + return r.LabelNamesFor(ctx, p) } // seriesData, used inside other iterators, are updated when we move from one series to another. diff --git a/tsdb/querier_test.go b/tsdb/querier_test.go index c7e60a0e1..a1af49465 100644 --- a/tsdb/querier_test.go +++ b/tsdb/querier_test.go @@ -2292,13 +2292,16 @@ func (m mockIndex) LabelValueFor(_ context.Context, id storage.SeriesRef, label return m.series[id].l.Get(label), nil } -func (m mockIndex) LabelNamesFor(ctx context.Context, ids ...storage.SeriesRef) ([]string, error) { +func (m mockIndex) LabelNamesFor(_ context.Context, postings index.Postings) ([]string, error) { namesMap := make(map[string]bool) - for _, id := range ids { - m.series[id].l.Range(func(lbl labels.Label) { + for postings.Next() { + m.series[postings.At()].l.Range(func(lbl labels.Label) { namesMap[lbl.Name] = true }) } + if err := postings.Err(); err != nil { + return nil, err + } names := make([]string, 0, len(namesMap)) for name := range namesMap { names = append(names, name) @@ -3232,7 +3235,7 @@ func (m mockMatcherIndex) LabelValueFor(context.Context, storage.SeriesRef, stri return "", errors.New("label value for called") } -func (m mockMatcherIndex) LabelNamesFor(ctx context.Context, ids ...storage.SeriesRef) ([]string, error) { +func (m mockMatcherIndex) LabelNamesFor(ctx context.Context, postings index.Postings) ([]string, error) { return nil, errors.New("label names for for called") } @@ -3693,7 +3696,7 @@ func (m mockReaderOfLabels) LabelNames(context.Context, ...*labels.Matcher) ([]s panic("LabelNames called") } -func (m mockReaderOfLabels) LabelNamesFor(context.Context, ...storage.SeriesRef) ([]string, error) { +func (m mockReaderOfLabels) LabelNamesFor(context.Context, index.Postings) ([]string, error) { panic("LabelNamesFor called") }