Alerting: Add doc comments to classic.go (#56724)
This commit is contained in:
+99
-69
@@ -11,92 +11,71 @@ import (
|
||||
"github.com/grafana/grafana/pkg/expr/mathexp"
|
||||
)
|
||||
|
||||
// ConditionsCmd is command for the classic conditions
|
||||
// expression operation.
|
||||
// ConditionsCmd is a command that supports the reduction and comparison of conditions.
|
||||
//
|
||||
// A condition in ConditionsCmd can reduce a time series, contain an instant metric, or the
|
||||
// result of another expression; and checks if it exceeds a threshold, falls within a range,
|
||||
// or does not contain a value.
|
||||
//
|
||||
// If ConditionsCmd contains more than one condition, it reduces the boolean outcomes of the
|
||||
// threshold, range or value checks using the logical operator of the right hand side condition
|
||||
// until all conditions have been reduced to a single boolean outcome. ConditionsCmd does not
|
||||
// follow operator precedence.
|
||||
//
|
||||
// For example if we have the following classic condition:
|
||||
//
|
||||
// min(A) > 5 OR max(B) < 10 AND C = 1
|
||||
//
|
||||
// which reduces to the following boolean outcomes:
|
||||
//
|
||||
// false OR true AND true
|
||||
//
|
||||
// then the outcome of ConditionsCmd is true.
|
||||
type ConditionsCmd struct {
|
||||
Conditions []condition
|
||||
refID string
|
||||
RefID string
|
||||
}
|
||||
|
||||
// ClassicConditionJSON is the JSON model for a single condition.
|
||||
// It is based on services/alerting/conditions/query.go's newQueryCondition().
|
||||
type ClassicConditionJSON struct {
|
||||
Evaluator ConditionEvalJSON `json:"evaluator"`
|
||||
|
||||
Operator struct {
|
||||
Type string `json:"type"`
|
||||
} `json:"operator"`
|
||||
|
||||
Query struct {
|
||||
Params []string `json:"params"`
|
||||
} `json:"query"`
|
||||
|
||||
Reducer struct {
|
||||
// Params []interface{} `json:"params"` (Unused)
|
||||
Type string `json:"type"`
|
||||
} `json:"reducer"`
|
||||
}
|
||||
|
||||
type ConditionEvalJSON struct {
|
||||
Params []float64 `json:"params"`
|
||||
Type string `json:"type"` // e.g. "gt"
|
||||
}
|
||||
|
||||
// condition is a single condition within the ConditionsCmd.
|
||||
// condition is a single condition in ConditionsCmd.
|
||||
type condition struct {
|
||||
QueryRefID string
|
||||
Reducer classicReducer
|
||||
Evaluator evaluator
|
||||
Operator string
|
||||
}
|
||||
InputRefID string
|
||||
|
||||
type classicReducer string
|
||||
// Reducer reduces a series of data into a single result. An example of a reducer is the avg,
|
||||
// min and max functions.
|
||||
Reducer reducer
|
||||
|
||||
// Evaluator evaluates the reduced time series, instant metric, or result of another expression
|
||||
// against an evaluator. An example of an evaluator is checking if it exceeds a threshold,
|
||||
// falls within a range, or does not contain a value.
|
||||
Evaluator evaluator
|
||||
|
||||
// Operator is the logical operator to use when there are two conditions in ConditionsCmd.
|
||||
// If there are more than two conditions in ConditionsCmd then operator is used to compare
|
||||
// the outcome of this condition with that of the condition before it.
|
||||
Operator string
|
||||
}
|
||||
|
||||
// NeedsVars returns the variable names (refIds) that are dependencies
|
||||
// to execute the command and allows the command to fulfill the Command interface.
|
||||
func (ccc *ConditionsCmd) NeedsVars() []string {
|
||||
func (cmd *ConditionsCmd) NeedsVars() []string {
|
||||
vars := []string{}
|
||||
for _, c := range ccc.Conditions {
|
||||
vars = append(vars, c.QueryRefID)
|
||||
for _, c := range cmd.Conditions {
|
||||
vars = append(vars, c.InputRefID)
|
||||
}
|
||||
return vars
|
||||
}
|
||||
|
||||
// EvalMatch represents the series violating the threshold.
|
||||
// It goes into the metadata of data frames so it can be extracted.
|
||||
type EvalMatch struct {
|
||||
Value *float64 `json:"value"`
|
||||
Metric string `json:"metric"`
|
||||
Labels data.Labels `json:"labels"`
|
||||
}
|
||||
|
||||
func (em EvalMatch) MarshalJSON() ([]byte, error) {
|
||||
fs := ""
|
||||
if em.Value != nil {
|
||||
fs = strconv.FormatFloat(*em.Value, 'f', -1, 64)
|
||||
}
|
||||
return json.Marshal(struct {
|
||||
Value string `json:"value"`
|
||||
Metric string `json:"metric"`
|
||||
Labels data.Labels `json:"labels"`
|
||||
}{
|
||||
fs,
|
||||
em.Metric,
|
||||
em.Labels,
|
||||
})
|
||||
}
|
||||
|
||||
// Execute runs the command and returns the results or an error if the command
|
||||
// failed to execute.
|
||||
func (ccc *ConditionsCmd) Execute(ctx context.Context, vars mathexp.Vars) (mathexp.Results, error) {
|
||||
func (cmd *ConditionsCmd) Execute(_ context.Context, vars mathexp.Vars) (mathexp.Results, error) {
|
||||
firing := true
|
||||
newRes := mathexp.Results{}
|
||||
noDataFound := true
|
||||
|
||||
matches := []EvalMatch{}
|
||||
|
||||
for i, c := range ccc.Conditions {
|
||||
querySeriesSet := vars[c.QueryRefID]
|
||||
for i, c := range cmd.Conditions {
|
||||
querySeriesSet := vars[c.InputRefID]
|
||||
nilReducedCount := 0
|
||||
firingCount := 0
|
||||
for _, val := range querySeriesSet.Values {
|
||||
@@ -184,19 +163,70 @@ func (ccc *ConditionsCmd) Execute(ctx context.Context, vars mathexp.Vars) (mathe
|
||||
return newRes, nil
|
||||
}
|
||||
|
||||
// EvalMatch represents the series violating the threshold.
|
||||
// It goes into the metadata of data frames so it can be extracted.
|
||||
type EvalMatch struct {
|
||||
Value *float64 `json:"value"`
|
||||
Metric string `json:"metric"`
|
||||
Labels data.Labels `json:"labels"`
|
||||
}
|
||||
|
||||
func (em EvalMatch) MarshalJSON() ([]byte, error) {
|
||||
fs := ""
|
||||
if em.Value != nil {
|
||||
fs = strconv.FormatFloat(*em.Value, 'f', -1, 64)
|
||||
}
|
||||
return json.Marshal(struct {
|
||||
Value string `json:"value"`
|
||||
Metric string `json:"metric"`
|
||||
Labels data.Labels `json:"labels"`
|
||||
}{
|
||||
fs,
|
||||
em.Metric,
|
||||
em.Labels,
|
||||
})
|
||||
}
|
||||
|
||||
// ConditionJSON is the JSON model for a single condition in ConditionsCmd.
|
||||
// It is based on services/alerting/conditions/query.go's newQueryCondition().
|
||||
type ConditionJSON struct {
|
||||
Evaluator ConditionEvalJSON `json:"evaluator"`
|
||||
Operator ConditionOperatorJSON `json:"operator"`
|
||||
Query ConditionQueryJSON `json:"query"`
|
||||
Reducer ConditionReducerJSON `json:"reducer"`
|
||||
}
|
||||
|
||||
type ConditionEvalJSON struct {
|
||||
Params []float64 `json:"params"`
|
||||
Type string `json:"type"` // e.g. "gt"
|
||||
}
|
||||
|
||||
type ConditionOperatorJSON struct {
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type ConditionQueryJSON struct {
|
||||
Params []string `json:"params"`
|
||||
}
|
||||
|
||||
type ConditionReducerJSON struct {
|
||||
Type string `json:"type"`
|
||||
// Params []interface{} `json:"params"` (Unused)
|
||||
}
|
||||
|
||||
// UnmarshalConditionsCmd creates a new ConditionsCmd.
|
||||
func UnmarshalConditionsCmd(rawQuery map[string]interface{}, refID string) (*ConditionsCmd, error) {
|
||||
jsonFromM, err := json.Marshal(rawQuery["conditions"])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to remarshal classic condition body: %w", err)
|
||||
}
|
||||
var ccj []ClassicConditionJSON
|
||||
var ccj []ConditionJSON
|
||||
if err = json.Unmarshal(jsonFromM, &ccj); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal remarshaled classic condition body: %w", err)
|
||||
}
|
||||
|
||||
c := &ConditionsCmd{
|
||||
refID: refID,
|
||||
RefID: refID,
|
||||
}
|
||||
|
||||
for i, cj := range ccj {
|
||||
@@ -208,12 +238,12 @@ func UnmarshalConditionsCmd(rawQuery map[string]interface{}, refID string) (*Con
|
||||
cond.Operator = cj.Operator.Type
|
||||
|
||||
if len(cj.Query.Params) == 0 || cj.Query.Params[0] == "" {
|
||||
return nil, fmt.Errorf("condition %v is missing the query refID argument", i+1)
|
||||
return nil, fmt.Errorf("condition %v is missing the query RefID argument", i+1)
|
||||
}
|
||||
|
||||
cond.QueryRefID = cj.Query.Params[0]
|
||||
cond.InputRefID = cj.Query.Params[0]
|
||||
|
||||
cond.Reducer = classicReducer(cj.Reducer.Type)
|
||||
cond.Reducer = reducer(cj.Reducer.Type)
|
||||
if !cond.Reducer.ValidReduceFunc() {
|
||||
return nil, fmt.Errorf("invalid reducer '%v' in condition %v", cond.Reducer, i+1)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user