From c7ac594f8319ac8d022bd3f7af7f83b7a00e4cb0 Mon Sep 17 00:00:00 2001 From: alanprot Date: Mon, 27 Jan 2025 15:11:23 -0800 Subject: [PATCH] Allowing to create Not/Regex/NotRegex matchers Signed-off-by: alanprot --- walk.go | 39 ++++++++++++++++++++++++++++++++++++--- walk_test.go | 14 +++++++++++--- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/walk.go b/walk.go index 2426841..74ac07d 100644 --- a/walk.go +++ b/walk.go @@ -460,12 +460,45 @@ func (s *PromQLSmith) walkLabelMatchers() []*labels.Matcher { lbls = append(lbls, l) }) + valF := func(v string) string { + val := s.rnd.Float64() + switch { + case val > 0.95: + return "" + case val > 0.90: + return ".*" + case val > 0.85: + return ".+" + case val > 0.75: + return fmt.Sprintf(".*%v", v[len(v)/2:]) + default: + return fmt.Sprintf("%v.*", v[:len(v)/2]) + } + } + for i := 0; i < items; i++ { + var matcher *labels.Matcher + if lbls[orders[i]].Name == labels.MetricName { containsName = true + matcher = labels.MustNewMatcher(labels.MatchEqual, lbls[orders[i]].Name, lbls[orders[i]].Value) + } else { + res := s.rnd.Intn(4) + matchType := labels.MatchType(res) + switch matchType { + case labels.MatchEqual: + matcher = labels.MustNewMatcher(labels.MatchEqual, lbls[orders[i]].Name, lbls[orders[i]].Value) + case labels.MatchNotEqual: + matcher = labels.MustNewMatcher(labels.MatchNotEqual, lbls[orders[i]].Name, lbls[orders[i]].Value) + case labels.MatchRegexp: + matcher = labels.MustNewMatcher(labels.MatchRegexp, lbls[orders[i]].Name, valF(lbls[orders[i]].Value)) + case labels.MatchNotRegexp: + matcher = labels.MustNewMatcher(labels.MatchNotRegexp, lbls[orders[i]].Name, valF(lbls[orders[i]].Value)) + } } - matchers = append(matchers, labels.MustNewMatcher(labels.MatchEqual, lbls[orders[i]].Name, lbls[orders[i]].Value)) + + matchers = append(matchers, matcher) } if !containsName { @@ -482,8 +515,8 @@ func (s *PromQLSmith) walkLabelMatchers() []*labels.Matcher { return matchers } -// walkSelectors is similar to walkLabelMatchers, but used for generating various -// types of matchers more than simple equal matcher. +// walkSelectors is similar to walkLabelMatchers, but does not guarantee the equal +// matcher on the metric name func (s *PromQLSmith) walkSelectors() []*labels.Matcher { if len(s.seriesSet) == 0 { return nil diff --git a/walk_test.go b/walk_test.go index 37d1670..d61b35a 100644 --- a/walk_test.go +++ b/walk_test.go @@ -497,7 +497,7 @@ func TestWalkVectorSelector(t *testing.T) { require.True(t, ok) containsMetricName := false for _, matcher := range vs.LabelMatchers { - require.Equal(t, labels.MatchEqual, matcher.Type) + require.LessOrEqual(t, matcher.Type, 4) if matcher.Name == labels.MetricName { containsMetricName = true } @@ -509,7 +509,8 @@ func TestWalkLabelMatchers(t *testing.T) { rnd := rand.New(rand.NewSource(time.Now().Unix())) opts := []Option{WithEnableOffset(true), WithEnableAtModifier(true)} for i, tc := range []struct { - ss []labels.Labels + expectedMatchers int + ss []labels.Labels }{ { ss: nil, @@ -526,9 +527,16 @@ func TestWalkLabelMatchers(t *testing.T) { } { t.Run(fmt.Sprintf("test_case_%d", i), func(t *testing.T) { p := New(rnd, tc.ss, opts...) + labelNames := make(map[string]struct{}) + for _, s := range tc.ss { + s.Range(func(l labels.Label) { + labelNames[l.Name] = struct{}{} + }) + } matchers := p.walkLabelMatchers() for _, matcher := range matchers { - require.Equal(t, labels.MatchEqual, matcher.Type) + require.LessOrEqual(t, matcher.Type, 4) + require.Contains(t, labelNames, matcher.Name) } }) }