告警分级与响应时间

2 min read
Zekari
系统设计监控告警事件响应

RPC调用失败。积分没有到账。Telegram立即发送告警。

日志中出现可疑的邮箱不匹配。系统15分钟后检查。

支付成功。系统记录。没有告警。

三个事件,三种响应策略。这不是随意的,而是设计的结果。

一切紧急的代价

早期的监控系统对所有事情一视同仁。一条日志,一次计数增加,如果发生足够多次,可能发个告警。

这带来一个问题:当一切都触发告警时,没有任何事情能得到适当的关注。

RPC失败需要立即干预。用户支付了但没有收到积分。这是影响金钱和信任的业务关键失败。15分钟后响应太慢了——用户可能已经联系了客服,或者更糟,要求退款。

邮箱不匹配可能是安全隐患,但它已经被拒绝了。交易没有完成。系统是安全的。15分钟后响应是可以的——你需要时间来判断这是模式(攻击)还是一次性的错误(用户输错)。

支付成功根本不需要人工关注。这是按设计工作的。记录它对分析和调试有用,但对它发告警就是噪音。

关键洞见:不同的问题需要不同的响应时间

三个级别,三种含义

告警级别不是抽象的严重程度。而是所需的响应时间

Critical:立即响应

用于延迟会直接造成损害的情况:

  • RPC调用失败(客户损失金钱)
  • 数据库连接丢失(系统无法运行)
  • 支付处理错误(收入损失)

这些会在凌晨3点叫醒人。它们应该很罕见。如果不罕见,说明系统从根本上坏了。

规则:Critical意味着必须在几分钟内采取行动

不是每个失败都需要立即响应。即使在"关键"事件中,时机的重要性也不同。

立即(< 5分钟)

  • 支付处理失败(结账时)
  • 认证系统宕机
  • 数据丢失正在进行

快速(< 30分钟)

  • 影响用户可见功能的后台任务失败
  • API速率限制超出
  • 缓存系统故障

尽快(< 2小时)

  • 批处理延迟
  • 非关键服务降级
  • 定时任务失败

区分得越细,产生的告警疲劳就越少。凌晨2点的后台任务失败如果可以等到早上8点,就不应该叫醒任何人。

Warning:监控模式

用于需要关注但不紧急的情况:

  • 安全事件(邮箱不匹配、可疑模式)
  • 速率限制接近(尚未超出)
  • 性能下降(慢但仍在工作)

这些不需要立即行动。它们需要模式分析

一个邮箱不匹配不是危机。一小时内十个可能意味着攻击。一个慢查询不是问题。所有查询都在变慢意味着负载问题。

系统每15分钟检查一次这些。这个间隔是经过深思熟虑的:

  • 足够频繁以快速捕获问题
  • 足够稀疏以将相关事件批量处理
  • 足够长以区分模式和噪音

规则:Warning意味着需要在几小时内审查

Info:仅记录

用于正常操作:

  • 支付成功
  • Webhook处理成功
  • 常规健康检查
  • 预期的验证

这些不需要人工关注。它们存在的目的是:

  • 出错时调试
  • 分析和商业智能
  • 审计轨迹
  • 成功率计算

规则:Info意味着记录以供后续分析,不告警

为什么安全检查是15分钟

选择15分钟作为安全事件检查间隔不是随机的。它平衡了多个因素。

太频繁(每分钟)

  • 每天1440次检查
  • 持续查询带来的数据库负载
  • 重复检查产生的日志噪音
  • 瞬时问题造成的虚假紧急感

太稀疏(每小时)

  • 每天24次检查
  • 对攻击的响应延迟
  • 一次性处理大批事件
  • 更难关联时间

15分钟(最优)

  • 每天96次检查
  • 在合理时间内捕获问题
  • 自然地批量处理相关事件
  • 最小的系统负载

