Prometheus 之禅
Prometheus 之禅是一套对初学者友好的核心价值与指南,旨在帮助你对应用程序进行埋点以及编写符合习惯的 Prometheus 告警。这是一份旨在由 Prometheus 社区维护的文档。欢迎 贡献内容 。
先埋点,后思考
在开发过程中,你永远无法预知后续需要询问哪些问题。软件需要良好的监控埋点,这不是可选项。没有标签的指标成本很低。请慷慨地使用它们,但在添加标签时要注意基数 (cardinality)。
这是第一条也是最重要的一条规则——如果你只能记住一件事,那就记住这一条。把所有东西都埋点监控起来。
衡量用户所关心的内容
你的用户关心数据库服务器是否宕机吗?他们关心 CPU 饱和度吗?是的,但不是直接关心——他们关心的是自己的体验。他们关心的是能否访问请求的页面,以及结果是否即时。以延迟和可用性的角度来思考。让你的 SLO (服务等级目标) 指导你的监控埋点和告警。
RED 方法 、USE 方法 和 四个黄金信号 是帮助你入门的著名框架。
你仍然应该衡量内部指标(如数据库可用性和 CPU 饱和度)——将它们用于故障排除和容量规划。
Use causal metrics to answer why something is broken.
标签是新的层级结构
标签是新的层级结构,但它更强大且灵活。标签是 Prometheus 的力量源泉。通过标签,可以在后续对指标进行分组和聚合。使用标签进行各种维度的切分。请记住“先埋点,后思考”,尽可能提供更多的上下文信息。然而,你必须谨慎使用标签。详见下文解释。
避免丢失指标
在发生某些情况之前不存在的时间序列很难处理。为避免这种情况,请为你预知可能存在的所有时间序列导出 0 值。使用零值初始化指标,以防止仪表盘损坏和错误触发告警。有关更详细的解释,请查阅 指标的生存问题 。
请记住,标签会创建时间序列,因此请使用你期望的标签来初始化你的指标——你的客户端库无法预知你将拥有哪些标签。
基数很重要
每一组唯一的标签都会创建一个新的时间序列。请谨慎使用标签,并注意放入其中的内容。避免基数爆炸;无限增长的标签会撑爆 Prometheus。请记住,标签在多个维度上是乘法关系。
Prometheus performance almost always comes down to one thing: label cardinality.
时刻牢记基数是关键 。
命名很难
指标名称在同一个作业 (job) 内必须具有单一含义,理想情况下在不同作业间也应具有相同的含义(例如 process_cpu_seconds_total)。
尊重约定胜于个人偏好。没人喜欢条条框框的约定,但约定又是每个人都需要的。关于命名细节,请参阅命名规范文档。
计数器 (Counter) 是王道,仪表盘 (Gauge) 弱爆了
暴露原始计数器,让 Prometheus 使用 rate() 和 increase() 为你计算速率。不要在目标端预先计算速率——那会丢弃信息。请记住“先埋点,后思考”。
当然,仪表盘指标也有其用武之地。将它们用于无法计数(如温度、磁盘占用率、队列深度)的定期测量。但如果某样东西只会增加,请将其设为计数器。
不要为聚合添加指标;PromQL 可以帮你完成。
先求速率,再进行聚合
注意计数器重置 。正如 先求速率再求和,绝不要先求和再求速率 中所言。经验法则是,你可以直接安全应用于计数器值的数学运算只有 rate、irate、increase 和 resets。其他操作都会导致问题。
如果你能记录日志,你就能为它添加指标
日志对于故障排除通常至关重要,但指标也同样有价值——故障排除过程通常是在不同信号之间来回切换的。不要低估指标对于理解系统运行状况的价值。
每当你记录一个事件时,考虑按大类进行计数。这不仅成本低廉,还能让你在错误率升高时发出告警,并全面了解正在发生的事情。记住,没有标签的指标成本很低——慷慨地添加计数器。
原生直方图几乎总是优于传统直方图
原生直方图解决了传统直方图的桶布局问题。它们无需预定义边界,能动态调整分辨率,并使用稀疏表示,空桶不占用空间。如果你的埋点库或 OTel 支持它们,请在进行新的埋点时优先选择原生直方图。
对于传统直方图,创建一个正确的桶布局是一门艺术。为了确保观测的有用性和告警的正确性,你需要想出一个有意义的桶布局。这与“先埋点,后思考”相冲突,因为你需要在大致了解延迟后才能进行测量。让你的 SLO 指导你的桶布局;创建与 SLO 相匹配的边界。
传统直方图本质上只是带有标签的计数器,其中桶边界被用作标签。在为直方图添加额外标签时要小心。记住,标签是乘法关系,且基数很重要。
如果你能绘制图形,你就可以针对它设置告警
你不可能 24/7 盯着仪表盘。Prometheus 统一了指标、仪表盘和告警。PromQL 是每个 Prometheus 告警的核心,PromQL 查询也是仪表盘上任何图形的来源。好好利用它。
如果你运行了它,就应该为它设置告警
至少要为目标的可用性和健康状态设置告警。你不能依赖那些你无法观察或无法采取行动的事物。
避免缺失和不健康的目标。Prometheus 会自动为每个目标生成 up 指标。用好它。
告警应该是紧急的、重要的、可操作的和真实的
告警应该是紧急的、重要的、可操作的和真实的 。道理就这么简单。
并且不要过度告警,“告警疲劳”是真实存在的。
基于症状的告警用于分页呼叫,基于原因的告警用于故障排除
类似于“衡量用户所关心的内容”,针对真正重要的事情发出告警。只要你的用户没有感知到,CPU 饱和与否并不重要。让你的 SLO 指导你的告警。
并非每个告警都需要发送页面提醒。基于原因的告警不应打扰任何人——它们应该进入仪表盘或工单队列,以便在需要时检查,或者在空闲时批量处理。保留分页提醒给那些显示有用户侧影响的、基于症状的告警。
更多背景信息请参考 我的告警哲学 (My Philosophy on Alerting) 。
请再多给我五分钟
Prometheus 告警规则允许你指定一个 for 持续时间,用于决定告警触发前条件必须持续多久。如果你不指定它,单次抓取失败就可能导致告警触发。你需要一定的容错度。经验法则是,除非有特定理由,否则至少使用 5 分钟。更多信息,请查阅 设置告警阈值 (Setting Thresholds on Alerts) 。
上下文就是王道
为你的告警保留通用且有用的标签。它们对于告警路由和静默非常有用。
这些理念的灵感来自于 Go 之禅 、Go 格言 (Go Proverbs) 和 Python 之禅 。
*Thank you very much all others that contributed with their invaluable ideas.*
The initial rules are gathered from several sources from the community, such as [Prometheus Proverbs](https://www.youtube.com/watch?v=TwH3KXKbJqM) by [Björn Rabenstein](https://github.com/beorn7), [Best Practices and Beastly Pitfalls](https://www.youtube.com/watch?v=_MNYuTNfTb4) by [Julius Volz](https://github.com/juliusv), [Patterns for Instrumenting Your Go Services](https://www.youtube.com/watch?v=LU6D5cNeHks) by [Bartek Plotka](https://github.com/bwplotka) and [Kemal Akkoyun](https://github.com/kakkoyun), [Instrumenting Applications and Alerting with Prometheus](https://www.youtube.com/watch?v=sHKWD8XnmmY) by [Simon Pasquier](https://github.com/simonpasquier) and [Robust Perception Blog](https://www.robustperception.io/blog) by [Brian Brazil](https://github.com/brian-brazil).
更多资源
遵循这些约定能让你受益于社区工具
- 监控 Mixins (Monitoring Mixins) - 针对通用服务的可复用仪表盘和告警