Repository: prometheus/prometheus
File: storage/merge.go (Go)

Code before:
}

type labelGenericQueriers []genericQuerier

func (l labelGenericQueriers) Len() int               { return len(l) }
func (l labelGenericQueriers) Get(i int) LabelQuerier { return l[i] }
func (l labelGenericQueriers) SplitByHalf() (labelGenericQueriers, labelGenericQueriers) {
	i := len(l) / 2
	return l[:i], l[i:]
}

// LabelValues returns all potential values for a label name.
// If matchers are specified the returned result set is reduced
// to label values of metrics matching the matchers.
func (q *mergeGenericQuerier) LabelValues(ctx context.Context, name string, hints *LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) {
	res, ws, err := q.mergeResults(q.queriers, hints, func(q LabelQuerier) ([]string, annotations.Annotations, error) {
		return q.LabelValues(ctx, name, hints, matchers...)
	})
	if err != nil {
		return nil, nil, fmt.Errorf("LabelValues() from merge generic querier for label %s: %w", name, err)
	}
	return res, ws, nil
}

// mergeResults performs merge sort for results from multiple queriers.
func (q *mergeGenericQuerier) mergeResults(lq labelGenericQueriers, hints *LabelHints, resultsFn func(q LabelQuerier) ([]string, annotations.Annotations, error)) ([]string, annotations.Annotations, error) {
	if lq.Len() == 0 {
		return nil, nil, nil
	}
	if lq.Len() == 1 {
		return resultsFn(lq.Get(0))
	}
	a, b := lq.SplitByHalf()

	var ws annotations.Annotations
	s1, w, err := q.mergeResults(a, hints, resultsFn)
	ws.Merge(w)
	if err != nil {
		return nil, ws, err
	}
	s2, ws, err := q.mergeResults(b, hints, resultsFn)
	ws.Merge(w)
	if err != nil {
		return nil, ws, err
	}

	s1 = truncateToLimit(s1, hints)
	s2 = truncateToLimit(s2, hints)

	merged := mergeStrings(s1, s2)
	merged = truncateToLimit(merged, hints)

Review comment (bug):
Maybe this should be `SortedLabelValues()` ?  

(Not something you changed; probably broken by #7448)

Code after:
	}()

	for r := range seriesSetChan {
		seriesSets = append(seriesSets, r)
	}
	return &lazyGenericSeriesSet{init: func() (genericSeriesSet, bool) {
		s := newGenericMergeSeriesSet(seriesSets, limit, q.mergeFn)
		return s, s.Next()
	}}
}

type labelGenericQueriers []genericQuerier

func (l labelGenericQueriers) Len() int               { return len(l) }
func (l labelGenericQueriers) Get(i int) LabelQuerier { return l[i] }
func (l labelGenericQueriers) SplitByHalf() (labelGenericQueriers, labelGenericQueriers) {
	i := len(l) / 2
	return l[:i], l[i:]
}

// LabelValues returns all potential values for a label name.
// If matchers are specified the returned result set is reduced
// to label values of metrics matching the matchers.
func (q *mergeGenericQuerier) LabelValues(ctx context.Context, name string, hints *LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) {
	res, ws, err := q.mergeResults(q.queriers, hints, func(q LabelQuerier) ([]string, annotations.Annotations, error) {
		return q.LabelValues(ctx, name, hints, matchers...)
	})
	if err != nil {
		return nil, nil, fmt.Errorf("LabelValues() from merge generic querier for label %s: %w", name, err)
	}
	return res, ws, nil
}

// mergeResults performs merge sort on the results of invoking the resultsFn against multiple queriers.
func (q *mergeGenericQuerier) mergeResults(lq labelGenericQueriers, hints *LabelHints, resultsFn func(q LabelQuerier) ([]string, annotations.Annotations, error)) ([]string, annotations.Annotations, error) {
	if lq.Len() == 0 {
		return nil, nil, nil
	}
	if lq.Len() == 1 {
		return resultsFn(lq.Get(0))
	}
	a, b := lq.SplitByHalf()

	var ws annotations.Annotations
	s1, w, err := q.mergeResults(a, hints, resultsFn)
	ws.Merge(w)
	if err != nil {
		return nil, ws, err
	}
	s2, w, err := q.mergeResults(b, hints, resultsFn)
	ws.Merge(w)