在告警引擎设计中,通用的阶梯告警规则,是非常常见的场景。
且需要很容易集成进告警引擎中
如何设计一个较为通用的阶梯告警逻辑,不难。
- 要点:引入表达式,用于生成复杂告警规则表达式
阶梯告警模版设计
package rules
import (
"fmt"
"strings"
"github.com/Knetic/govaluate"
)
const (
ExpressionCurrentKey = "Current"
ExpressionPreviousValueKey = "PreviousValue"
)
var (
// Define alert Rules
Rules = []AlertTieredRule{
{ThresholdMin: 50, ThresholdMax: 60, IncreasePercent: 20},
{ThresholdMin: 30, ThresholdMax: 50, IncreasePercent: 30},
{ThresholdMin: 10, ThresholdMax: 30, IncreasePercent: 40},
{ThresholdMin: 60, ThresholdMax: 70, IncreasePercent: 15},
{ThresholdMin: 70, ThresholdMax: 80, IncreasePercent: 10},
{ThresholdMin: 80, ThresholdMax: 88, IncreasePercent: 5},
}
)
// 告警详情
type Alert struct {
Value float64 //告警值
}
// 告警阶梯模版
type AlertTieredRule struct {
ThresholdMin float64 //阈值起始
ThresholdMax float64 //阈值结束
IncreasePercent float64 //增长百分比
PreviousValue float64 //前值
}
func NewAlertRule() *AlertTieredRule {
return &AlertTieredRule{}
}
func (r *AlertTieredRule) CheckAlert(currentValue Alert, alertRule AlertTieredRule) (bool, error) {
rule := ConstructExpression(Rules)
expr, _ := govaluate.NewEvaluableExpression(rule)
con := make(map[string]interface{})
con[ExpressionCurrentKey] = currentValue.Value
con[ExpressionPreviousValueKey] = alertRule.PreviousValue
result, err := expr.Evaluate(con)
fmt.Println(result, err)
return result.(bool), err
}
// 创建告警「阶梯」条件表达式
func ConstructExpression(conditions []AlertTieredRule) string {
var builder strings.Builder
for i := 0; i < len(conditions); i++ {
condition := []string{
fmt.Sprintf("Current >= %v", conditions[i].ThresholdMin),
fmt.Sprintf("Current < %v", conditions[i].ThresholdMax),
fmt.Sprintf(
"(Current-PreviousValue)/PreviousValue*100 >= %v",
conditions[i].IncreasePercent,
),
}
builder.WriteString(buildExpression(condition))
if len(conditions)-1 == i {
continue
}
builder.WriteString(" || ")
}
return builder.String()
}
// 构建告警表达式
func buildExpression(conditions []string) string {
if len(conditions) == 0 {
return ""
}
expression := conditions[0]
for _, cond := range conditions[1:] {
expression += " && (" + cond + ")"
}
return expression
}
引用
r := rules.NewAlertRule()
r.CheckAlert(
rules.Alert{
Value: 68,
},
rules.AlertTieredRule{
PreviousValue: 61,
},
)