Alertmanager-silencer告警静默

基于v0.28

总体流程

sequenceDiagram
participant Alert as 告警(Labels)
participant Silencer as Silencer
participant Silences as Silences
participant Store as state(存储)
participant Marker as AlertMarker

Alert->>Silencer: 新告警流入,调用 Mutes(lset)
Silencer->>Marker: 查询该告警指纹的静默状态
alt Marker 版本与 Silences 一致
Silencer->>Silences: 仅查询已知静默ID是否仍然有效
else Marker 版本不一致
Silencer->>Silences: 全量查询所有匹配该告警的静默
end
Silences->>Store: 检索活跃/待生效静默
Store-->>Silences: 返回静默列表
Silences-->>Silencer: 返回匹配静默
Silencer->>Marker: 更新告警的静默状态
alt 存在活跃静默
Silencer-->>Alert: 返回 true(被静默)
else 无活跃静默
Silencer-->>Alert: 返回 false(未被静默)
end

Note over Silencer,Silences: <b>核心流程说明:</b><br/>1. 新告警到达,Silencer 查询静默状态<br/>2. 若有活跃静默,告警被静默,不再通知<br/>3. 若无活跃静默,告警正常进入后续流程

运行原理

初始化

silencer := silence.NewSilencer(silences, marker, logger)

// Silences 结构体负责静默的存储、查询、GC、快照、分布式同步等。
type Silences struct {
clock quartz.Clock // 时钟接口,便于测试

logger *slog.Logger // 日志
metrics *metrics // 监控指标
retention time.Duration // 过期静默的保留时长
limits Limits // 静默数量和大小限制

mtx sync.RWMutex // 并发控制
st state // 静默状态存储(map)
version int // 状态版本号,每次变更递增
broadcast func([]byte) // 分布式同步广播函数
mc matcherCache // 匹配器缓存
}

// NewSilencer 创建一个新的 Silencer 实例。
// s: 静默存储对象
// m: 告警标记器
// l: 日志对象
// 返回值: 新的 Silencer 实例
func NewSilencer(s *Silences, m types.AlertMarker, l *slog.Logger) *Silencer {
return &Silencer{
silences: s,
marker: m,
logger: l,
}
}

更新API配置

// 更新API配置
api.Update(conf, func(labels model.LabelSet) {
inhibitor.Mutes(labels)
silencer.Mutes(labels)
})

告警静默

核心静默

// Silencer 结构体将 Silences 与 AlertMarker 绑定,实现 Muter 接口,
// 用于判断某个告警是否被静默。
type Silencer struct {
silences *Silences // 静默存储对象
marker types.AlertMarker // 告警标记器
logger *slog.Logger // 日志
}

// Mutes 判断给定标签集合(lset)是否被当前静默规则静默。
// lset: 需要判断的标签集合(告警)
// 返回值: true 表示被静默,false 表示未被静默
func (s *Silencer) Mutes(lset model.LabelSet) bool {
fp := lset.Fingerprint()
activeIDs, pendingIDs, markerVersion, _ := s.marker.Silenced(fp)

var (
err error
allSils []*pb.Silence
newVersion = markerVersion
)
if markerVersion == s.silences.Version() {
totalSilences := len(activeIDs) + len(pendingIDs)
// 无静默直接返回
if totalSilences == 0 {
return false
}
// 仅需检查已有静默是否仍然有效
allIDs := append(append(make([]string, 0, totalSilences), activeIDs...), pendingIDs...)
allSils, _, err = s.silences.Query(
QIDs(allIDs...),
QState(types.SilenceStateActive, types.SilenceStatePending),
)
} else {
// 有新静默,需全量查询
allSils, newVersion, err = s.silences.Query(
QState(types.SilenceStateActive, types.SilenceStatePending),
QMatches(lset),
)
}
if err != nil {
s.logger.Error("Querying silences failed, alerts might not get silenced correctly", "err", err)
}
if len(allSils) == 0 {
// 没有任何静默,重置标记
s.marker.SetActiveOrSilenced(fp, newVersion, nil, nil)
return false
}
// 重新计算当前活跃和待生效的静默 ID
activeIDs, pendingIDs = nil, nil
now := s.silences.nowUTC()
for _, sil := range allSils {
switch getState(sil, now) {
case types.SilenceStatePending:
pendingIDs = append(pendingIDs, sil.Id)
case types.SilenceStateActive:
activeIDs = append(activeIDs, sil.Id)
default:
// 已过期静默无需处理
}
}
s.logger.Debug(
"determined current silences state",
"now", now,
"total", len(allSils),
"active", len(activeIDs),
"pending", len(pendingIDs),
)
sort.Strings(activeIDs)
sort.Strings(pendingIDs)

s.marker.SetActiveOrSilenced(fp, newVersion, activeIDs, pendingIDs)

return len(activeIDs) > 0
}


