623 lines
11 KiB
Go
623 lines
11 KiB
Go
|
package rules
|
||
|
|
||
|
import (
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
pql "github.com/prometheus/prometheus/promql"
|
||
|
"github.com/stretchr/testify/assert"
|
||
|
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
|
||
|
)
|
||
|
|
||
|
type testLogger struct {
|
||
|
t *testing.T
|
||
|
}
|
||
|
|
||
|
func (l testLogger) Log(args ...interface{}) error {
|
||
|
l.t.Log(args...)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func TestPromRuleShouldAlert(t *testing.T) {
|
||
|
postableRule := PostableRule{
|
||
|
AlertName: "Test Rule",
|
||
|
AlertType: "METRIC_BASED_ALERT",
|
||
|
RuleType: RuleTypeProm,
|
||
|
EvalWindow: Duration(5 * time.Minute),
|
||
|
Frequency: Duration(1 * time.Minute),
|
||
|
RuleCondition: &RuleCondition{
|
||
|
CompositeQuery: &v3.CompositeQuery{
|
||
|
QueryType: v3.QueryTypePromQL,
|
||
|
PromQueries: map[string]*v3.PromQuery{
|
||
|
"A": {
|
||
|
Query: "dummy_query", // This is not used in the test
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
cases := []struct {
|
||
|
values pql.Series
|
||
|
expectAlert bool
|
||
|
compareOp string
|
||
|
matchType string
|
||
|
target float64
|
||
|
}{
|
||
|
// Test cases for Equals Always
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "2", // Always
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "2", // Always
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "2", // Always
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "2", // Always
|
||
|
target: 0.0,
|
||
|
},
|
||
|
// Test cases for Equals Once
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "1", // Once
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "1", // Once
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "1", // Once
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "1", // Once
|
||
|
target: 0.0,
|
||
|
},
|
||
|
// Test cases for Greater Than Always
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 4.0},
|
||
|
{F: 6.0},
|
||
|
{F: 8.0},
|
||
|
{F: 2.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "1", // Greater Than
|
||
|
matchType: "2", // Always
|
||
|
target: 1.5,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 4.0},
|
||
|
{F: 6.0},
|
||
|
{F: 8.0},
|
||
|
{F: 2.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "1", // Greater Than
|
||
|
matchType: "2", // Always
|
||
|
target: 4.5,
|
||
|
},
|
||
|
// Test cases for Greater Than Once
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 4.0},
|
||
|
{F: 6.0},
|
||
|
{F: 8.0},
|
||
|
{F: 2.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "1", // Greater Than
|
||
|
matchType: "1", // Once
|
||
|
target: 4.5,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 4.0},
|
||
|
{F: 4.0},
|
||
|
{F: 4.0},
|
||
|
{F: 4.0},
|
||
|
{F: 4.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "1", // Greater Than
|
||
|
matchType: "1", // Once
|
||
|
target: 4.5,
|
||
|
},
|
||
|
// Test cases for Not Equals Always
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
{F: 0.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "2", // Always
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 0.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "2", // Always
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "2", // Always
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 1.0},
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "2", // Always
|
||
|
target: 0.0,
|
||
|
},
|
||
|
// Test cases for Not Equals Once
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
{F: 0.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "1", // Once
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "1", // Once
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 0.0},
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
{F: 0.0},
|
||
|
{F: 1.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "1", // Once
|
||
|
target: 0.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
{F: 1.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "1", // Once
|
||
|
target: 0.0,
|
||
|
},
|
||
|
// Test cases for Less Than Always
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 1.5},
|
||
|
{F: 1.5},
|
||
|
{F: 1.5},
|
||
|
{F: 1.5},
|
||
|
{F: 1.5},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "2", // Less Than
|
||
|
matchType: "2", // Always
|
||
|
target: 4,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 4.5},
|
||
|
{F: 4.5},
|
||
|
{F: 4.5},
|
||
|
{F: 4.5},
|
||
|
{F: 4.5},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "2", // Less Than
|
||
|
matchType: "2", // Always
|
||
|
target: 4,
|
||
|
},
|
||
|
// Test cases for Less Than Once
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 4.5},
|
||
|
{F: 4.5},
|
||
|
{F: 4.5},
|
||
|
{F: 4.5},
|
||
|
{F: 2.5},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "2", // Less Than
|
||
|
matchType: "1", // Once
|
||
|
target: 4,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 4.5},
|
||
|
{F: 4.5},
|
||
|
{F: 4.5},
|
||
|
{F: 4.5},
|
||
|
{F: 4.5},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "2", // Less Than
|
||
|
matchType: "1", // Once
|
||
|
target: 4,
|
||
|
},
|
||
|
// Test cases for OnAverage
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 4.0},
|
||
|
{F: 6.0},
|
||
|
{F: 8.0},
|
||
|
{F: 2.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "3", // OnAverage
|
||
|
target: 6.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 4.0},
|
||
|
{F: 6.0},
|
||
|
{F: 8.0},
|
||
|
{F: 2.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "3", // OnAverage
|
||
|
target: 4.5,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 4.0},
|
||
|
{F: 6.0},
|
||
|
{F: 8.0},
|
||
|
{F: 2.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "3", // OnAverage
|
||
|
target: 4.5,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 4.0},
|
||
|
{F: 6.0},
|
||
|
{F: 8.0},
|
||
|
{F: 2.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "3", // OnAverage
|
||
|
target: 6.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 4.0},
|
||
|
{F: 6.0},
|
||
|
{F: 8.0},
|
||
|
{F: 2.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "1", // Greater Than
|
||
|
matchType: "3", // OnAverage
|
||
|
target: 4.5,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 4.0},
|
||
|
{F: 6.0},
|
||
|
{F: 8.0},
|
||
|
{F: 2.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "2", // Less Than
|
||
|
matchType: "3", // OnAverage
|
||
|
target: 12.0,
|
||
|
},
|
||
|
// Test cases for InTotal
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 4.0},
|
||
|
{F: 6.0},
|
||
|
{F: 8.0},
|
||
|
{F: 2.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "4", // InTotal
|
||
|
target: 30.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 4.0},
|
||
|
{F: 6.0},
|
||
|
{F: 8.0},
|
||
|
{F: 2.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "3", // Equals
|
||
|
matchType: "4", // InTotal
|
||
|
target: 20.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "4", // InTotal
|
||
|
target: 9.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "4", // Not Equals
|
||
|
matchType: "4", // InTotal
|
||
|
target: 10.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 10.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "1", // Greater Than
|
||
|
matchType: "4", // InTotal
|
||
|
target: 10.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 10.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "1", // Greater Than
|
||
|
matchType: "4", // InTotal
|
||
|
target: 20.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 10.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: true,
|
||
|
compareOp: "2", // Less Than
|
||
|
matchType: "4", // InTotal
|
||
|
target: 30.0,
|
||
|
},
|
||
|
{
|
||
|
values: pql.Series{
|
||
|
Floats: []pql.FPoint{
|
||
|
{F: 10.0},
|
||
|
{F: 10.0},
|
||
|
},
|
||
|
},
|
||
|
expectAlert: false,
|
||
|
compareOp: "2", // Less Than
|
||
|
matchType: "4", // InTotal
|
||
|
target: 20.0,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for idx, c := range cases {
|
||
|
postableRule.RuleCondition.CompareOp = CompareOp(c.compareOp)
|
||
|
postableRule.RuleCondition.MatchType = MatchType(c.matchType)
|
||
|
postableRule.RuleCondition.Target = &c.target
|
||
|
|
||
|
rule, err := NewPromRule("69", &postableRule, testLogger{t}, PromRuleOpts{})
|
||
|
if err != nil {
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
|
||
|
_, shoulAlert := rule.shouldAlert(c.values)
|
||
|
assert.Equal(t, c.expectAlert, shoulAlert, "Test case %d", idx)
|
||
|
}
|
||
|
}
|