Golang 实现阶梯告警模版,作为告警规则用于集成进告警引擎

193 阅读1分钟

在告警引擎设计中,通用的阶梯告警规则,是非常常见的场景。

且需要很容易集成进告警引擎中

如何设计一个较为通用的阶梯告警逻辑,不难。

  • 要点:引入表达式,用于生成复杂告警规则表达式

阶梯告警模版设计


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,
		},
	)