Skip to content

Commit

Permalink
Allowing to create Not/Regex/NotRegex matchers (#142)
Browse files Browse the repository at this point in the history
* Allowing to create Not/Regex/NotRegex matchers

Signed-off-by: alanprot <alanprot@gmail.com>

* fix lint

Signed-off-by: alanprot <alanprot@gmail.com>

* Adding != case

Signed-off-by: alanprot <alanprot@gmail.com>

* using ceil when  discovering how many extra matcher will be added on walkLabelMatchers function

Signed-off-by: alanprot <alanprot@gmail.com>

---------

Signed-off-by: alanprot <alanprot@gmail.com>
  • Loading branch information
alanprot authored Jan 28, 2025
1 parent 8b48fe2 commit eaf3e57
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 18 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,5 @@ jobs:
with:
go-version-file: .go-version
cache: true
- name: Lint
uses: golangci/golangci-lint-action@v6.1.0
with:
version: v1.59.0
- name: Golangci-lint
uses: golangci/golangci-lint-action@v6.2.0
53 changes: 42 additions & 11 deletions walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package promqlsmith

import (
"fmt"
"math"
"math/rand"
"sort"
"strings"
Expand Down Expand Up @@ -452,20 +453,57 @@ func (s *PromQLSmith) walkLabelMatchers() []*labels.Matcher {
}
series := s.seriesSet[s.rnd.Intn(len(s.seriesSet))]
orders := s.rnd.Perm(series.Len())
items := s.rnd.Intn((series.Len() + 1) / 2)
items := s.rnd.Intn(int(math.Ceil(float64(series.Len()+1) / 2)))
matchers := make([]*labels.Matcher, 0, items)
containsName := false
lbls := make([]labels.Label, 0, series.Len())
series.Range(func(l labels.Label) {
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:
val := lbls[orders[i]].Value
if s.rnd.Float64() > 0.9 {
val = ""
}
matcher = labels.MustNewMatcher(labels.MatchNotEqual, lbls[orders[i]].Name, val)
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 {
Expand All @@ -482,8 +520,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
Expand Down Expand Up @@ -687,13 +725,6 @@ func keepValueTypes(input []parser.ValueType, keep []parser.ValueType) []parser.
return out
}

func min(a, b int) int {
if a > b {
return b
}
return a
}

// generate a non-zero float64 value randomly.
func getNonZeroFloat64(rnd *rand.Rand) float64 {
for {
Expand Down
14 changes: 11 additions & 3 deletions walk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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,
Expand All @@ -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)
}
})
}
Expand Down

0 comments on commit eaf3e57

Please sign in to comment.