如何对多个告警源的告警内容,进行统一收集、处理
目标:
设计一套通用框架,实现多源告警内容的 告警处理,包括优先级、白名单、复杂表达式处理,以及去重、聚合等
规则库
构建规则库,用于处理告警、对告警执行规则过滤
定义数据模型
Alert:告警内容
Condition:条件接口 ;主要方法:Evaluate;评估告警
Rule:定义告警优先级、标签、互斥标签、条件『组合』、动作、白名单、链式调用、表达式
package service
type Alert struct {
Source string
Type string
Severity string
CPUUsage float64
MemUsage float64
Message string
}
type Condition interface {
`Evaluate`(alert Alert) bool
}
type Rule struct {
Priority int
Label string
MutexLabels []string
Conditions []Condition
Action func(Alert)
WhiteList []string
Next *Rule
Expression string
}
实现告警内容 Evaluate 接口
以CPU使用率过高 HighCPUUsageCondition 为例,实现 Evaluate 接口
用于实现评估逻辑:
- 比如 告警是否统一关联的service name
- 包括去重计数器处理、聚合逻辑执行 等
以及用于判断是否继续往下一规则处理
「扩展」
- 这里可以引入自己实现的去重算法实现,最常见的参考alertmanager基于时间hash的去重算法
- 多重策略算法时,可以使用策略模式设计模式
package service
import (
"context"
"fmt"
"sort"
"github.com/PaesslerAG/gval"
)
func handleHighCPUUsage(alert Alert) {
// 处理高 CPU 使用率告警
}
func handleHighMemoryUsage(alert Alert) {
// 处理高内存使用率告警
}
type HighCPUUsageCondition struct {
Threshold float64
}
func (c HighCPUUsageCondition) Evaluate(alert Alert) bool {
return alert.CPUUsage > c.Threshold
}
type DatabaseDownCondition struct{}
func (c DatabaseDownCondition) `Evaluate`(alert Alert) bool {
return alert.Type == "Database" && alert.Message == "Down"
}
type HighMemoryUsageCondition struct {
Threshold float64
}
func (c HighMemoryUsageCondition) Evaluate(alert Alert) bool {
return alert.MemUsage > c.Threshold
}
实现告警 Action 回调函数 func(Alert)
用于执行 告警处理后的后续动作,比如发送告警、静默等
func handleHighResourceUsage(alert Alert) {
// 处理资源使用高的情况
}
func handleDatabaseDown(alert Alert) {
// 处理数据库宕机情况
}
告警内容表达式处理
使用规则 处理 告警内容
引入表达式,场景:
对告警指标值,做逻辑判断,比如 多个告警指标间逻辑判断,包括跨告警内容间
「扩展」
- 这里的规则表达式,很容易和前端整合,实现复杂告警规则处理
package service
import (
"context"
"fmt"
"sort"
"github.com/PaesslerAG/gval"
)
func evaluateRule(rule Rule, alert Alert) (bool, error) {
evaluation, err := gval.Full().NewEvaluable(rule.Expression)
if err != nil {
return false, err
}
result, err := evaluation(context.Background(), map[string]interface{}{
"Type": alert.Type,
"CPUUsage": alert.CPUUsage,
"MemUsage": alert.MemUsage,
// 其他字段...
})
if err != nil {
return false, err
}
matched, ok := result.(bool)
if !ok {
return false, fmt.Errorf("expression does not evaluate to a boolean")
}
return matched, nil
}
多规则间处理
比如:处理规则间 优先级排序
将规则 构建为
规则链
DefineRules:演示了 如何对规则 进行排序、以及构建为 规则链
- 以及如何构建 规则,包括 定义优先级、条件组合、动作、白名单、标签、互斥标签等
DefineRulesV2 与 DefineRules区别是:
- 引入 表达式,支持复杂表达式间逻辑处理
func DefineRules() *Rule {
rule1 := &Rule{
Priority: 1,
Conditions: []Condition{
HighCPUUsageCondition{Threshold: 80},
HighMemoryUsageCondition{Threshold: 75},
},
Action: handleHighResourceUsage,
WhiteList: []string{"MonitoringSystem"},
Label: "HighResourceUsage",
MutexLabels: []string{"DatabaseDown"},
}
rule2 := &Rule{
Priority: 2,
Conditions: []Condition{
DatabaseDownCondition{},
},
Action: handleDatabaseDown,
WhiteList: []string{},
Label: "DatabaseDown",
MutexLabels: []string{"HighResourceUsage"},
}
// 根据优先级排序规则
sortedRules := sortRulesByPriority([]*Rule{rule1, rule2})
buildRuleChain(sortedRules)
return sortedRules[0]
}
func sortRulesByPriority(rules []*Rule) []*Rule {
// 实现优先级排序逻辑
sort.Slice(rules, func(i, j int) bool {
return rules[i].Priority < rules[j].Priority
})
return rules
}
func buildRuleChain(sortedRules []*Rule) {
// 将规则链接成链
for i := 0; i < len(sortedRules)-1; i++ {
sortedRules[i].Next = sortedRules[i+1]
}
}
func DefineRulesV2() []Rule {
return []Rule{
{
Expression: "Type == 'CPU' && CPUUsage > 80",
Action: handleHighCPUUsage,
},
{
Expression: "Type == 'Memory' && MemUsage > 75",
Action: handleHighMemoryUsage,
},
// 更多规则...
}
}
规则处理引擎
ProcessAlert 引擎 主要 方法,
- 对引擎规则进行 链式调用,持续处理引擎的规则,依次匹配命中
evaluateConditions 会对告警进行判断
- 若规则已经处理过告警,是否允许继续被其他规则处理
ProcessAlert 主函数
- 将告警内容扔至 evaluateRule ,依次被规则链 处理
package service
type Engine struct {
FirstRule *Rule
}
func NewEngine(firstRule *Rule) *Engine {
return &Engine{FirstRule: firstRule}
}
func isInWhiteList(alert Alert, whiteList []string) bool {
// 实现白名单检查逻辑
return true
}
func evaluateConditions(alert Alert, conditions []Condition) bool {
// 实现条件评估逻辑
return true
}
func (e *Engine) ProcessAlert(alert Alert) {
triggeredLabels := make(map[string]bool)
for r := e.FirstRule; r != nil; r = r.Next {
// if isInWhiteList(alert, r.WhiteList) {
// r.Action(alert)
// return
// }
// if evaluateConditions(alert, r.Conditions) {
// r.Action(alert)
// return
// }
// 检查白名单
if isInWhiteList(alert, r.WhiteList) {
r.Action(alert)
triggeredLabels[r.Label] = true
continue
}
// 检查互斥
if isMutex(triggeredLabels, r.MutexLabels) {
continue
}
// 检查条件
if evaluateConditions(alert, r.Conditions) {
/*
告警在rule1处理过,不允许在rule2再次处理
*/
// r.Action(alert)
// triggeredLabels[r.Label] = true
/*
告警在rule1处理过,允许在rule2再次处理
*/
r.Action(alert)
// 不再跳出循环,允许进一步检查其他规则
}
}
for r := e.FirstRule; r != nil; r = r.Next {
allConditionsMet := true
for _, condition := range r.Conditions {
if !condition.Evaluate(alert) {
allConditionsMet = false
break
}
}
if allConditionsMet {
r.Action(alert)
break
}
}
}
// 互斥检查
func isMutex(triggeredLabels map[string]bool, mutexLabels []string) bool {
for _, label := range mutexLabels {
if triggeredLabels[label] {
return true
}
}
return false
}
func ProcessAlert(alert Alert, rules []Rule) {
for _, rule := range rules {
matched, err := evaluateRule(rule, alert)
if err != nil {
// 处理错误...
continue
}
if matched {
rule.Action(alert)
}
}
}
调用处理引擎
「扩展」
- 实际处理中,可以在引擎上封装,构建超级引擎
func TestProcessAlert(t *testing.T){
firstRule := service.DefineRules()
engine := service.NewEngine(firstRule)
alert := service.Alert{
Source: "System",
Type: "CPU",
Severity: "High",
CPUUsage: 85.0,
MemUsage: 80.0,
}
engine.ProcessAlert(alert)
}
func TestProcessAlertV2(t *testing.T) {
rules := service.DefineRulesV2()
alert := service.Alert{
Type: "CPU",
CPUUsage: 85.0,
}
service.ProcessAlert(alert, rules)
}