更重要的是,15分钟符合安全分析的自然节奏。你不是在响应单个事件——你在寻找模式。一次攻击在第5分钟检测到与在第15分钟检测到并没有变得更严重。重要的是在模式成功之前捕获它。

不同问题有不同的自然频率:

实时(立即)

  • 支付处理 - 涉及金钱,用户在等待
  • 认证 - 用户无法继续,直到解决
  • 数据损坏 - 每次操作都会恶化

近实时(< 5分钟)

  • API故障 - 影响活跃用户
  • 缓存故障 - 降低用户体验
  • 服务不可用 - 立即可见

定期(15-60分钟)

  • 安全事件 - 需要模式分析
  • 资源使用 - 趋势比峰值更重要
  • 后台任务健康 - 不面向用户

批量(每天)

  • 使用分析
  • 成本优化机会
  • 趋势分析

关键是将检查频率匹配到决策节奏。如果你无论如何都无法在15分钟内对某事采取行动,那么更频繁地检查只会产生噪音。

告警疲劳与信号保存

监控系统最常见的失败模式不是错过重要告警——而是淹没在不重要的告警中。

当你每天收到50个告警,其中45个不需要采取行动时,你会停止认真对待告警。这就是告警疲劳。这是一种防御机制。大脑学会了大多数告警都是误报,并开始忽略它们。

然后当真正的危机发生时,告警到达,没有人快速响应,因为他们已经被训练成认为告警无关紧要。

这就是为什么告警级别必须映射到实际响应时间。如果某事触发了Critical告警,最好有人在几分钟内响应。如果没有发生,要么:

  1. 告警级别错了(应该是Warning或Info)
  2. 响应流程错了(需要更好的值班程序)
  3. 系统从根本上不可靠(需要架构修复)

解决方案不是更好的告警工具。而是更好的告警纪律

每个告警应该回答两个问题:

  1. 什么出错了?
  2. 我应该采取什么行动?

如果你无法回答这两个问题,就不应该告警。

相关阅读:what-monitoring-systems-see 讨论了日志级别以及监控系统应该记录什么。monitoring-observation-period 介绍了如何验证监控改进是否真正有效。

全面记录,选择性告警

记录告警之间有微妙的区别。

记录意味着写入日志,存储在指标数据库中,使数据可供分析。这应该是全面的。每个重要事件,每个决策点,每个状态转换。

告警意味着向人类发送通知。这应该是选择性的。只有需要人工行动的事件。

Telegram告警系统展示了这一点:

记录但不告警

  • 每个接收到的webhook
  • 每次签名验证
  • 每次RPC调用持续时间
  • 每次支付成功

Warning级别告警

  • 邮箱不匹配(需要模式分析)
  • 速率限制接近(预防性行动)
  • 订阅取消(商业智能)

Critical级别告警

  • RPC失败(涉及金钱)
  • 系统配置错误(阻塞操作)
  • 认证失败(安全漏洞)

这种分离意味着你有完整的数据用于调试,而告警频道中没有噪音。调查问题时,你可以重建发生的一切。但在日常工作中,你只听到需要采取行动的事情。

支付webhook到达。系统记录七个事件:

  1. webhook_received - 入口确认(Info级别)
  2. signature_verified - 安全检查通过(Info级别)
  3. plan_retrieved - 配置加载(Info级别)
  4. rpc_call_initiated - 积分添加开始(Info级别)
  5. rpc_execution_completed - 积分已添加(Info级别)
  6. queue_message_sent - 后续操作已排队(Info级别)
  7. webhook_success - 端到端完成(Info级别)

如果步骤5失败,系统记录rpc_execution_failed并发送Critical告警

如果步骤2失败,系统记录signature_verification_failed并发送Warning(在15分钟安全检查中批量处理)。

所有七个步骤都会被记录。但只有失败才触发告警,且告警级别与所需响应时间匹配。

时间指标优于布尔标志

Telegram告警系统的另一个关键洞见:记录时间,而不仅仅是成功/失败

