Prometheus 之禅是一组适合初学者的核心价值观和指导方针,用于指导应用程序的监控埋点和使用 Prometheus 编写规范的告警。这是一份旨在由 Prometheus 社区维护的文档。欢迎参与贡献。
先埋点,后提问
在开发过程中,你永远不知道以后需要问什么问题。软件需要良好的埋点,这不是可选的。没有标签的指标开销很小。大方地使用它们,但在添加标签时要注意基数。
第一条也是最重要的规则——如果你只能记住一件事,请记住这一条。对所有东西进行埋点。
衡量用户关心的事情
你的用户关心数据库服务器是否宕机吗?他们关心 CPU 饱和度吗?是的,但不是直接关心——他们关心的是自己的体验。他们关心是否能访问请求的页面,以及结果是否是最新的。从延迟和可用性的角度思考。让你的 SLO 指导你的埋点和告警。
RED、USE 和 The Four Golden Signals 是帮助你入门的知名框架。
你仍然应该衡量内部指标如数据库可用性和 CPU 饱和度——将它们用于故障排查和容量规划。
使用因果指标来回答为什么某些东西出了问题。
标签是新的层级结构
标签是新的层级结构,但更强大、更灵活。标签是 Prometheus 的强项。使用标签,你可以在事后对度量进行分组和聚合。使用标签进行切片和切块。记住先埋点,后提问,尽可能多地提供上下文。但是,你必须谨慎使用标签。请参阅下面的解释。
避免缺失指标
在某些事件发生之前不存在的时间序列很难处理。为避免这种情况,为你事先知道可能存在的任何时间序列导出 0。用零值初始化你的指标,以防止仪表盘出错和告警误触发。更详细的解释请查看 Existential issues with metrics。
记住,标签创建时间序列,因此用你预期使用的标签来初始化你的指标——你的客户端库无法知道你将使用什么标签。
基数很重要
每组唯一的标签都会创建一个新的时间序列。谨慎使用标签,注意你放入其中的内容。避免基数爆炸;无界标签会导致 Prometheus 崩溃。请记住,标签在不同维度之间是乘法关系。
Prometheus 的性能几乎总是归结于一件事:标签基数。
始终记住 Cardinality is key。
命名很难
一个指标名称在一个 job 内必须有单一含义,理想情况下在不同 job 之间也应该有相同的含义(如 process_cpu_seconds_total)。
尊重约定而非偏好。约定不是任何人的最爱,但约定是所有人的最爱。详细内容请参阅 Naming 文档。
Counter 为王,gauge 次之
暴露原始 counter,让 Prometheus 使用 rate() 和 increase() 为你计算速率。不要在目标端预计算速率——这会丢失信息。记住先埋点,后提问。
当然,gauge 也有其用武之地。在根本没有可计数事物的周期性测量中使用它们——温度、磁盘使用率、队列深度。但如果某个值只会增加,就把它做成 counter。
不要添加用于聚合的指标;PromQL 可以为你完成。
先计算速率,再聚合
注意 counter 重置。
正如 Rate then sum, never sum then rate 所述。
作为经验法则,你可以安全地直接应用于 counter 值的数学操作只有 rate、irate、increase 和 resets。其他任何操作都会导致问题。
如果你能记录日志,你就能有一个指标
日志通常对故障排查至关重要,但指标同样有价值——故障排查过程通常在不同信号之间来回跳转。不要低估指标对于理解正在发生什么的价值。
每当你记录一个事件时,考虑按大类对其进行计数。这很廉价,并且为你提供了对升高错误率的告警以及正在发生什么的概览。记住,没有标签的指标是廉价的——大方地使用计数器。
原生 histogram 几乎总是优于经典 histogram
原生 histogram 解决了经典 histogram 的桶布局问题。它们不需要预定义的边界,动态调整分辨率,并使用稀疏表示,空桶不消耗任何资源。如果你的埋点库或 OTel 支持它们,优先使用原生 histogram 进行新的埋点。
使用经典 histogram 时,创建正确的桶布局是一门艺术。为了确保观测值的有效性和告警的正确性,你必须设计一个有意义的桶布局。这与先埋点,后提问相矛盾,因为你需要在测量之前就对你的延迟有所了解。让你的 SLO 指导你的桶布局;创建与你的 SLO 匹配的边界。
经典 histogram 本质上只是带标签的 counter,其中桶边界被用作标签。在为 histogram 添加额外标签时要谨慎。记住,标签是乘法关系,并且基数很重要。
如果你能画图,你就能告警
你不能 24 小时盯着仪表盘。Prometheus 统一了指标、仪表盘和告警。PromQL 是每条 Prometheus 告警的核心,而 PromQL 查询是仪表盘上任何图表的数据源。善用它。
如果你运行它,就应该为它设置告警
始终至少对目标的存在性和健康状况设置告警。你不能依赖你无法观察或无法采取行动的东西。
避免缺失和不健康的目标。Prometheus 会自动为每个目标生成 up 指标。善用它。
告警应该是紧急的、重要的、可操作的和真实的
告警应该是紧急的、重要的、可操作的和真实的。简单明了。
不要过度告警,告警疲劳是真实存在的。
基于症状的告警用于呼叫,基于原因的告警用于排查
类似于衡量用户关心的事情,对真正重要的事情进行告警。只要用户没有察觉,CPU 饱和度并不重要。让你的 SLO 指导你的告警。
并非每条告警都需要呼叫某人。基于原因的告警不应该在半夜叫醒任何人——它们应该输出到仪表盘或工单队列中,在需要时检查或批量处理。将呼叫告警保留给表示用户可感知影响的基于症状的告警。
更多上下文请参阅 My Philosophy on Alerting。
请至少等五分钟
Prometheus 告警规则允许你指定一个 for 持续时间,决定条件必须为真多长时间才触发告警。如果不指定,单次失败的抓取就可能导致告警触发。你需要容错。作为经验法则,除非有特定理由,否则至少使用 5 分钟。更多信息请查看 Setting Thresholds on Alerts。
上下文为王
为你的告警保留常见且有用的标签。它们对路由和静默最为有用。
这个想法的灵感来自 The Zen of Go、Go Proverbs 和 The Zen of Python。
*非常感谢所有贡献了宝贵想法的人。*
初始规则收集自社区的多个来源,例如 [Björn Rabenstein](https://github.com/beorn7) 的 [Prometheus Proverbs](https://www.youtube.com/watch?v=TwH3KXKbJqM)、[Julius Volz](https://github.com/juliusv) 的 [Best Practices and Beastly Pitfalls](https://www.youtube.com/watch?v=_MNYuTNfTb4)、[Bartek Plotka](https://github.com/bwplotka) 和 [Kemal Akkoyun](https://github.com/kakkoyun) 的 [Patterns for Instrumenting Your Go Services](https://www.youtube.com/watch?v=LU6D5cNeHks)、[Simon Pasquier](https://github.com/simonpasquier) 的 [Instrumenting Applications and Alerting with Prometheus](https://www.youtube.com/watch?v=sHKWD8XnmmY) 以及 [Brian Brazil](https://github.com/brian-brazil) 的 [Robust Perception Blog](https://www.robustperception.io/blog)。
更多资源
遵循这些约定可以让你从社区工具中受益:
- Monitoring Mixins - 常见服务的可复用仪表盘和告警