Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions pkg/cortex/cortex.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
"github.com/cortexproject/cortex/pkg/ingester"
"github.com/cortexproject/cortex/pkg/ingester/client"
"github.com/cortexproject/cortex/pkg/parquetconverter"
cortexparser "github.com/cortexproject/cortex/pkg/parser"
"github.com/cortexproject/cortex/pkg/querier"
"github.com/cortexproject/cortex/pkg/querier/tenantfederation"
"github.com/cortexproject/cortex/pkg/querier/tripperware"
Expand Down Expand Up @@ -551,7 +552,5 @@ func (t *Cortex) readyHandler(sm *services.Manager) http.HandlerFunc {
}

func (t *Cortex) setupPromQLFunctions() {
// The holt_winters function is renamed to double_exponential_smoothing and has been experimental since Prometheus v3. (https://github.com/prometheus/prometheus/pull/14930)
// The cortex supports holt_winters for users using this function.
querier.EnableExperimentalPromQLFunctions(t.Cfg.Querier.EnablePromQLExperimentalFunctions, true)
cortexparser.Setup(t.Cfg.Querier.EnablePromQLExperimentalFunctions, true)
}
29 changes: 27 additions & 2 deletions pkg/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,41 @@ package parser
import (
"maps"

"github.com/prometheus/prometheus/promql"
promqlparser "github.com/prometheus/prometheus/promql/parser"
"github.com/thanos-io/promql-engine/execution/parse"
)

var functions = buildFunctions()
var functions = buildFunctions(true)

func buildFunctions() map[string]*promqlparser.Function {
func Setup(enableExperimentalFunctions, enableHoltWinters bool) {
promqlparser.EnableExperimentalFunctions = enableExperimentalFunctions
buildFunctions(enableHoltWinters)
}

func buildFunctions(enableHoltWinters bool) map[string]*promqlparser.Function {
fns := make(map[string]*promqlparser.Function, len(promqlparser.Functions))
maps.Copy(fns, promqlparser.Functions)
maps.Copy(fns, parse.XFunctions)

// The holt_winters function was renamed to double_exponential_smoothing and marked experimental in Prometheus v3.
// Register holt_winters as an alias to maintain backward compatibility.
if enableHoltWinters {
if des, ok := fns["double_exponential_smoothing"]; ok {
holtWinters := *des
holtWinters.Experimental = false
holtWinters.Name = "holt_winters"
fns["holt_winters"] = &holtWinters

// Also register in global Prometheus parser for engine execution
promqlparser.Functions["holt_winters"] = &holtWinters
promql.FunctionCalls["holt_winters"] = promql.FunctionCalls["double_exponential_smoothing"]
}
} else {
delete(promqlparser.Functions, "holt_winters")
delete(promql.FunctionCalls, "holt_winters")
}

return fns
}

Expand Down
13 changes: 0 additions & 13 deletions pkg/querier/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/promql"
"github.com/prometheus/prometheus/promql/parser"
"github.com/prometheus/prometheus/storage"
"github.com/prometheus/prometheus/util/annotations"
"github.com/thanos-io/thanos/pkg/strutil"
Expand Down Expand Up @@ -719,15 +718,3 @@ func validateQueryTimeRange(ctx context.Context, userID string, startMs, endMs i

return int64(startTime), int64(endTime), nil
}

func EnableExperimentalPromQLFunctions(enablePromQLExperimentalFunctions, enableHoltWinters bool) {
parser.EnableExperimentalFunctions = enablePromQLExperimentalFunctions

if enableHoltWinters {
holtWinters := *parser.Functions["double_exponential_smoothing"]
holtWinters.Experimental = false
holtWinters.Name = "holt_winters"
parser.Functions["holt_winters"] = &holtWinters
promql.FunctionCalls["holt_winters"] = promql.FunctionCalls["double_exponential_smoothing"]
}
}
27 changes: 15 additions & 12 deletions pkg/querier/querier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
promchunk "github.com/cortexproject/cortex/pkg/chunk/encoding"
"github.com/cortexproject/cortex/pkg/cortexpb"
"github.com/cortexproject/cortex/pkg/ingester/client"
cortexparser "github.com/cortexproject/cortex/pkg/parser"
"github.com/cortexproject/cortex/pkg/querier/batch"
"github.com/cortexproject/cortex/pkg/querier/series"
"github.com/cortexproject/cortex/pkg/util"
Expand Down Expand Up @@ -1693,32 +1694,34 @@ func TestConfig_Validate(t *testing.T) {
}

func Test_EnableExperimentalPromQLFunctions(t *testing.T) {
EnableExperimentalPromQLFunctions(true, true)
cortexparser.Setup(true, true)
defer cortexparser.Setup(false, false)

// holt_winters function should exist
holtWintersFunc, ok := parser.Functions["holt_winters"]
require.True(t, ok)
// Verify experimental functions flag is set
require.True(t, parser.EnableExperimentalFunctions)

// double_exponential_smoothing function should exist
doubleExponentialSmoothingFunc, ok := parser.Functions["double_exponential_smoothing"]
require.True(t, ok)
require.Equal(t, "double_exponential_smoothing", doubleExponentialSmoothingFunc.Name)
require.True(t, parser.Functions["double_exponential_smoothing"].Experimental)

// holt_winters should not experimental function.
// holt_winters should exist
holtWintersFunc, ok := parser.Functions["holt_winters"]
require.True(t, ok)
require.Equal(t, "holt_winters", holtWintersFunc.Name)
require.False(t, holtWintersFunc.Experimental)
// holt_winters's Variadic, ReturnType, and ArgTypes are the same as the double_exponential_smoothing.

// holt_winters's Variadic, ReturnType, and ArgTypes are the same as the double_exponential_smoothing
require.Equal(t, doubleExponentialSmoothingFunc.Variadic, holtWintersFunc.Variadic)
require.Equal(t, doubleExponentialSmoothingFunc.ReturnType, holtWintersFunc.ReturnType)
require.Equal(t, doubleExponentialSmoothingFunc.ArgTypes, holtWintersFunc.ArgTypes)

// double_exponential_smoothing shouldn't be changed.
require.Equal(t, "double_exponential_smoothing", doubleExponentialSmoothingFunc.Name)
require.True(t, parser.Functions["double_exponential_smoothing"].Experimental)

// holt_winters function calls should exist.
// holt_winters function calls should exist
_, ok = promql.FunctionCalls["holt_winters"]
require.True(t, ok)

// double_exponential_smoothing function calls should exist.
// double_exponential_smoothing function calls should exist
_, ok = promql.FunctionCalls["double_exponential_smoothing"]
require.True(t, ok)
}
Expand Down
Loading