// MemMarker 是 AlertMarker 的内存实现。
type MemMarker struct {
alerts map[model.Fingerprint]*AlertStatus // 告警状态存储
groups map[string]*groupStatus // 分组状态存储

mtx sync.RWMutex // 并发控制
}

// Silenced 返回告警是否被静默、相关静默 ID、版本号等。
func (m *MemMarker) Silenced(alert model.Fingerprint) (activeIDs, pendingIDs []string, version int, silenced bool) {
s := m.Status(alert)
return s.SilencedBy, s.pendingSilences, s.silencesVersion,
s.State == AlertStateSuppressed && len(s.SilencedBy) > 0
}

内存告警管理实现

// AlertMarker 用于标记告警的静默/抑制状态,所有方法均为并发安全。
type AlertMarker interface {
// SetActiveOrSilenced 设置告警的静默状态,activeSilenceIDs/pendingSilenceIDs 为影响该告警的静默 ID。
// version: 静默状态版本号
SetActiveOrSilenced(alert model.Fingerprint, version int, activeSilenceIDs, pendingSilenceIDs []string)
// SetInhibited 设置告警的抑制状态,alertIDs 为抑制该告警的其他告警 ID。
SetInhibited(alert model.Fingerprint, alertIDs ...string)

// Count 统计指定状态的告警数量。
Count(...AlertState) int

// Status 获取指定告警的状态。
Status(model.Fingerprint) AlertStatus
// Delete 删除指定告警的状态。
Delete(model.Fingerprint)

// Unprocessed/Active/Silenced/Inhibited 判断告警是否处于对应状态。
// Silenced 返回影响该告警的静默 ID、版本号等。
Unprocessed(model.Fingerprint) bool
Active(model.Fingerprint) bool
Silenced(model.Fingerprint) (activeIDs, pendingIDs []string, version int, silenced bool)
Inhibited(model.Fingerprint) ([]string, bool)
}

// GroupMarker 用于标记分组的静默状态,所有方法均为并发安全。
// routeID: 路由唯一标识,groupKey: 分组唯一标识
type GroupMarker interface {
// Muted 判断分组是否被静默,返回静默时间区间名列表和是否被静默。
Muted(routeID, groupKey string) ([]string, bool)
// SetMuted 标记分组被哪些时间区间静默。
SetMuted(routeID, groupKey string, timeIntervalNames []string)
// DeleteByGroupKey 删除指定分组的所有标记。
DeleteByGroupKey(routeID, groupKey string)
}

// NewMarker 创建一个 AlertMarker 实现。
func NewMarker(r prometheus.Registerer) *MemMarker {
m := &MemMarker{
alerts: map[model.Fingerprint]*AlertStatus{},
groups: map[string]*groupStatus{},
}
m.registerMetrics(r)
return m
}

// MemMarker 是 AlertMarker 的内存实现。
type MemMarker struct {
alerts map[model.Fingerprint]*AlertStatus // 告警状态存储
groups map[string]*groupStatus // 分组状态存储

mtx sync.RWMutex // 并发控制
}

// Muted 实现 GroupMarker,判断分组是否被静默。
func (m *MemMarker) Muted(routeID, groupKey string) ([]string, bool) {
m.mtx.Lock()
defer m.mtx.Unlock()
status, ok := m.groups[routeID+groupKey]
if !ok {
return nil, false
}
return status.mutedBy, len(status.mutedBy) > 0
}

// SetMuted 实现 GroupMarker,设置分组被哪些时间区间静默。
func (m *MemMarker) SetMuted(routeID, groupKey string, timeIntervalNames []string) {
m.mtx.Lock()
defer m.mtx.Unlock()
status, ok := m.groups[routeID+groupKey]
if !ok {
status = &groupStatus{}
m.groups[routeID+groupKey] = status
}
status.mutedBy = timeIntervalNames
}

// DeleteByGroupKey 删除指定分组的所有标记。
func (m *MemMarker) DeleteByGroupKey(routeID, groupKey string) {
m.mtx.Lock()
defer m.mtx.Unlock()
delete(m.groups, routeID+groupKey)
}