传统监控跟踪二元状态:

  • 成功了吗?是/否
  • 多少次?计数
  • 多久一次?频率

这忽略了一个关键维度:性能下降

一个系统可以有99%的成功率,同时正在死亡。如果每个请求需要10秒而不是100毫秒,用户正在离开。但成功率看起来很好。

这就是为什么每个记录的事件都应该包含持续时间指标:

  • duration_ms - 这一步花了多长时间
  • rpc_duration_ms - 外部调用花了多长时间
  • total_duration_ms - 整个流程花了多长时间

这些指标揭示了成功率隐藏的问题:

  • 渐进性能下降(查询越来越慢)
  • 瓶颈识别(哪一步慢)
  • 超时风险预测(接近超时阈值)

时间序列数据将监控从被动变为预测性。你在问题成为故障之前就看到它们正在形成。

为正确的响应而设计

告警设计的根本问题不是"什么出错了?"——而是"接下来应该发生什么?"

RPC失败应该触发立即调查和可能的回滚。这就是为什么它是Critical。

安全事件应该在工作时间作为模式分析的一部分进行审查。这就是为什么它是Warning并每15分钟检查一次。

支付成功应该记录用于分析,但不需要人工关注。这就是为什么它是Info并且从不告警。

每个告警级别意味着一个响应时间。每个响应时间意味着组织承诺。如果你无法承诺对Critical告警在5分钟内响应,就不要使用Critical告警。

这不是关于技术。而是关于将系统设计与运营现实对齐

你的监控系统应该反映你实际做的事情,而不是你希望做的事情。如果没有人在凌晨3点响应告警,就不要在凌晨3点发送Critical告警。要么修复你的值班流程,要么降低告警级别。

最好的监控系统是这样的:

  • Critical告警很罕见,总是被处理
  • Warning告警定期审查并推动改进
  • Info日志全面且对调试有用
  • 没有人经历告警疲劳
  • 真正的问题得到适当的响应

这不是通过更好的工具实现的。而是通过更好的告警纪律实现的。

系统告诉我们的

Telegram告警部署揭示了一些重要的事情:我们认为需要告警的大部分事情实际上不需要。

Webhook流程中的七个事件。只有两个条件触发告警:

  • RPC失败(Critical)
  • 安全事件(Warning,批量处理)

其他一切都被记录但保持沉默。这是设计使然。

系统每天处理数百个webhook。如果每个都生成告警,频道将无法使用。通过只对需要响应的条件告警,信噪比保持高水平。

当告警到达时,它意味着某事。人们响应。问题得到修复。

这就是良好监控的样子:全面记录,选择性告警,以及与实际紧急程度匹配的响应时间

Related Posts

Articles you might also find interesting

监控观察期法

3 min read

部署不是结束,而是验证的开始。修复代码只是假设,监控数据才是证明。48小时观察期:让错误主动暴露,让数据证明修复。

系统设计监控
Read More

管理后台需要两次设计

3 min read

第一次设计回答"发生了什么",第二次设计回答"我能做什么"。在第一次就试图解决所有问题,结果是功能很多但都不够深入。

系统设计API 设计
Read More

文档标准是成本计算的前提

3 min read

API文档不只是写给开发者看的。它定义了系统的边界、成本结构和可维护性。统一的文档标准让隐性成本变得可见。

API文档
Read More

BullMQ 队列

3 min read

队列不是技术选型,而是对时间的承认,对顺序的尊重,对不确定性的应对

系统设计异步处理
Read More

BullMQ Worker

2 min read

Worker 的本质是对时间的重新分配,是对主线的解放,也是对专注的追求

系统设计异步处理
Read More

配置不会自动同步

2 min read

视频生成任务永远pending,代码完美部署,队列正确配置。问题不在代码,在于配置的独立性被低估。静默失败比错误更危险。

部署配置管理
Read More

CRUD 操作

2 min read

四个字母背后,是数据的生命周期,是权限的边界,也是系统设计的基础逻辑

