Select implements storage.Querier interface. The bool passed is ignored because the series is always sorted.
(ctx context.Context, sortSeries bool, sp *storage.SelectHints, matchers ...*labels.Matcher)
| 384 | // Select implements storage.Querier interface. |
| 385 | // The bool passed is ignored because the series is always sorted. |
| 386 | func (q querier) Select(ctx context.Context, sortSeries bool, sp *storage.SelectHints, matchers ...*labels.Matcher) storage.SeriesSet { |
| 387 | ctx, stats, userID, mint, maxt, metadataQuerier, queriers, err := q.setupFromCtx(ctx) |
| 388 | if err == errEmptyTimeRange { |
| 389 | return storage.EmptySeriesSet() |
| 390 | } else if err != nil { |
| 391 | return storage.ErrSeriesSet(err) |
| 392 | } |
| 393 | startT := time.Now() |
| 394 | defer func() { |
| 395 | stats.AddQueryStorageWallTime(time.Since(startT)) |
| 396 | }() |
| 397 | |
| 398 | log, ctx := spanlogger.New(ctx, "querier.Select") |
| 399 | defer log.Finish() |
| 400 | |
| 401 | if sp != nil { |
| 402 | level.Debug(log).Log("start", util.TimeFromMillis(sp.Start).UTC().String(), "end", util.TimeFromMillis(sp.End).UTC().String(), "step", sp.Step, "matchers", matchers) |
| 403 | } |
| 404 | |
| 405 | if sp == nil { |
| 406 | mint, maxt, err = validateQueryTimeRange(ctx, userID, mint, maxt, q.limits, q.maxQueryIntoFuture) |
| 407 | if err == errEmptyTimeRange { |
| 408 | return storage.EmptySeriesSet() |
| 409 | } else if err != nil { |
| 410 | return storage.ErrSeriesSet(err) |
| 411 | } |
| 412 | // if SelectHints is null, rely on minT, maxT of querier to scope in range for Select stmt |
| 413 | sp = &storage.SelectHints{Start: mint, End: maxt} |
| 414 | } |
| 415 | |
| 416 | // Validate query time range. Even if the time range has already been validated when we created |
| 417 | // the querier, we need to check it again here because the time range specified in hints may be |
| 418 | // different. |
| 419 | startMs, endMs, err := validateQueryTimeRange(ctx, userID, sp.Start, sp.End, q.limits, q.maxQueryIntoFuture) |
| 420 | if err == errEmptyTimeRange { |
| 421 | return storage.NoopSeriesSet() |
| 422 | } else if err != nil { |
| 423 | return storage.ErrSeriesSet(err) |
| 424 | } |
| 425 | |
| 426 | // The time range may have been manipulated during the validation, |
| 427 | // so we make sure changes are reflected back to hints. |
| 428 | sp.Start = startMs |
| 429 | sp.End = endMs |
| 430 | getSeries := sp.Func == "series" |
| 431 | |
| 432 | // For series queries without specifying the start time, we prefer to |
| 433 | // only query ingesters and not to query maxQueryLength to avoid OOM kill. |
| 434 | if getSeries && startMs == 0 { |
| 435 | return metadataQuerier.Select(ctx, true, sp, matchers...) |
| 436 | } |
| 437 | |
| 438 | startTime := model.Time(startMs) |
| 439 | endTime := model.Time(endMs) |
| 440 | |
| 441 | // Validate query time range. This validation for instant / range queries can be done either at Query Frontend |
| 442 | // or here at Querier. When the check is done at Query Frontend, we still want to enforce the max query length |
| 443 | // check for /api/v1/series request since there is no specific tripperware for series. |