我配置了一个告警规则,执行频率是60s,持续时长是600s,我这边收到的告警显示有持续时长0s,也有11,12,13,14m 不知道为啥未生效,看描述这个持续时长意思是连续查询10次才会告警,为啥持续时长为0就告警了
我配置了一个告警规则,执行频率是60s,持续时长是600s,我这边收到的告警显示有持续时长0s,也有11,12,13,14m 不知道为啥未生效,看描述这个持续时长意思是连续查询10次才会告警,为啥持续时长为0就告警了
结论是虽然你设置的持续时长是600s,不过还有个重要的配置-‘重复通知间隔(分钟)’,这里描述的问题我认为是和它有关。
再详细解释一下:
‘告警显示有持续时长0s’,这一部分描述中我和碰到的情况不太一样,你可以给出更多描述或者证据。
‘也有11,12,13,14m 不知道为啥未生效,看描述这个持续时长意思是连续查询10次才会告警’,这一部分我目前的判断是因为‘重复通知间隔’配置的问题,不过在不调整配置的情况下,告警恢复再次触发的两次告警会满足你的预期。
本来以为挺了解告警这部分内容,看到这个问题,细想了下,不是很理解具体怎么处理的,又看了下表结构和源码,也记录一下重要的部分。
下面是process.go中handleEvent函数的片段,这是判断是否要生成告警事件的必要判断步骤之一,用到了执行频率(PromEvalInterval)和持续时长(PromForDuration)两个配置,这里可以看到生成告警事件需要满足上面连续告警的要求,不是通过判断n次满足发送告警,再重置计数器达到n再发送的方式。
...
var preTriggerTime int64//首次触发事件
preEvent, has := p.pendings.Get(event.Hash)//活跃告警map(AlertCurEventMap)中查到上次事件记录,其中hash是‘规则id+异常点标签+数据源id+异常等级’ 的md5值,process.go Hash
if has {
p.pendings.UpdateLastEvalTime(event.Hash, event.LastEvalTime)//更新活跃告警map的‘最近一次计算时间’为这次事件的计算时间
preTriggerTime = preEvent.TriggerTime//设置首次触发时间为活跃告警map对象中事件的首次触发时间
} else {
p.pendings.Set(event.Hash, event)
preTriggerTime = event.TriggerTime//设置首次触发时间为本次事件的触发时间
}
//***当前触发异常点的时间(同上次触发时间) - 首次异常点触发时间 + 执行频率 >= 持续时长 ***
if event.LastEvalTime-preTriggerTime+int64(event.PromEvalInterval) >= int64(p.rule.PromForDuration) {
fireEvents = append(fireEvents, event)
if severity > event.Severity {
severity = event.Severity
}
continue
}
....
其次在看下fireEvent函数,经过上面函数判断后,这里用到重复通知间隔的配置(NotifyRepeatStep),告警事件是否继续发送的判断是这样:本次触发时间〉上次发送告警时间+通知间隔 ,所以我总结下来应该是符合这样的规律
间隔(分钟) | 频率(分钟) | 触发(分钟) |
---|---|---|
2 | 0.5 | 2.5 |
2 | 1 | 3 |
2 | 2 | 4 |
2 | 3 | 3 |
...
if cachedRule.NotifyRepeatStep == 0 {
logger.Debugf("rule_eval:%s event:%+v repeat is zero nothing to do", p.Key(), event)
// 说明不想重复通知,那就直接返回了,nothing to do
// do not need to send alert again
return
}
// 之前发送过告警了,这次是否要继续发送,要看是否过了通道静默时间
if event.LastEvalTime > fired.LastSentTime+int64(cachedRule.NotifyRepeatStep)*60 {
if cachedRule.NotifyMaxNumber == 0 {
...