Skip to content

Commit

Permalink
Remove max future query window flag (#10771)
Browse files Browse the repository at this point in the history
  • Loading branch information
chencs authored Mar 4, 2025
1 parent 9d1ae28 commit 52ea02b
Show file tree
Hide file tree
Showing 7 changed files with 0 additions and 154 deletions.
1 change: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
* `cortex_ingester_tsdb_block_postings_for_matchers_cache_evictions_total`
* [ENHANCEMENT] Compactor: Shuffle users' order in `BlocksCleaner`. Prevents bucket indexes from going an extended period without cleanup during compactor restarts. #10513
* [ENHANCEMENT] Distributor, querier, ingester and store-gateway: Add support for `limit` parameter for label names and values requests. #10410
* [ENHANCEMENT] Query-frontend: Allow adjustment of queries looking into the future to a maximum duration with experimental `-query-frontend.max-future-query-window` flag. #10547
* [ENHANCEMENT] Ruler: Adds support for filtering results from rule status endpoint by `file[]`, `rule_group[]` and `rule_name[]`. #10589
* [ENHANCEMENT] Query-frontend: Add option to "spin off" subqueries as actual range queries, so that they benefit from query acceleration techniques such as sharding, splitting, and caching. To enable this feature, set the `-query-frontend.instant-queries-with-subquery-spin-off=<comma separated list>` option on the frontend or the `instant_queries_with_subquery_spin_off` per-tenant override with regular expressions matching the queries to enable. #10460 #10603 #10621 #10742 #10796
* [ENHANCEMENT] Querier, ingester: The series API respects passed `limit` parameter. #10620 #10652
Expand Down
11 changes: 0 additions & 11 deletions cmd/mimir/config-descriptor.json
Original file line number Diff line number Diff line change
Expand Up @@ -4770,17 +4770,6 @@
"fieldType": "string",
"fieldCategory": "experimental"
},
{
"kind": "field",
"name": "max_future_query_window",
"required": false,
"desc": "Mutate incoming queries that look far into the future to only look into the future by the set duration. 0 to disable.",
"fieldValue": null,
"fieldDefaultValue": 0,
"fieldFlag": "query-frontend.max-future-query-window",
"fieldType": "duration",
"fieldCategory": "experimental"
},
{
"kind": "field",
"name": "cardinality_analysis_enabled",
Expand Down
2 changes: 0 additions & 2 deletions cmd/mimir/help-all.txt.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2359,8 +2359,6 @@ Usage of ./cmd/mimir/mimir:
Max body size for downstream prometheus. (default 10485760)
-query-frontend.max-cache-freshness duration
Most recent allowed cacheable result per-tenant, to prevent caching very recent results that might still be in flux. (default 10m)
-query-frontend.max-future-query-window duration
[experimental] Mutate incoming queries that look far into the future to only look into the future by the set duration. 0 to disable.
-query-frontend.max-queriers-per-tenant int
Maximum number of queriers that can handle requests for a single tenant. If set to 0 or value higher than number of available queriers, *all* queriers will handle requests for the tenant. Each frontend (or query-scheduler, if used) will select the same set of queriers for the same tenant (given that all queriers are connected to all frontends / query-schedulers). This option only works with queriers connecting to the query-frontend / query-scheduler, not when using downstream URL.
-query-frontend.max-query-expression-size-bytes int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3765,11 +3765,6 @@ The `limits` block configures default and per-tenant limits imposed by component
# CLI flag: -query-frontend.instant-queries-with-subquery-spin-off
[instant_queries_with_subquery_spin_off: <string> | default = ""]

# (experimental) Mutate incoming queries that look far into the future to only
# look into the future by the set duration. 0 to disable.
# CLI flag: -query-frontend.max-future-query-window
[max_future_query_window: <duration> | default = 0s]

# Enables endpoints used for cardinality analysis.
# CLI flag: -querier.cardinality-analysis-enabled
[cardinality_analysis_enabled: <boolean> | default = false]
Expand Down
31 changes: 0 additions & 31 deletions pkg/frontend/querymiddleware/limits.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,6 @@ type Limits interface {
// InstantQueriesWithSubquerySpinOff returns a list of regexp patterns of instant queries that can be optimized by spinning off range queries.
// If the list is empty, the feature is disabled.
InstantQueriesWithSubquerySpinOff(userID string) []string

// MaxFutureQueryWindow returns the maximum duration into the future a query can be executed for the tenant.
MaxFutureQueryWindow(userID string) time.Duration
}

type limitsMiddleware struct {
Expand Down Expand Up @@ -202,34 +199,6 @@ func (l limitsMiddleware) Do(ctx context.Context, r MetricsQueryRequest) (Respon
return nil, newMaxTotalQueryLengthError(queryLen, maxQueryLength)
}
}

if maxFutureQueryWindow := validation.SmallestPositiveNonZeroDurationPerTenant(tenantIDs, l.MaxFutureQueryWindow); maxFutureQueryWindow > 0 {
maxAllowedTs := util.TimeToMillis(time.Now().Add(maxFutureQueryWindow))
if r.GetStart() > maxAllowedTs {
// The request is fully outside the allowed range, so we can return an empty response.
level.Debug(log).Log(
"msg", "skipping the execution of the query because its time range is exclusively after the 'max future window' setting",
"reqStart", util.FormatTimeMillis(r.GetStart()),
"redEnd", util.FormatTimeMillis(r.GetEnd()),
"maxFutureWindow", maxFutureQueryWindow,
)
return newEmptyPrometheusResponse(), nil
}

if r.GetEnd() > maxAllowedTs {
level.Debug(log).Log(
"msg", "the end time of the query has been manipulated because of the 'max-future-query-window' setting",
"original", util.FormatTimeMillis(r.GetEnd()),
"updated", util.FormatTimeMillis(maxAllowedTs),
"maxFutureWindow", maxFutureQueryWindow,
)
r, err = r.WithStartEnd(r.GetStart(), maxAllowedTs)
if err != nil {
return nil, apierror.New(apierror.TypeInternal, err.Error())
}
}
}

return l.next.Do(ctx, r)
}

