signoz/pkg/query-service/rules/thresholdRule_test.go
Vishal Sharma c66c8c2823
chore: add new dashboard/alerts info events (#4214)
* chore: add new dashboard/alerts info events
2023-12-13 18:14:55 +05:30

298 lines
7.0 KiB
Go

package rules
import (
"context"
"testing"
"time"
cmock "github.com/srikanthccv/ClickHouse-go-mock"
"github.com/stretchr/testify/assert"
"go.signoz.io/signoz/pkg/query-service/featureManager"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
)
func TestThresholdRuleCombinations(t *testing.T) {
postableRule := PostableRule{
Alert: "Tricky Condition Tests",
AlertType: "METRIC_BASED_ALERT",
RuleType: RuleTypeThreshold,
EvalWindow: Duration(5 * time.Minute),
Frequency: Duration(1 * time.Minute),
RuleCondition: &RuleCondition{
CompositeQuery: &v3.CompositeQuery{
QueryType: v3.QueryTypeBuilder,
BuilderQueries: map[string]*v3.BuilderQuery{
"A": {
QueryName: "A",
StepInterval: 60,
AggregateAttribute: v3.AttributeKey{
Key: "probe_success",
},
AggregateOperator: v3.AggregateOperatorNoOp,
DataSource: v3.DataSourceMetrics,
Expression: "A",
},
},
},
},
}
fm := featureManager.StartManager()
mock, err := cmock.NewClickHouseNative(nil)
if err != nil {
t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
}
cols := make([]cmock.ColumnType, 0)
cols = append(cols, cmock.ColumnType{Name: "value", Type: "Int32"})
cols = append(cols, cmock.ColumnType{Name: "endpoint", Type: "String"})
cases := []struct {
values [][]interface{}
expectAlert bool
compareOp string
matchType string
target float64
}{
// Test cases for Equals Always
{
values: [][]interface{}{
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
},
expectAlert: true,
compareOp: "3", // Equals
matchType: "2", // Always
target: 0.0,
},
{
values: [][]interface{}{
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(1), "endpoint"},
},
expectAlert: false,
compareOp: "3", // Equals
matchType: "2", // Always
target: 0.0,
},
{
values: [][]interface{}{
{int32(0), "endpoint"},
{int32(1), "endpoint"},
{int32(0), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
},
expectAlert: false,
compareOp: "3", // Equals
matchType: "2", // Always
target: 0.0,
},
{
values: [][]interface{}{
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
},
expectAlert: false,
compareOp: "3", // Equals
matchType: "2", // Always
target: 0.0,
},
// Test cases for Equals Once
{
values: [][]interface{}{
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
},
expectAlert: true,
compareOp: "3", // Equals
matchType: "1", // Once
target: 0.0,
},
{
values: [][]interface{}{
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(1), "endpoint"},
},
expectAlert: true,
compareOp: "3", // Equals
matchType: "1", // Once
target: 0.0,
},
{
values: [][]interface{}{
{int32(0), "endpoint"},
{int32(1), "endpoint"},
{int32(0), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
},
expectAlert: true,
compareOp: "3", // Equals
matchType: "1", // Once
target: 0.0,
},
{
values: [][]interface{}{
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
},
expectAlert: false,
compareOp: "3", // Equals
matchType: "1", // Once
target: 0.0,
},
// Test cases for Not Equals Always
{
values: [][]interface{}{
{int32(0), "endpoint"},
{int32(1), "endpoint"},
{int32(0), "endpoint"},
{int32(1), "endpoint"},
{int32(0), "endpoint"},
},
expectAlert: false,
compareOp: "4", // Not Equals
matchType: "2", // Always
target: 0.0,
},
{
values: [][]interface{}{
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(0), "endpoint"},
},
expectAlert: false,
compareOp: "4", // Not Equals
matchType: "2", // Always
target: 0.0,
},
{
values: [][]interface{}{
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
},
expectAlert: true,
compareOp: "4", // Not Equals
matchType: "2", // Always
target: 0.0,
},
{
values: [][]interface{}{
{int32(1), "endpoint"},
{int32(0), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
},
expectAlert: false,
compareOp: "4", // Not Equals
matchType: "2", // Always
target: 0.0,
},
// Test cases for Not Equals Once
{
values: [][]interface{}{
{int32(0), "endpoint"},
{int32(1), "endpoint"},
{int32(0), "endpoint"},
{int32(1), "endpoint"},
{int32(0), "endpoint"},
},
expectAlert: true,
compareOp: "4", // Not Equals
matchType: "1", // Once
target: 0.0,
},
{
values: [][]interface{}{
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(0), "endpoint"},
},
expectAlert: false,
compareOp: "4", // Not Equals
matchType: "1", // Once
target: 0.0,
},
{
values: [][]interface{}{
{int32(0), "endpoint"},
{int32(0), "endpoint"},
{int32(1), "endpoint"},
{int32(0), "endpoint"},
{int32(1), "endpoint"},
},
expectAlert: true,
compareOp: "4", // Not Equals
matchType: "1", // Once
target: 0.0,
},
{
values: [][]interface{}{
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
{int32(1), "endpoint"},
},
expectAlert: true,
compareOp: "4", // Not Equals
matchType: "1", // Once
target: 0.0,
},
}
for idx, c := range cases {
rows := cmock.NewRows(cols, c.values)
// We are testing the eval logic after the query is run
// so we don't care about the query string here
queryString := "SELECT value, endpoint FROM table"
mock.
ExpectQuery(queryString).
WillReturnRows(rows)
postableRule.RuleCondition.CompareOp = CompareOp(c.compareOp)
postableRule.RuleCondition.MatchType = MatchType(c.matchType)
postableRule.RuleCondition.Target = &c.target
rule, err := NewThresholdRule("69", &postableRule, ThresholdRuleOpts{}, fm)
if err != nil {
assert.NoError(t, err)
}
result, err := rule.runChQuery(context.Background(), mock, queryString)
if err != nil {
assert.NoError(t, err)
}
if c.expectAlert {
assert.Equal(t, 1, len(result), "case %d", idx)
} else {
assert.Equal(t, 0, len(result), "case %d", idx)
}
}
}