mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-11 17:19:06 +08:00
chore: add missing shiftby in alert rule (#6239)
This commit is contained in:
parent
00421235b0
commit
6c7167a224
@ -1142,25 +1142,7 @@ func ParseQueryRangeParams(r *http.Request) (*v3.QueryRangeParamsV3, *model.ApiE
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the time shift function from the list of functions and set the shift by value
|
||||
var timeShiftBy int64
|
||||
if len(query.Functions) > 0 {
|
||||
for idx := range query.Functions {
|
||||
function := &query.Functions[idx]
|
||||
if function.Name == v3.FunctionNameTimeShift {
|
||||
// move the function to the beginning of the list
|
||||
// so any other function can use the shifted time
|
||||
var fns []v3.Function
|
||||
fns = append(fns, *function)
|
||||
fns = append(fns, query.Functions[:idx]...)
|
||||
fns = append(fns, query.Functions[idx+1:]...)
|
||||
query.Functions = fns
|
||||
timeShiftBy = int64(function.Args[0].(float64))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
query.ShiftBy = timeShiftBy
|
||||
query.SetShiftByFromFunc()
|
||||
|
||||
if query.Filters == nil || len(query.Filters.Items) == 0 {
|
||||
continue
|
||||
|
@ -297,6 +297,8 @@ func TestParseQueryRangeParamsCompositeQuery(t *testing.T) {
|
||||
compositeQuery v3.CompositeQuery
|
||||
expectErr bool
|
||||
errMsg string
|
||||
hasShiftBy bool
|
||||
shiftBy int64
|
||||
}{
|
||||
{
|
||||
desc: "no query in request",
|
||||
@ -496,6 +498,56 @@ func TestParseQueryRangeParamsCompositeQuery(t *testing.T) {
|
||||
expectErr: true,
|
||||
errMsg: "builder query A is invalid: group by is invalid",
|
||||
},
|
||||
{
|
||||
desc: "builder query with shift by",
|
||||
compositeQuery: v3.CompositeQuery{
|
||||
PanelType: v3.PanelTypeGraph,
|
||||
QueryType: v3.QueryTypeBuilder,
|
||||
BuilderQueries: map[string]*v3.BuilderQuery{
|
||||
"A": {
|
||||
QueryName: "A",
|
||||
DataSource: "logs",
|
||||
AggregateOperator: "sum",
|
||||
AggregateAttribute: v3.AttributeKey{Key: "attribute"},
|
||||
GroupBy: []v3.AttributeKey{{Key: "group_key"}},
|
||||
Expression: "A",
|
||||
Functions: []v3.Function{
|
||||
{
|
||||
Name: v3.FunctionNameTimeShift,
|
||||
Args: []interface{}{float64(10)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
hasShiftBy: true,
|
||||
shiftBy: 10,
|
||||
},
|
||||
{
|
||||
desc: "builder query with shift by as string",
|
||||
compositeQuery: v3.CompositeQuery{
|
||||
PanelType: v3.PanelTypeGraph,
|
||||
QueryType: v3.QueryTypeBuilder,
|
||||
BuilderQueries: map[string]*v3.BuilderQuery{
|
||||
"A": {
|
||||
QueryName: "A",
|
||||
DataSource: "logs",
|
||||
AggregateOperator: "sum",
|
||||
AggregateAttribute: v3.AttributeKey{Key: "attribute"},
|
||||
GroupBy: []v3.AttributeKey{{Key: "group_key"}},
|
||||
Expression: "A",
|
||||
Functions: []v3.Function{
|
||||
{
|
||||
Name: v3.FunctionNameTimeShift,
|
||||
Args: []interface{}{"3600"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
hasShiftBy: true,
|
||||
shiftBy: 3600,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range reqCases {
|
||||
@ -514,13 +566,16 @@ func TestParseQueryRangeParamsCompositeQuery(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v3/query_range", body)
|
||||
|
||||
_, apiErr := ParseQueryRangeParams(req)
|
||||
params, apiErr := ParseQueryRangeParams(req)
|
||||
if tc.expectErr {
|
||||
require.Error(t, apiErr)
|
||||
require.Contains(t, apiErr.Error(), tc.errMsg)
|
||||
} else {
|
||||
require.Nil(t, apiErr)
|
||||
}
|
||||
if tc.hasShiftBy {
|
||||
require.Equal(t, tc.shiftBy, params.CompositeQuery.BuilderQueries["A"].ShiftBy)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type DataSource string
|
||||
@ -789,6 +790,38 @@ type BuilderQuery struct {
|
||||
QueriesUsedInFormula []string
|
||||
}
|
||||
|
||||
func (b *BuilderQuery) SetShiftByFromFunc() {
|
||||
// Remove the time shift function from the list of functions and set the shift by value
|
||||
var timeShiftBy int64
|
||||
if len(b.Functions) > 0 {
|
||||
for idx := range b.Functions {
|
||||
function := &b.Functions[idx]
|
||||
if function.Name == FunctionNameTimeShift {
|
||||
// move the function to the beginning of the list
|
||||
// so any other function can use the shifted time
|
||||
var fns []Function
|
||||
fns = append(fns, *function)
|
||||
fns = append(fns, b.Functions[:idx]...)
|
||||
fns = append(fns, b.Functions[idx+1:]...)
|
||||
b.Functions = fns
|
||||
if len(function.Args) > 0 {
|
||||
if shift, ok := function.Args[0].(float64); ok {
|
||||
timeShiftBy = int64(shift)
|
||||
} else if shift, ok := function.Args[0].(string); ok {
|
||||
shiftBy, err := strconv.ParseFloat(shift, 64)
|
||||
if err != nil {
|
||||
zap.L().Error("failed to parse time shift by", zap.String("shift", shift), zap.Error(err))
|
||||
}
|
||||
timeShiftBy = int64(shiftBy)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
b.ShiftBy = timeShiftBy
|
||||
}
|
||||
|
||||
func (b *BuilderQuery) Clone() *BuilderQuery {
|
||||
if b == nil {
|
||||
return nil
|
||||
|
@ -152,6 +152,9 @@ func (r *ThresholdRule) prepareQueryRange(ts time.Time) (*v3.QueryRangeParamsV3,
|
||||
if minStep := common.MinAllowedStepInterval(start, end); q.StepInterval < minStep {
|
||||
q.StepInterval = minStep
|
||||
}
|
||||
|
||||
q.SetShiftByFromFunc()
|
||||
|
||||
if q.DataSource == v3.DataSourceMetrics && constants.UseMetricsPreAggregation() {
|
||||
// if the time range is greater than 1 day, and less than 1 week set the step interval to be multiple of 5 minutes
|
||||
// if the time range is greater than 1 week, set the step interval to be multiple of 30 mins
|
||||
|
@ -1602,3 +1602,66 @@ func TestThresholdRuleLogsLink(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestThresholdRuleShiftBy(t *testing.T) {
|
||||
target := float64(10)
|
||||
postableRule := PostableRule{
|
||||
AlertName: "Logs link test",
|
||||
AlertType: AlertTypeLogs,
|
||||
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: "component",
|
||||
},
|
||||
AggregateOperator: v3.AggregateOperatorCountDistinct,
|
||||
DataSource: v3.DataSourceLogs,
|
||||
Expression: "A",
|
||||
Filters: &v3.FilterSet{
|
||||
Operator: "AND",
|
||||
Items: []v3.FilterItem{
|
||||
{
|
||||
Key: v3.AttributeKey{Key: "k8s.container.name", IsColumn: false, Type: v3.AttributeKeyTypeTag, DataType: v3.AttributeKeyDataTypeString},
|
||||
Value: "testcontainer",
|
||||
Operator: v3.FilterOperatorEqual,
|
||||
},
|
||||
},
|
||||
},
|
||||
Functions: []v3.Function{
|
||||
{
|
||||
Name: v3.FunctionNameTimeShift,
|
||||
Args: []interface{}{float64(10)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Target: &target,
|
||||
CompareOp: ValueAboveOrEq,
|
||||
},
|
||||
}
|
||||
|
||||
rule, err := NewThresholdRule("69", &postableRule, nil, nil, true)
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
rule.TemporalityMap = map[string]map[v3.Temporality]bool{
|
||||
"signoz_calls_total": {
|
||||
v3.Delta: true,
|
||||
},
|
||||
}
|
||||
|
||||
params, err := rule.prepareQueryRange(time.Now())
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
assert.Equal(t, int64(10), params.CompositeQuery.BuilderQueries["A"].ShiftBy)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user