diff --git a/go.mod b/go.mod index 40fdbdbc39..a2febb2cec 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/aws/aws-sdk-go v1.55.5 github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 github.com/cespare/xxhash v1.1.0 - github.com/cortexproject/promqlsmith v0.0.0-20241101182713-3eec5725bc3f + github.com/cortexproject/promqlsmith v0.0.0-20241102030034-4051538fd914 github.com/dustin/go-humanize v1.0.1 github.com/efficientgo/core v1.0.0-rc.3 github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb diff --git a/go.sum b/go.sum index 0fc538f087..85de66d80e 100644 --- a/go.sum +++ b/go.sum @@ -944,8 +944,8 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cortexproject/promqlsmith v0.0.0-20241101182713-3eec5725bc3f h1:5C8PGy3GN+qqQatdDMU5bXFIspoIngMuyD7UCWkMiRA= -github.com/cortexproject/promqlsmith v0.0.0-20241101182713-3eec5725bc3f/go.mod h1:ypUb6BfnDVr7QrBgAxtzRqZ573swvka0BdCkPqa2A5g= +github.com/cortexproject/promqlsmith v0.0.0-20241102030034-4051538fd914 h1:UhI6yOSqMz3ln8FGaZRLbJTKzPHRaVwewoTa6N5PU5k= +github.com/cortexproject/promqlsmith v0.0.0-20241102030034-4051538fd914/go.mod h1:ypUb6BfnDVr7QrBgAxtzRqZ573swvka0BdCkPqa2A5g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/integration/query_fuzz_test.go b/integration/query_fuzz_test.go index bf9485f5e6..a9d15a7ea9 100644 --- a/integration/query_fuzz_test.go +++ b/integration/query_fuzz_test.go @@ -10,7 +10,6 @@ import ( "os" "path" "path/filepath" - "slices" "sort" "strconv" "strings" @@ -42,9 +41,6 @@ var enabledFunctions []*parser.Function func init() { for _, f := range parser.Functions { - if slices.Contains(f.ArgTypes, parser.ValueTypeString) { - continue - } // Ignore native histogram functions for now as our test cases are only float samples. if strings.Contains(f.Name, "histogram") && f.Name != "histogram_quantile" { continue @@ -129,7 +125,7 @@ func TestDisableChunkTrimmingFuzz(t *testing.T) { serieses := make([]prompb.TimeSeries, numSeries) lbls := make([]labels.Labels, numSeries) for i := 0; i < numSeries; i++ { - series := e2e.GenerateSeriesWithSamples(fmt.Sprintf("test_series_%d", i), start, scrapeInterval, i*numSamples, numSamples, prompb.Label{Name: "job", Value: "test"}) + series := e2e.GenerateSeriesWithSamples("test_series", start, scrapeInterval, i*numSamples, numSamples, prompb.Label{Name: "job", Value: "test"}, prompb.Label{Name: "series", Value: strconv.Itoa(i)}) serieses[i] = series builder := labels.NewBuilder(labels.EmptyLabels()) @@ -175,7 +171,8 @@ func TestDisableChunkTrimmingFuzz(t *testing.T) { for { expr = ps.WalkRangeQuery() query = expr.Pretty(0) - if !strings.Contains(query, "timestamp") { + // timestamp is a known function that break with disable chunk trimming. + if isValidQuery(expr, 5) && !strings.Contains(query, "timestamp") { break } } diff --git a/vendor/github.com/cortexproject/promqlsmith/opts.go b/vendor/github.com/cortexproject/promqlsmith/opts.go index c4b080c0bc..2f806fba4b 100644 --- a/vendor/github.com/cortexproject/promqlsmith/opts.go +++ b/vendor/github.com/cortexproject/promqlsmith/opts.go @@ -5,7 +5,6 @@ import ( "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/promql/parser" - "golang.org/x/exp/slices" ) var ( @@ -58,9 +57,6 @@ var ( func init() { for _, f := range parser.Functions { - if slices.Contains(f.ArgTypes, parser.ValueTypeString) { - continue - } // Ignore experimental functions for now. if !f.Experimental { defaultSupportedFuncs = append(defaultSupportedFuncs, f) diff --git a/vendor/github.com/cortexproject/promqlsmith/walk.go b/vendor/github.com/cortexproject/promqlsmith/walk.go index f98dc151ed..930bba99df 100644 --- a/vendor/github.com/cortexproject/promqlsmith/walk.go +++ b/vendor/github.com/cortexproject/promqlsmith/walk.go @@ -16,6 +16,9 @@ import ( const ( // max number of grouping labels in either by or without clause. maxGroupingLabels = 5 + + // Destination label used in functions like label_replace and label_join. + destinationLabel = "__promqlsmith_dst_label__" ) // walkExpr generates the given expression type with one of the required value type. @@ -249,10 +252,20 @@ func (s *PromQLSmith) walkCall(valueTypes ...parser.ValueType) parser.Expr { } func (s *PromQLSmith) walkFunctions(expr *parser.Call) { + switch expr.Func.Name { + case "label_join": + s.walkLabelJoin(expr) + return + default: + } + expr.Args = make([]parser.Expr, len(expr.Func.ArgTypes)) if expr.Func.Name == "holt_winters" { s.walkHoltWinters(expr) return + } else if expr.Func.Name == "label_replace" { + s.walkLabelReplace(expr) + return } if expr.Func.Variadic != 0 { s.walkVariadicFunctions(expr) @@ -269,6 +282,70 @@ func (s *PromQLSmith) walkHoltWinters(expr *parser.Call) { expr.Args[2] = &parser.NumberLiteral{Val: getNonZeroFloat64(s.rnd)} } +func (s *PromQLSmith) walkLabelReplace(expr *parser.Call) { + expr.Args[0] = s.Walk(expr.Func.ArgTypes[0]) + expr.Args[1] = &parser.StringLiteral{Val: destinationLabel} + expr.Args[2] = &parser.StringLiteral{Val: "$1"} + seriesSet, _ := getOutputSeries(expr.Args[0]) + + var srcLabel string + if len(seriesSet) > 0 { + lbls := seriesSet[0] + if lbls.Len() > 0 { + idx := s.rnd.Intn(lbls.Len()) + cnt := 0 + lbls.Range(func(lbl labels.Label) { + if cnt == idx { + srcLabel = lbl.Name + } + cnt++ + }) + } + } + if srcLabel != "" { + // It is possible that the vector selector match nothing. In this case, it doesn't matter which label + // we pick. Just pick something from all series labels. + idx := s.rnd.Intn(len(s.labelNames)) + srcLabel = s.labelNames[idx] + } + expr.Args[3] = &parser.StringLiteral{Val: srcLabel} + // Just copy the label we picked. + expr.Args[4] = &parser.StringLiteral{Val: "(.*)"} +} + +func (s *PromQLSmith) walkLabelJoin(expr *parser.Call) { + expr.Args = make([]parser.Expr, 0, len(expr.Func.ArgTypes)) + expr.Args = append(expr.Args, s.Walk(expr.Func.ArgTypes[0])) + seriesSet, _ := getOutputSeries(expr.Args[0]) + expr.Args = append(expr.Args, &parser.StringLiteral{Val: destinationLabel}) + expr.Args = append(expr.Args, &parser.StringLiteral{Val: ","}) + + // Let's try to not join more than 2 labels for simplicity. + cnt := 0 + if len(seriesSet) > 0 { + seriesSet[0].Range(func(lbl labels.Label) { + if cnt < 2 { + if s.rnd.Int()%2 == 0 { + expr.Args = append(expr.Args, &parser.StringLiteral{Val: lbl.Name}) + cnt++ + } + } + }) + return + } + + // It is possible that the vector selector match nothing. In this case, it doesn't matter which label + // we pick. Just pick something from all series labels. + for _, name := range s.labelNames { + if cnt < 2 { + if s.rnd.Int()%2 == 0 { + expr.Args = append(expr.Args, &parser.StringLiteral{Val: name}) + cnt++ + } + } + } +} + // Supported variadic functions include: // days_in_month, day_of_month, day_of_week, day_of_year, year, // hour, minute, month, round. diff --git a/vendor/modules.txt b/vendor/modules.txt index d0d95231df..0b9739eb33 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -303,7 +303,7 @@ github.com/coreos/go-semver/semver ## explicit; go 1.12 github.com/coreos/go-systemd/v22/activation github.com/coreos/go-systemd/v22/journal -# github.com/cortexproject/promqlsmith v0.0.0-20241101182713-3eec5725bc3f +# github.com/cortexproject/promqlsmith v0.0.0-20241102030034-4051538fd914 ## explicit; go 1.21.0 github.com/cortexproject/promqlsmith # github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc