LabelValues implements storage.Querier.
(ctx context.Context, name string, hints *storage.LabelHints, matchers ...*labels.Matcher)
| 484 | |
| 485 | // LabelValues implements storage.Querier. |
| 486 | func (q querier) LabelValues(ctx context.Context, name string, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { |
| 487 | ctx, stats, userID, mint, maxt, metadataQuerier, queriers, err := q.setupFromCtx(ctx) |
| 488 | if err == errEmptyTimeRange { |
| 489 | return nil, nil, nil |
| 490 | } else if err != nil { |
| 491 | return nil, nil, err |
| 492 | } |
| 493 | startT := time.Now() |
| 494 | defer func() { |
| 495 | stats.AddQueryStorageWallTime(time.Since(startT)) |
| 496 | }() |
| 497 | |
| 498 | // For label values queries without specifying the start time, we prefer to |
| 499 | // only query ingesters and not to query maxQueryLength to avoid OOM kill. |
| 500 | if mint == 0 { |
| 501 | return metadataQuerier.LabelValues(ctx, name, hints, matchers...) |
| 502 | } |
| 503 | |
| 504 | startTime := model.Time(mint) |
| 505 | endTime := model.Time(maxt) |
| 506 | |
| 507 | if maxQueryLength := q.limits.MaxQueryLength(userID); maxQueryLength > 0 && endTime.Sub(startTime) > maxQueryLength { |
| 508 | limitErr := validation.LimitError(fmt.Sprintf(validation.ErrQueryTooLong, endTime.Sub(startTime), maxQueryLength)) |
| 509 | return nil, nil, limitErr |
| 510 | } |
| 511 | |
| 512 | if len(queriers) == 1 { |
| 513 | return queriers[0].LabelValues(ctx, name, hints, matchers...) |
| 514 | } |
| 515 | |
| 516 | var ( |
| 517 | g, _ = errgroup.WithContext(ctx) |
| 518 | sets = [][]string{} |
| 519 | warnings = annotations.Annotations(nil) |
| 520 | |
| 521 | resMtx sync.Mutex |
| 522 | ) |
| 523 | |
| 524 | for _, querier := range queriers { |
| 525 | // Need to reassign as the original variable will change and can't be relied on in a goroutine. |
| 526 | g.Go(func() error { |
| 527 | // NB: Values are sorted in Cortex already. |
| 528 | myValues, myWarnings, err := querier.LabelValues(ctx, name, hints, matchers...) |
| 529 | if err != nil { |
| 530 | return err |
| 531 | } |
| 532 | |
| 533 | resMtx.Lock() |
| 534 | sets = append(sets, myValues) |
| 535 | warnings.Merge(myWarnings) |
| 536 | resMtx.Unlock() |
| 537 | |
| 538 | return nil |
| 539 | }) |
| 540 | } |
| 541 | |
| 542 | if err := g.Wait(); err != nil { |
| 543 | return nil, nil, err |
nothing calls this directly
no test coverage detected