prometheus源码阅读 - 规则管理与告警

初始化

rules/manager.go

ruleManager := rules.NewManager(&rules.ManagerOptions{
		Appendable:  fanoutStorage,
		Notifier:    notifier,
		QueryEngine: queryEngine,
		Context:     ctx,
		ExternalURL: cfg.web.ExternalURL,
		Logger:      log.With(logger, "component", "rule manager"),
	})

go ruleManager.Run()

配置

rules/manager.go

func (m *Manager) ApplyConfig(conf *config.Config) error {
    var files []string
    for _, pat := range conf.RuleFiles {
        fs, err := filepath.Glob(pat)
        files = append(files, fs...)
    }
    groups, errs := m.loadGroups(time.Duration(conf.GlobalConfig.EvaluationInterval), files...)
    for _, newg := range groups {
        go func(newg *Group) {
            go func() {
                newg.run()
            }
        }
    }
}

主要做了如下几件事情:

  1. 列出配置的所有rules文件
  2. 解析rules文件
  3. 按groupName分组
  4. group.Run(),此处会启动定时任务,按照配置的频率evaluation_interval执行告警或者汇总规则

运行规则

运行group

rules/manager.go中的group.Run()运行group

iter := func() {
    start := time.Now()
	g.Eval(start)
}
iter()
tick := time.NewTicker(g.interval)
for {
		select {
            default:
			select {
                case <-tick.C:    //按照频率重新运行该group
                    iter()
            }
        }
}

运行规则

rules/manager.go中的Eval方法,将循环当前group的所有rule,并执行eval

func (g *Group) Eval(ts time.Time) {
     for i, rule := range g.rules {
         func(i int, rule Rule) {
            vector, err := rule.Eval(g.opts.Context, ts, g.opts.QueryEngine, g.opts.ExternalURL)
            if ar, ok := rule.(*AlertingRule); ok {
				g.sendAlerts(ar)
			}
         }(i, rule)
     }
}

调用rules/alerting.go的Eval()方法,判断是否需要进行alert:

func (r *AlertingRule) Eval(ctx context.Context, ts time.Time, engine *promql.Engine, externalURL *url.URL) (promql.Vector, error) {
    res, err := query.Exec(ctx).Vector()   //查询
    for _, smpl := range res {
        r.active[h] = &Alert{ //缓存alert
            ActiveAt:    ts,
			State:       StatePending,
        }
    } 
    // 调整alert的告警状态
    for fp, a := range r.active {
        if _, ok := resultFPs[fp]; !ok {
            if a.State == StatePending || (!a.ResolvedAt.IsZero() && ts.Sub(a.ResolvedAt) > resolvedRetention) {
				delete(r.active, fp)
			}
			if a.State != StateInactive {
				a.State = StateInactive
				a.ResolvedAt = ts
			}
			continue
        }
        if a.State == StatePending && ts.Sub(a.ActiveAt) >= r.holdDuration {
			a.State = StateFiring
		}
    }
}

发送告警

rules/manager.go中的sendAlerts方法 , 最终调用Notifier.Send()方法将alert发送给alertmanager

func (g *Group) sendAlerts(rule *AlertingRule) error {
    var alerts []*notifier.Alert
    for _, alert := range rule.currentAlerts() {
        if alert.State == StatePending {
			continue
		}   
    }
    if len(alerts) > 0 {
		g.opts.Notifier.Send(alerts...)
	}
}

转载于:https://my.oschina.net/sannychan/blog/1596807

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值