系统设计软件工程
Read More

数据库参数国际化:从 13 个迁移学到的设计原则

3 min read

数据不该懂语言。当数据库参数嵌入中文标签时,系统的边界就被语言限制了。这篇文章从 13 个参数对齐迁移中提炼出设计原则——国际化不是功能,是系统设计的底层约束。

数据库国际化
Read More

Stripe Webhook中的防御性编程

2 min read

三个Bug揭示的真相:假设是代码中最危险的东西。API返回类型、环境配置、变量作用域——每个看似合理的假设都可能导致客户损失。

Web开发系统设计
Read More

双重验证:Stripe生产模式的防御性切换

7 min read

从测试到生产不是更换API keys,而是建立一套双重验证系统。每一步都在两个环境中验证,确保真实支付不会因假设而失败。

系统设计Stripe
Read More

错误隔离

3 min read

失败是必然的。真正的问题不是失败本身,而是失败如何蔓延。错误隔离不是为了消除失败,而是为了控制失败的范围。

系统设计可靠性工程
Read More

在运行的系统上生长新功能

3 min read

扩展不是推倒重来,而是理解边界,找到生长点。管理层作为观察者和调节器,附着在核心系统上,监测它,影响它,但不改变它的运行逻辑。

系统设计架构
Read More

实现幂等性处理,忽略已处理的任务

3 min read

在代码层面识别和忽略已处理的任务,不是简单的布尔检查,而是对时序、并发和状态的深刻理解

系统设计并发控制
Read More

单例模式管理 Redis 连接

5 min read

连接不是技术细节,而是系统与外部世界的第一次握手,是可靠性的起点

系统设计后端架构
Read More

缺失值的级联效应

3 min read

一个NULL值如何在调用链中传播,最终导致错误的错误消息。理解防御层的设计,在失败传播前拦截。

系统设计防御性编程
Read More

Props Drilling

3 min read

数据在组件树中层层传递,每一层都不需要它,却必须经手。这不是技术债,是架构对真实需求的误解。

React组件设计
Read More

队列生产者实例的工厂函数

4 min read

工厂函数不是设计模式的炫技,而是对重复的拒绝,对集中管理的追求,对变化的准备

系统设计设计模式
Read More

监听 Redis 连接事件 - 让不可见的脆弱变得可见

4 min read

连接看起来应该是透明的。但当它断开时,你才意识到透明不等于可靠。监听不是多余,而是对脆弱性的承认。

系统设计Redis
Read More

资源不会消失,只会泄露

2 min read

在积分系统中,用户的钱不会凭空消失,但会因为两个时间窗口而泄露:并发请求之间的竞争,和回调永不到达的沉默。

系统设计并发控制
Read More

RPC函数的原子化处理

1 min read

当一个远程函数做太多事情,失败就变得难以理解

分布式系统RPC
Read More

RPC函数

2 min read

关于远程过程调用的本质思考:当你试图让远方看起来像眼前

分布式系统RPC
Read More

使用Secret Token验证回调请求的合法性

2 min read

在开放的网络中,信任不能被假设。Secret Token 是对身份的确认,对伪装的识别,也是对安全边界的坚守

Web 安全系统设计
Read More

第三方回调的状态映射完整性

5 min read

KIE.AI 视频生成的三个修复揭示了一个本质问题:回调不只是接收结果,是建立状态映射。没有 vendor_task_id,系统就失去了追溯能力。

Purikura 项目系统设计
Read More

What Monitoring Systems See

7 min read

Production logs showed errors everywhere. But most weren't errors at all. When test webhooks generate error-level logs, and successful validations leak customer emails, the monitoring system loses its ability to tell you what's actually wrong.

日志监控
Read More

指数退避超时 - 防止无限重试循环

3 min read

失败后立即重试是本能。但有些失败,需要时间来消化。指数退避不是逃避失败,而是尊重失败。

系统设计可靠性工程
Read More