alertmanager源码阅读 - alerts接收

prometheus发送alert的接口:/api/v1/alerts,初始化代码在api/api.go

func (api *API) Register(r *route.Router) {
    r.Post("/alerts", ihf("add_alerts", api.addAlerts))
}
func (api *API) addAlerts(w http.ResponseWriter, r *http.Request) {
	var alerts []*types.Alert
	if err := receive(r, &alerts); err != nil { //
		respondError()
		return
	}
	api.insertAlerts(w, r, alerts...)
}

func (api *API) insertAlerts(w http.ResponseWriter, r *http.Request, alerts ...*types.Alert) {
    now := time.Now()
    for _, alert := range alerts {
        alert.UpdatedAt = now
        if alert.EndsAt.IsZero() {
			alert.Timeout = true
			alert.EndsAt = now.Add(api.resolveTimeout) //如果resolveTimeout后alert没有更新,alert会被标记为resolved,默认的resolveTimeout为5m
			numReceivedAlerts.WithLabelValues("firing").Inc()
		} else {
			numReceivedAlerts.WithLabelValues("resolved").Inc()
		}
        
    }
    var (
		validAlerts    = make([]*types.Alert, 0, len(alerts))
		validationErrs = &types.MultiError{}
	)
    for _, a := range alerts {
		if err := a.Validate(); err != nil {
			continue
		}
		validAlerts = append(validAlerts, a)
	}
    if err := api.alerts.Put(validAlerts...); err != nil {

    }
}

接下来我们看看alerts.Put(),这是一个接口方法,目前的版本只有mem实现方式,代码在:provider/mem/mem.go

func (a *Alerts) Put(alerts ...*types.Alert) error {
    for _, alert := range alerts {
        fp := alert.Fingerprint()
        if old, ok := a.alerts[fp]; ok {
			if (alert.EndsAt.After(old.StartsAt) && alert.EndsAt.Before(old.EndsAt)) ||
				(alert.StartsAt.After(old.StartsAt) && alert.StartsAt.Before(old.EndsAt)) {
				alert = old.Merge(alert)
			}
		}

		a.alerts[fp] = alert

		for _, ch := range a.listeners {
			ch <- alert
		}
    }
}

接收alert的最终去向是向ch chan写入了数据,我们再来看看此处的ch是如何来的。

ch 是循环listeners,再追溯listeners的来源,就是provider/mem/mem.go的Subscribe()方法。

func (a *Alerts) Subscribe() provider.AlertIterator {
    var (
		ch   = make(chan *types.Alert, 200)
		done = make(chan struct{})
	)
    a.listeners[i] = ch
    return provider.NewAlertIterator(ch, done, err)
}

而调用Subscribe()有两处

  • Dispatcher

用于告警的group,router管理,满足条件情况下发送alert。后面有专门的帖子来分析这一块。

func (d *Dispatcher) Run() {
    d.run(d.alerts.Subscribe())
}
  • Inhibitor

Inhibitor主要是用于针对两个告警,如果他们在某些指定的属性不同、某些指定的属性相同的情况下,只发送其中某属性为某值的告警。 比如cpu使用率的告警,在90%时为critical,75%时为warning;可以设置Inhibitor规则,让warning告警不发送出来。 笔者在使用过程中,尚未使用Inhibitor的规则。

func (ih *Inhibitor) Run() {
    it := ih.alerts.Subscribe()
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值