Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Fix flaky tests, clean up logic on rules #596

Merged
merged 1 commit into from
Jan 31, 2023
Merged
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
25 changes: 8 additions & 17 deletions config/sampler_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,21 +123,12 @@ func tryConvertToFloat(v any) (float64, bool) {
}
}

// In the case of strings, we want to stringize everything we get through a
// "standard" format, which we are defining as whatever Go does with the %v
// operator to sprintf. This will make sure that no matter how people encode
// their values, they compare on an equal footing.
func tryConvertToString(v any) (string, bool) {
switch value := v.(type) {
case string:
return value, true
case int:
return strconv.Itoa(value), true
case int64:
return strconv.FormatInt(value, 10), true
case float64:
return strconv.FormatFloat(value, 'E', -1, 64), false
case bool:
return strconv.FormatBool(value), true
default:
return "", false
}
return fmt.Sprintf("%v", v), true
}

func tryConvertToBool(v any) bool {
Expand Down Expand Up @@ -357,23 +348,23 @@ func setMatchStringBasedOperators(r *RulesBasedSamplerCondition, condition strin
switch condition {
case "starts-with":
r.Matches = func(spanValue any, exists bool) bool {
s, ok := spanValue.(string)
s, ok := tryConvertToString(spanValue)
if ok {
return strings.HasPrefix(s, conditionValue)
}
return false
}
case "contains":
r.Matches = func(spanValue any, exists bool) bool {
s, ok := spanValue.(string)
s, ok := tryConvertToString(spanValue)
if ok {
return strings.Contains(s, conditionValue)
}
return false
}
case "does-not-contain":
r.Matches = func(spanValue any, exists bool) bool {
s, ok := spanValue.(string)
s, ok := tryConvertToString(spanValue)
if ok {
return !strings.Contains(s, conditionValue)
}
Expand Down
73 changes: 46 additions & 27 deletions sample/rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1118,6 +1119,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1146,6 +1148,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1174,6 +1177,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1202,6 +1206,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand All @@ -1212,8 +1217,8 @@ func TestRulesDatatypes(t *testing.T) {
Condition: []*config.RulesBasedSamplerCondition{
{
Field: "test",
Operator: "=",
Value: "blaaahhhh",
Operator: "contains",
Value: "ru",
Datatype: "string",
},
},
Expand All @@ -1224,12 +1229,13 @@ func TestRulesDatatypes(t *testing.T) {
{
Event: types.Event{
Data: map[string]interface{}{
"test": false,
"test": true,
},
},
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1258,6 +1264,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand All @@ -1268,7 +1275,7 @@ func TestRulesDatatypes(t *testing.T) {
Condition: []*config.RulesBasedSamplerCondition{
{
Field: "test",
Operator: "=",
Operator: "<",
Value: float64(100.01),
Datatype: "float",
},
Expand All @@ -1286,6 +1293,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1314,6 +1322,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1342,6 +1351,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1370,6 +1380,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand All @@ -1380,7 +1391,7 @@ func TestRulesDatatypes(t *testing.T) {
Condition: []*config.RulesBasedSamplerCondition{
{
Field: "test",
Operator: "<",
Operator: ">",
Value: "10.3",
Datatype: "string",
},
Expand All @@ -1392,12 +1403,13 @@ func TestRulesDatatypes(t *testing.T) {
{
Event: types.Event{
Data: map[string]interface{}{
"test": 9.3,
"test": 9.3, // "9.3" is greater than "10.3" when compared as a string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh. Turns out it's consistent with F# too, so this isn't just some "rob pike is a weird dude" behavior:

λ ~/scratch/otel-pixie/ dotnet fsi

Microsoft (R) F# Interactive version 12.4.0.0 for F# 7.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> "9.3" > "10.3";;
val it: bool = true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, alphabetically '9' is greater than '1'. :)

},
},
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1426,6 +1438,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1454,6 +1467,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 1,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1482,6 +1496,7 @@ func TestRulesDatatypes(t *testing.T) {
},
},
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Expand Down Expand Up @@ -1509,18 +1524,19 @@ func TestRulesDatatypes(t *testing.T) {
},
},
},
ExpectedKeep: false,
ExpectedKeep: true,
ExpectedRate: 10,
},
{
Rules: &config.RulesBasedSamplerConfig{
Rule: []*config.RulesBasedSamplerRule{
{
Name: "shouldFail",
Name: "intsNotEqual",
SampleRate: 10,
Condition: []*config.RulesBasedSamplerCondition{
{
Field: "test",
Operator: "=",
Operator: "!=",
Value: int64(1),
Datatype: "int",
},
Expand All @@ -1532,35 +1548,38 @@ func TestRulesDatatypes(t *testing.T) {
{
Event: types.Event{
Data: map[string]interface{}{
"test": int64(1),
"test": int64(11),
},
},
},
},
ExpectedKeep: false,
ExpectedKeep: true,
ExpectedRate: 10,
},
}

for _, d := range data {
sampler := &RulesBasedSampler{
Config: d.Rules,
Logger: &logger.NullLogger{},
Metrics: &metrics.NullMetrics{},
}

sampler.Start()
t.Run(d.Rules.Rule[0].Name, func(t *testing.T) {
sampler := &RulesBasedSampler{
Config: d.Rules,
Logger: &logger.NullLogger{},
Metrics: &metrics.NullMetrics{},
}

trace := &types.Trace{}
sampler.Start()

for _, span := range d.Spans {
trace.AddSpan(span)
}
trace := &types.Trace{}

_, keep, _ := sampler.GetSampleRate(trace)
for _, span := range d.Spans {
trace.AddSpan(span)
}

// // we can only test when we don't expect to keep the trace
if !d.ExpectedKeep {
assert.Equal(t, d.ExpectedKeep, keep, d.Rules)
}
rate, keep, _ := sampler.GetSampleRate(trace)
assert.Equal(t, d.ExpectedRate, rate, d.Rules)
// because keep depends on sampling rate, we can only test expectedKeep when it should be false
if !d.ExpectedKeep {
assert.Equal(t, d.ExpectedKeep, keep, d.Rules)
}
})
}
}