Skip to content

Commit e449374

Browse files
authored
[Querier] Add day range limit for LabelNames and LabelValues (#6233)
1 parent 3f18862 commit e449374

File tree

2 files changed

+91
-2
lines changed

2 files changed

+91
-2
lines changed

pkg/querier/querier.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ func (q querier) Select(ctx context.Context, sortSeries bool, sp *storage.Select
431431

432432
// LabelValues implements storage.Querier.
433433
func (q querier) LabelValues(ctx context.Context, name string, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) {
434-
ctx, stats, _, _, _, _, queriers, err := q.setupFromCtx(ctx)
434+
ctx, stats, userID, mint, maxt, _, queriers, err := q.setupFromCtx(ctx)
435435
if err == errEmptyTimeRange {
436436
return nil, nil, nil
437437
} else if err != nil {
@@ -442,6 +442,14 @@ func (q querier) LabelValues(ctx context.Context, name string, hints *storage.La
442442
stats.AddQueryStorageWallTime(time.Since(startT))
443443
}()
444444

445+
startTime := model.Time(mint)
446+
endTime := model.Time(maxt)
447+
448+
if maxQueryLength := q.limits.MaxQueryLength(userID); maxQueryLength > 0 && endTime.Sub(startTime) > maxQueryLength {
449+
limitErr := validation.LimitError(fmt.Sprintf(validation.ErrQueryTooLong, endTime.Sub(startTime), maxQueryLength))
450+
return nil, nil, limitErr
451+
}
452+
445453
if len(queriers) == 1 {
446454
return queriers[0].LabelValues(ctx, name, hints, matchers...)
447455
}
@@ -481,7 +489,7 @@ func (q querier) LabelValues(ctx context.Context, name string, hints *storage.La
481489
}
482490

483491
func (q querier) LabelNames(ctx context.Context, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) {
484-
ctx, stats, _, _, _, _, queriers, err := q.setupFromCtx(ctx)
492+
ctx, stats, userID, mint, maxt, _, queriers, err := q.setupFromCtx(ctx)
485493
if err == errEmptyTimeRange {
486494
return nil, nil, nil
487495
} else if err != nil {
@@ -492,6 +500,14 @@ func (q querier) LabelNames(ctx context.Context, hints *storage.LabelHints, matc
492500
stats.AddQueryStorageWallTime(time.Since(startT))
493501
}()
494502

503+
startTime := model.Time(mint)
504+
endTime := model.Time(maxt)
505+
506+
if maxQueryLength := q.limits.MaxQueryLength(userID); maxQueryLength > 0 && endTime.Sub(startTime) > maxQueryLength {
507+
limitErr := validation.LimitError(fmt.Sprintf(validation.ErrQueryTooLong, endTime.Sub(startTime), maxQueryLength))
508+
return nil, nil, limitErr
509+
}
510+
495511
if len(queriers) == 1 {
496512
return queriers[0].LabelNames(ctx, hints, matchers...)
497513
}

pkg/querier/querier_test.go

+73
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,79 @@ func TestQuerier_ValidateQueryTimeRange_MaxQueryLength_Series(t *testing.T) {
928928
require.True(t, strings.Contains(ss.Err().Error(), "the query time range exceeds the limit (query length: 721h0m0s, limit: 720h0m0s)"))
929929
}
930930

931+
func TestQuerier_ValidateQueryTimeRange_MaxQueryLength_Labels(t *testing.T) {
932+
t.Parallel()
933+
const maxQueryLength = 30 * 24 * time.Hour
934+
tests := map[string]struct {
935+
startTime time.Time
936+
endTime time.Time
937+
expected error
938+
ignoreMaxQueryLength bool
939+
}{
940+
"time range shorter than maxQueryLength": {
941+
startTime: time.Now().Add(-maxQueryLength).Add(time.Hour),
942+
endTime: time.Now(),
943+
expected: nil,
944+
ignoreMaxQueryLength: false,
945+
},
946+
"time range longer than maxQueryLength": {
947+
startTime: time.Now().Add(-maxQueryLength).Add(-time.Hour),
948+
endTime: time.Now(),
949+
expected: validation.LimitError("expanding series: the query time range exceeds the limit (query length: 721h0m0s, limit: 720h0m0s)"),
950+
ignoreMaxQueryLength: false,
951+
},
952+
"time range longer than maxQueryLength and ignoreMaxQueryLength is true": {
953+
startTime: time.Now().Add(-maxQueryLength).Add(-time.Hour),
954+
endTime: time.Now(),
955+
expected: validation.LimitError("expanding series: the query time range exceeds the limit (query length: 721h0m0s, limit: 720h0m0s)"),
956+
ignoreMaxQueryLength: true,
957+
},
958+
}
959+
960+
for testName, testData := range tests {
961+
t.Run(testName, func(t *testing.T) {
962+
var cfg Config
963+
flagext.DefaultValues(&cfg)
964+
cfg.ActiveQueryTrackerDir = ""
965+
cfg.IgnoreMaxQueryLength = testData.ignoreMaxQueryLength
966+
967+
limits := DefaultLimitsConfig()
968+
limits.MaxQueryLength = model.Duration(maxQueryLength)
969+
overrides, err := validation.NewOverrides(limits, nil)
970+
require.NoError(t, err)
971+
972+
chunkStore := &emptyChunkStore{}
973+
distributor := &emptyDistributor{}
974+
975+
queryables := []QueryableWithFilter{UseAlwaysQueryable(NewMockStoreQueryable(chunkStore))}
976+
queryable, _, _ := New(cfg, overrides, distributor, queryables, nil, log.NewNopLogger())
977+
978+
ctx := user.InjectOrgID(context.Background(), "test")
979+
980+
q, err := queryable.Querier(util.TimeToMillis(testData.startTime), util.TimeToMillis(testData.endTime))
981+
require.NoError(t, err)
982+
983+
_, _, err = q.LabelNames(ctx, &storage.LabelHints{Limit: 0})
984+
985+
if testData.expected != nil {
986+
require.NotNil(t, err)
987+
assert.True(t, strings.Contains(testData.expected.Error(), err.Error()))
988+
} else {
989+
assert.Nil(t, err)
990+
}
991+
992+
_, _, err = q.LabelValues(ctx, labels.MetricName, &storage.LabelHints{Limit: 0})
993+
994+
if testData.expected != nil {
995+
require.NotNil(t, err)
996+
assert.True(t, strings.Contains(testData.expected.Error(), err.Error()))
997+
} else {
998+
assert.Nil(t, err)
999+
}
1000+
})
1001+
}
1002+
}
1003+
9311004
func TestQuerier_ValidateQueryTimeRange_MaxQueryLookback(t *testing.T) {
9321005
t.Parallel()
9331006
const (

0 commit comments

Comments
 (0)