Files
signoz/pkg/query-service/rules/manager_test_data.go
Srikanth Chekuri 5abfd0732a
Some checks failed
build-staging / prepare (push) Has been cancelled
build-staging / js-build (push) Has been cancelled
build-staging / go-build (push) Has been cancelled
build-staging / staging (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
chore: remove deprecated v3/v4 support in rules (#10760)
* chore: remove deprecated v3/v4 support in rules

* chore: fix test

* chore: fix logs

* chore: fix logging

* chore: fix ci

* chore: address review comments
2026-04-01 19:48:37 +00:00

229 lines
6.9 KiB
Go

package rules
import (
"math"
"time"
"github.com/SigNoz/signoz/pkg/types/metrictypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
ruletypes "github.com/SigNoz/signoz/pkg/types/ruletypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/SigNoz/signoz/pkg/valuer"
)
// ThresholdRuleTestCase defines test case structure for threshold rule test notifications
type ThresholdRuleTestCase struct {
Name string
Values [][]any
ExpectAlerts int
ExpectValue float64
}
// PromRuleTestValue represents a single value point in a PromQL rule test case
type PromRuleTestValue struct {
Offset time.Duration // offset from baseTime (negative = in the past)
Value float64
}
// PromRuleTestCase defines test case structure for PromQL rule test notifications
type PromRuleTestCase struct {
Name string
Values []PromRuleTestValue
ExpectAlerts int
ExpectValue float64
}
// ThresholdRuleAtLeastOnceValueAbove creates a PostableRule for threshold rule test notifications
func ThresholdRuleAtLeastOnceValueAbove(target float64, recovery *float64) ruletypes.PostableRule {
return ruletypes.PostableRule{
AlertName: "test-alert",
AlertType: ruletypes.AlertTypeMetric,
RuleType: ruletypes.RuleTypeThreshold,
Evaluation: &ruletypes.EvaluationEnvelope{Kind: ruletypes.RollingEvaluation, Spec: ruletypes.RollingWindow{
EvalWindow: valuer.MustParseTextDuration("5m"),
Frequency: valuer.MustParseTextDuration("1m"),
}},
Labels: map[string]string{
"service.name": "frontend",
},
Annotations: map[string]string{
"value": "{{$value}}",
},
Version: "v5",
RuleCondition: &ruletypes.RuleCondition{
MatchType: ruletypes.AtleastOnce,
CompareOperator: ruletypes.ValueIsAbove,
Target: &target,
CompositeQuery: &ruletypes.AlertCompositeQuery{
QueryType: ruletypes.QueryTypeBuilder,
Queries: []qbtypes.QueryEnvelope{
{
Type: qbtypes.QueryTypeBuilder,
Spec: qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation]{
Name: "A",
StepInterval: qbtypes.Step{Duration: 60 * time.Second},
Signal: telemetrytypes.SignalMetrics,
Aggregations: []qbtypes.MetricAggregation{
{
MetricName: "probe_success",
TimeAggregation: metrictypes.TimeAggregationAvg,
SpaceAggregation: metrictypes.SpaceAggregationAvg,
},
},
},
},
},
},
Thresholds: &ruletypes.RuleThresholdData{
Kind: ruletypes.BasicThresholdKind,
Spec: ruletypes.BasicRuleThresholds{
{
Name: "primary",
TargetValue: &target,
RecoveryTarget: recovery,
MatchType: ruletypes.AtleastOnce,
CompareOperator: ruletypes.ValueIsAbove,
},
},
},
},
NotificationSettings: &ruletypes.NotificationSettings{},
}
}
// BuildPromAtLeastOnceValueAbove creates a PostableRule for PromQL rule test notifications
func BuildPromAtLeastOnceValueAbove(target float64, recovery *float64) ruletypes.PostableRule {
return ruletypes.PostableRule{
AlertName: "test-prom-alert",
AlertType: ruletypes.AlertTypeMetric,
RuleType: ruletypes.RuleTypeProm,
Evaluation: &ruletypes.EvaluationEnvelope{Kind: ruletypes.RollingEvaluation, Spec: ruletypes.RollingWindow{
EvalWindow: valuer.MustParseTextDuration("5m"),
Frequency: valuer.MustParseTextDuration("1m"),
}},
Labels: map[string]string{
"service.name": "frontend",
},
Annotations: map[string]string{
"value": "{{$value}}",
},
Version: "v5",
RuleCondition: &ruletypes.RuleCondition{
MatchType: ruletypes.AtleastOnce,
SelectedQuery: "A",
CompareOperator: ruletypes.ValueIsAbove,
Target: &target,
CompositeQuery: &ruletypes.AlertCompositeQuery{
QueryType: ruletypes.QueryTypePromQL,
PanelType: ruletypes.PanelTypeGraph,
Queries: []qbtypes.QueryEnvelope{
{
Type: qbtypes.QueryTypePromQL,
Spec: qbtypes.PromQuery{
Name: "A",
Query: "{\"test_metric\"}",
Disabled: false,
Stats: false,
},
},
},
},
Thresholds: &ruletypes.RuleThresholdData{
Kind: ruletypes.BasicThresholdKind,
Spec: ruletypes.BasicRuleThresholds{
{
Name: "primary",
TargetValue: &target,
RecoveryTarget: recovery,
MatchType: ruletypes.AtleastOnce,
CompareOperator: ruletypes.ValueIsAbove,
Channels: []string{"slack"},
},
},
},
},
NotificationSettings: &ruletypes.NotificationSettings{},
}
}
var (
// TcTestNotiSendUnmatchedThresholdRule contains test cases for threshold rule test notifications
TcTestNotiSendUnmatchedThresholdRule = []ThresholdRuleTestCase{
{
Name: "return first valid point in case of test notification",
Values: [][]any{
{float64(3), "attr", time.Now()},
{float64(4), "attr", time.Now().Add(1 * time.Minute)},
},
ExpectAlerts: 1,
ExpectValue: 3,
},
{
Name: "No data in DB so no alerts fired",
Values: [][]any{},
ExpectAlerts: 0,
},
{
Name: "return first valid point in case of test notification skips NaN and Inf",
Values: [][]any{
{math.NaN(), "attr", time.Now()},
{math.Inf(1), "attr", time.Now().Add(1 * time.Minute)},
{float64(7), "attr", time.Now().Add(2 * time.Minute)},
},
ExpectAlerts: 1,
ExpectValue: 7,
},
{
Name: "If found matching alert with given target value, return the alerting value rather than first valid point",
Values: [][]any{
{float64(1), "attr", time.Now()},
{float64(2), "attr", time.Now().Add(1 * time.Minute)},
{float64(3), "attr", time.Now().Add(2 * time.Minute)},
{float64(12), "attr", time.Now().Add(3 * time.Minute)},
},
ExpectAlerts: 1,
ExpectValue: 12,
},
}
// TcTestNotificationSendUnmatchedPromRule contains test cases for PromQL rule test notifications
TcTestNotificationSendUnmatchedPromRule = []PromRuleTestCase{
{
Name: "return first valid point in case of test notification",
Values: []PromRuleTestValue{
{Offset: -4 * time.Minute, Value: 3},
{Offset: -3 * time.Minute, Value: 4},
},
ExpectAlerts: 1,
ExpectValue: 3,
},
{
Name: "No data in DB so no alerts fired",
Values: []PromRuleTestValue{},
ExpectAlerts: 0,
},
{
Name: "return first valid point in case of test notification skips NaN and Inf",
Values: []PromRuleTestValue{
{Offset: -4 * time.Minute, Value: math.NaN()},
{Offset: -3 * time.Minute, Value: math.Inf(1)},
{Offset: -2 * time.Minute, Value: 7},
},
ExpectAlerts: 1,
ExpectValue: 7,
},
{
Name: "If found matching alert with given target value, return the alerting value rather than first valid point",
Values: []PromRuleTestValue{
{Offset: -4 * time.Minute, Value: 1},
{Offset: -3 * time.Minute, Value: 2},
{Offset: -2 * time.Minute, Value: 3},
{Offset: -1 * time.Minute, Value: 12},
},
ExpectAlerts: 1,
ExpectValue: 12,
},
}
)