Expand Down
92 changes: 0 additions & 92 deletions pkg/frontend/querymiddleware/limits_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,89 +281,6 @@ func TestLimitsMiddleware_MaxQueryLookback_InstantQuery(t *testing.T) {
}
}

func TestLimitsMiddleware_MaxFutureQueryWindow_RangeQueryAndRemoteRead(t *testing.T) {
now := time.Now()
maxFutureWindow := 7 * 24 * time.Hour
tests := []struct {
name string
startTime time.Time
endTime time.Time
maxFutureWindow time.Duration
expectedEndTs time.Time
expectedSkipped bool
}{
{
name: "queries into past are not adjusted with max future window enabled",
startTime: now.Add(-365 * 24 * time.Hour),
endTime: now,
maxFutureWindow: maxFutureWindow,
expectedEndTs: now,
},
{
name: "queries exclusively past max future window are skipped",
startTime: now.Add((7*24 + 1) * time.Hour),
endTime: now.Add(8 * 24 * time.Hour),
maxFutureWindow: maxFutureWindow,
expectedSkipped: true,
},
{
name: "queries partially into future are adjusted",
startTime: now.Add(-24 * time.Hour),
endTime: now.Add(8 * 24 * time.Hour),
maxFutureWindow: maxFutureWindow,
expectedEndTs: now.Add(maxFutureWindow),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
reqs := map[string]MetricsQueryRequest{
"range query": &PrometheusRangeQueryRequest{
start: util.TimeToMillis(tt.startTime),
end: util.TimeToMillis(tt.endTime),
},
"remote read": &remoteReadQueryRequest{
path: remoteReadPathSuffix,
query: &prompb.Query{
StartTimestampMs: util.TimeToMillis(tt.startTime),
EndTimestampMs: util.TimeToMillis(tt.endTime),
},
},
}

for reqType, req := range reqs {
t.Run(reqType, func(t *testing.T) {
limits := mockLimits{maxFutureQueryWindow: tt.maxFutureWindow}
middleware := newLimitsMiddleware(limits, log.NewNopLogger())

innerRes := newEmptyPrometheusResponse()
inner := &mockHandler{}
inner.On("Do", mock.Anything, mock.Anything).Return(innerRes, nil)

ctx := user.InjectOrgID(context.Background(), "test")
outer := middleware.Wrap(inner)
res, err := outer.Do(ctx, req)
require.NoError(t, err)

if tt.expectedSkipped {
// We expect an empty response, but not the one returned by the inner handler
// which we expect has been skipped.
assert.NotSame(t, innerRes, res)
assert.Len(t, inner.Calls, 0)
} else {
// We expect the response returned by the inner handler.
assert.Same(t, innerRes, res)

// Assert on the time range of the request passed to the inner handler (5s delta).
delta := float64(5000)
require.Len(t, inner.Calls, 1)
assert.InDelta(t, util.TimeToMillis(tt.expectedEndTs), inner.Calls[0].Arguments.Get(1).(MetricsQueryRequest).GetEnd(), delta)
}
})
}
})
}
}

