4. 异常事件采集与标准化

异常工单能否自动流转,第一步并不在“流转”,而在“采集与标准化”。监控系统、日志平台、APM、数据库告警、业务埋点、人工上报等来源产生的异常事件,字段命名、时间精度、严重级别、对象标识各不相同。如果直接把这些原始事件送进工单引擎,后续的去重、关联、派单和升级都会失去可靠依据。本节围绕一条完整的事件处理链展开:多源接入 → 格式归一化 → 去重 → 关联 → 富化,并给出可落地的字段设计与判断规则。

一、多源事件接入:先统一“入口契约”

接入层要解决的不是“能不能收到”,而是“收到后能否被稳定解析”。常见来源可分为三类:推送型(Webhook、Syslog、Kafka 消息)、拉取型(定时调用告警 API、轮询数据库告警表)、人工型(工单页面、IM 机器人指令)。无论哪类,接入层都应先落一份原始事件(Raw Event),保留原始报文与来源标识,再进入解析流程。这样做的价值在于:解析规则升级后可以回放历史原始事件,而不必要求上游重发。

接入层建议统一以下入口字段:source_system(来源系统)、source_event_id(来源侧事件 ID)、received_at(接入时间,UTC 毫秒)、raw_payload(原始报文)、ingest_channel(push/pull/manual)。其中 source_event_id 是后续去重的重要依据,若来源系统不提供,则需在接入层生成稳定指纹。

二、格式归一化:把异构字段映射到统一事件模型

归一化的目标是把不同来源的字段映射为统一事件模型(Canonical Event)。一个够用的最小模型包含:事件标识、时间、来源、对象、级别、指标、描述、标签。关键映射关系如下:

统一字段含义示例映射
event_id平台内唯一事件 ID由 source_system + source_event_id 生成
occur_time事件发生时间(UTC 毫秒)Zabbix clock、Prometheus startsAt、日志 @timestamp
severity归一化级别P1/P2/P3/P4,由来源级别映射
entity异常对象host、service、db_instance、biz_order
metric异常指标或错误类型cpu_usage、http_5xx_rate、slow_sql
labels维度标签env、region、cluster、version

级别映射必须显式定义,不能依赖字符串包含判断。例如来源 A 的 critical 映射为 P1,来源 B 的 fatal 映射为 P1,来源 C 的 warning 映射为 P3。时间统一为 UTC 毫秒,避免跨时区比较时出现顺序错乱。对象标识要统一命名规范,例如主机统一为 host:<hostname>,服务统一为 service:<app>.<env>,否则后续关联无法命中。

归一化规则建议以配置表形式维护,而不是写死在代码里。每条规则包含:来源系统、原始字段路径、目标字段、转换函数、默认值。规则变更后可灰度生效并回放验证。

三、去重:识别“同一异常的重复表达”

去重不是简单按标题去重,而要区分三种情况:完全重复(同一来源同一事件 ID 重发)、近邻重复(同一对象同一指标在短时间窗口内反复触发)、语义重复(不同来源描述同一故障)。前两种可用确定性规则处理,第三种需要关联阶段配合。

推荐去重键:entity + metric + severity + time_bucket。其中 time_bucket 按分钟取整,例如 floor(occur_time / 60000)。若同一去重键在窗口内再次出现,则合并为一条事件,累加 repeat_count,更新 last_seen,并保留首次 first_seen。这样既能抑制风暴,又能保留“持续发生”的证据。

去重键示例:
dedup_key = entity + "|" + metric + "|" + severity + "|" + floor(occur_time/60000)

合并规则:
if dedup_key 已存在:
    repeat_count += 1
    last_seen = max(last_seen, occur_time)
    severity = max(severity, new_severity)   # 级别取高
else:
    新建事件,first_seen = last_seen = occur_time,repeat_count = 1

四、关联:把分散事件聚合成“一个故障”

关联的目标是回答“这些事件是不是同一件事”。常用关联维度有三类:时间邻近(窗口内)、拓扑邻近(同一主机、同一集群、上下游调用关系)、因果邻近(数据库慢查询导致应用 5xx 上升)。工程上可先做规则关联,再逐步引入图关联。

一个可执行的关联规则示例:若 service:order-api.prod 出现 http_5xx_rate 异常,且其依赖的 db_instance:order-db 在前后 2 分钟内出现 slow_sql 异常,则将两条事件归入同一事件组,并以数据库事件作为疑似根因,应用事件作为影响面。关联结果写入 group_id,后续工单以组为单位创建,避免同一故障开出多张工单。

五、富化:补齐决策所需上下文

富化是在事件进入工单引擎前,补充派单、定级和通知所需的字段。常见富化项包括:CMDB 归属(业务线、负责人、值班组)、历史工单(近 7 天同类事件次数)、变更记录(近 1 小时是否有发布)、影响面(关联服务数、受影响订单量)。富化数据应标注来源与获取时间,避免使用过期缓存导致误判。

例如,一条 service:order-api.prod 的 P2 事件,富化后得到:归属业务线“交易”、值班组“订单SRE”、近 1 小时存在发布记录、近 7 天同类事件 3 次。这些字段直接决定工单是自动派给订单SRE,还是因“发布关联”而升级为 P1 并通知变更负责人。

多源异常事件采集与标准化处理链 多源接入 监控 / 日志 / APM 数据库 / 业务埋点 人工上报 push / pull / manual 原始事件 raw_payload source_system source_event_id received_at (UTC ms) 格式归一化 统一事件模型 severity 映射 entity 命名规范 occur_time 统一 UTC 去重 dedup_key time_bucket repeat_count first_seen / last_seen 关联 时间邻近 拓扑邻近 因果邻近 group_id 富化:补齐派单与定级上下文 CMDB 归属(业务线 / 负责人 / 值班组) · 历史工单(近 7 天同类次数) 变更记录(近 1 小时发布) · 影响面(关联服务数 / 受影响订单量) 标注数据来源与获取时间,避免过期缓存误判 标准化事件 → 工单引擎 event_id · group_id · severity · entity · metric · labels · 富化字段 关键判断依据 去重键是否命中 关联窗口是否重叠 富化字段是否完整

六、处理结果如何判断

一条事件经过上述链路后,应满足以下可检查条件:event_id 唯一且可回溯到原始报文;occur_time 为 UTC 毫秒且与来源时间偏差在允许范围内;severity 落在 P1–P4 且映射规则可查;同一 dedup_key 在窗口内只保留一条主事件且 repeat_count 正确累加;同一故障的多条事件共享 group_id;富化字段非空且带有来源时间戳。若这些条件不满足,工单引擎的自动派单和升级就会退化为人工判断。

常见误区:把去重做成“按标题字符串去重”,会把不同主机的同类告警错误合并;把关联窗口设得过大,会把无关事件聚成一组;富化使用过期 CMDB 缓存,会把工单派给已离任负责人。建议对去重键、关联窗口、富化缓存 TTL 分别设置可观测指标并定期回放验证。

完成采集与标准化后,事件才具备进入工单引擎的资格。下一阶段将围绕工单生成、派单与状态流转展开,而本节产出的 event_id、group_id、severity、entity 和富化字段,正是后续所有自动决策的输入基础。