// registerMetrics 注册告警状态相关的监控指标。
func (m *MemMarker) registerMetrics(r prometheus.Registerer) {
newMarkedAlertMetricByState := func(st AlertState) prometheus.GaugeFunc {
return prometheus.NewGaugeFunc(
prometheus.GaugeOpts{
Name: "alertmanager_marked_alerts",
Help: "How many alerts by state are currently marked in the Alertmanager regardless of their expiry.",
ConstLabels: prometheus.Labels{"state": string(st)},
},
func() float64 {
return float64(m.Count(st))
},
)
}

alertsActive := newMarkedAlertMetricByState(AlertStateActive)
alertsSuppressed := newMarkedAlertMetricByState(AlertStateSuppressed)
alertStateUnprocessed := newMarkedAlertMetricByState(AlertStateUnprocessed)

r.MustRegister(alertsActive)
r.MustRegister(alertsSuppressed)
r.MustRegister(alertStateUnprocessed)
}

// Count 实现 AlertMarker,统计指定状态的告警数量。
func (m *MemMarker) Count(states ...AlertState) int {
m.mtx.RLock()
defer m.mtx.RUnlock()

if len(states) == 0 {
return len(m.alerts)
}

var count int
for _, status := range m.alerts {
for _, state := range states {
if status.State == state {
count++
}
}
}
return count
}

// SetActiveOrSilenced 实现 AlertMarker,设置告警的静默状态。
func (m *MemMarker) SetActiveOrSilenced(alert model.Fingerprint, version int, activeIDs, pendingIDs []string) {
m.mtx.Lock()
defer m.mtx.Unlock()

s, found := m.alerts[alert]
if !found {
s = &AlertStatus{}
m.alerts[alert] = s
}
s.SilencedBy = activeIDs
s.pendingSilences = pendingIDs
s.silencesVersion = version

// 若无静默/抑制,则为 active,否则为 suppressed
if len(activeIDs) == 0 && len(s.InhibitedBy) == 0 {
s.State = AlertStateActive
return
}

s.State = AlertStateSuppressed
}

// SetInhibited 实现 AlertMarker,设置告警的抑制状态。
func (m *MemMarker) SetInhibited(alert model.Fingerprint, ids ...string) {
m.mtx.Lock()
defer m.mtx.Unlock()

s, found := m.alerts[alert]
if !found {
s = &AlertStatus{}
m.alerts[alert] = s
}
s.InhibitedBy = ids

// 若无静默/抑制,则为 active,否则为 suppressed
if len(ids) == 0 && len(s.SilencedBy) == 0 {
s.State = AlertStateActive
return
}

s.State = AlertStateSuppressed
}

// Status 实现 AlertMarker,获取指定告警的状态。
func (m *MemMarker) Status(alert model.Fingerprint) AlertStatus {
m.mtx.RLock()
defer m.mtx.RUnlock()

if s, found := m.alerts[alert]; found {
return *s
}
return AlertStatus{
State: AlertStateUnprocessed,
SilencedBy: []string{},
InhibitedBy: []string{},
}
}

// Delete 实现 AlertMarker,删除指定告警的状态。
func (m *MemMarker) Delete(alert model.Fingerprint) {
m.mtx.Lock()
defer m.mtx.Unlock()

delete(m.alerts, alert)
}

// Unprocessed 实现 AlertMarker,判断告警是否为未处理状态。
func (m *MemMarker) Unprocessed(alert model.Fingerprint) bool {
return m.Status(alert).State == AlertStateUnprocessed
}

// Active 实现 AlertMarker,判断告警是否为活跃状态。
func (m *MemMarker) Active(alert model.Fingerprint) bool {
return m.Status(alert).State == AlertStateActive
}

// Inhibited 实现 AlertMarker,判断告警是否被抑制。
func (m *MemMarker) Inhibited(alert model.Fingerprint) ([]string, bool) {
s := m.Status(alert)
return s.InhibitedBy,
s.State == AlertStateSuppressed && len(s.InhibitedBy) > 0
}

// Silenced 返回告警是否被静默、相关静默 ID、版本号等。
func (m *MemMarker) Silenced(alert model.Fingerprint) (activeIDs, pendingIDs []string, version int, silenced bool) {
s := m.Status(alert)
return s.SilencedBy, s.pendingSilences, s.silencesVersion,
s.State == AlertStateSuppressed && len(s.SilencedBy) > 0
}