func TestLimitsMiddleware_MaxQueryExpressionSizeBytes(t *testing.T) {
now := time.Now()

Expand Down Expand Up @@ -600,10 +517,6 @@ func (m multiTenantMockLimits) MaxCacheFreshness(userID string) time.Duration {
return m.byTenant[userID].maxCacheFreshness
}

func (m multiTenantMockLimits) MaxFutureQueryWindow(userID string) time.Duration {
return m.byTenant[userID].maxFutureQueryWindow
}

func (m multiTenantMockLimits) QueryShardingTotalShards(userID string) int {
return m.byTenant[userID].totalShards
}
Expand Down Expand Up @@ -705,7 +618,6 @@ type mockLimits struct {
maxQueryParallelism int
maxShardedQueries int
maxRegexpSizeBytes int
maxFutureQueryWindow time.Duration
splitInstantQueriesInterval time.Duration
totalShards int
compactorShards int
Expand Down Expand Up @@ -755,10 +667,6 @@ func (m mockLimits) MaxCacheFreshness(string) time.Duration {
return m.maxCacheFreshness
}

func (m mockLimits) MaxFutureQueryWindow(string) time.Duration {
return m.maxFutureQueryWindow
}

func (m mockLimits) QueryShardingTotalShards(string) int {
return m.totalShards
}
Expand Down
12 changes: 0 additions & 12 deletions pkg/util/validation/limits.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ const (
AlertmanagerMaxGrafanaStateSizeFlag = "alertmanager.max-grafana-state-size-bytes"
costAttributionLabelsFlag = "validation.cost-attribution-labels"
maxCostAttributionLabelsPerUserFlag = "validation.max-cost-attribution-labels-per-user"
maxFutureQueryWindowFlag = "query-frontend.max-future-query-window"

// MinCompactorPartialBlockDeletionDelay is the minimum partial blocks deletion delay that can be configured in Mimir.
MinCompactorPartialBlockDeletionDelay = 4 * time.Hour
Expand All @@ -76,7 +75,6 @@ var (
errInvalidMaxEstimatedChunksPerQueryMultiplier = errors.New("invalid value for -" + MaxEstimatedChunksPerQueryMultiplierFlag + ": must be 0 or greater than or equal to 1")
errCostAttributionLabelsLimitExceeded = errors.New("invalid value for -" + costAttributionLabelsFlag + ": exceeds the limit defined by -" + maxCostAttributionLabelsPerUserFlag)
errInvalidMaxCostAttributionLabelsPerUser = errors.New("invalid value for -" + maxCostAttributionLabelsPerUserFlag + ": must be less than or equal to 4")
errInvalidMaxFutureQueryWindow = errors.New("invalid value for -" + maxFutureQueryWindowFlag + ": must be greater than or equal to 0")
)

// LimitError is a marker interface for the errors that do not comply with the specified limits.
Expand Down Expand Up @@ -194,7 +192,6 @@ type Limits struct {
EnabledPromQLExperimentalFunctions flagext.StringSliceCSV `yaml:"enabled_promql_experimental_functions" json:"enabled_promql_experimental_functions" category:"experimental"`
Prom2RangeCompat bool `yaml:"prom2_range_compat" json:"prom2_range_compat" category:"experimental"`
InstantQueriesWithSubquerySpinOff flagext.StringSliceCSV `yaml:"instant_queries_with_subquery_spin_off" json:"instant_queries_with_subquery_spin_off" category:"experimental"`
MaxFutureQueryWindow model.Duration `yaml:"max_future_query_window" json:"max_future_query_window" category:"experimental"`

// Cardinality
CardinalityAnalysisEnabled bool `yaml:"cardinality_analysis_enabled" json:"cardinality_analysis_enabled"`
Expand Down Expand Up @@ -400,7 +397,6 @@ func (l *Limits) RegisterFlags(f *flag.FlagSet) {
f.BoolVar(&l.AlignQueriesWithStep, alignQueriesWithStepFlag, false, "Mutate incoming queries to align their start and end with their step to improve result caching.")
f.Var(&l.EnabledPromQLExperimentalFunctions, "query-frontend.enabled-promql-experimental-functions", "Enable certain experimental PromQL functions, which are subject to being changed or removed at any time, on a per-tenant basis. Defaults to empty which means all experimental functions are disabled. Set to 'all' to enable all experimental functions.")
f.BoolVar(&l.Prom2RangeCompat, "query-frontend.prom2-range-compat", false, "Rewrite queries using the same range selector and resolution [X:X] which don't work in Prometheus 3.0 to a nearly identical form that works with Prometheus 3.0 semantics")
f.Var(&l.MaxFutureQueryWindow, maxFutureQueryWindowFlag, "Mutate incoming queries that look far into the future to only look into the future by the set duration. 0 to disable.")
f.Var(&l.InstantQueriesWithSubquerySpinOff, "query-frontend.instant-queries-with-subquery-spin-off", "List of regular expression patterns matching instant queries. Subqueries within those instant queries will be spun off as range queries to optimize their performance.")

// Store-gateway.
Expand Down Expand Up @@ -525,10 +521,6 @@ func (l *Limits) validate() error {
return errInvalidMaxCostAttributionLabelsPerUser
}

if l.MaxFutureQueryWindow < 0 {
return errInvalidMaxFutureQueryWindow
}

return nil
}

Expand Down Expand Up @@ -876,10 +868,6 @@ func (o *Overrides) OutOfOrderBlocksExternalLabelEnabled(userID string) bool {
return o.getOverridesForUser(userID).OutOfOrderBlocksExternalLabelEnabled
}

func (o *Overrides) MaxFutureQueryWindow(userID string) time.Duration {
return time.Duration(o.getOverridesForUser(userID).MaxFutureQueryWindow)
}

// SeparateMetricsGroupLabel returns the custom label used to separate specific metrics
func (o *Overrides) SeparateMetricsGroupLabel(userID string) string {
return o.getOverridesForUser(userID).SeparateMetricsGroupLabel
Expand Down

0 comments on commit 52ea02b

Please sign in to comment.