跳转至

超越业务逻辑的编码 — 日志、指标、追踪与仪表盘从代码里长出来

这一章讲什么: 一个服务上线后,你凭什么知道它好不好?答案必须在你写代码的时候就写好—— 日志、指标、追踪、仪表盘,四样东西全是代码的产物,不是运维后来贴上去的膏药。 这一章是全书第一个动手层章节,给出了大量可以直接抄的代码、配置和清单。 读完你会拿到一条主线:同一个用户请求,如何穿过日志 → 指标 → 追踪 → 仪表盘这四层信号。

1. 主线例子:一笔支付请求的四层人生

本章全部机制,都挂在同一个具体输入上走一遍。输入:用户点击「结账」,支付 49.99 元。

  第 1 层 日志:    服务写下一行 JSON——"event": "payment_failed", "order_id": "A123",
                   "reason": "insufficient_funds", "trace_id": "c78f9d2a..."
  第 2 层 指标:    代码里 REQUEST_COUNT.inc() 加一,直方图记一次延迟 240ms
                   → Prometheus 定时来 /metrics 端点抓走
  第 3 层 追踪:    请求进网关时拿到 trace_id,调用支付服务、写消息队列,
                   每个服务都把自己的一小段(span)挂到同一个 trace_id 上
  第 4 层 仪表盘:  Grafana 上,SLO 行显示「支付成功率 99.2%,已跌破 99.9% 目标」,
                   依赖行显示「支付网关错误率飙升」,注解行显示「14:03 有一次配置变更」

  图说:一层信号回答一个问题。日志答「发生了什么」,指标答「多严重、什么趋势」,
  追踪答「卡在哪一跳」,仪表盘答「现在要不要人管」。
  上面每个字段名都来自原书示例;金额与延迟数值沿用了原书例子的量级。

下面四节把每一层讲透,第五节讲不同负载的监控怎么调,第六节讲仪表盘归谁管, 第七节是一个真实的翻车与翻盘案例。

2. 结构化日志:从「Error occurred」到可查询的数据

2.1 解决什么问题

传统日志是这样的:

  User login failed
  Connection error

原书的话很直白:这种日志「在生产里几乎没用」——数据量巨大的时候,没有格式的文本 让 ELK/OpenSearch 这类日志处理器无从下手1。

结构化日志的做法:每行日志是一个键值对(通常就是 JSON——一种通用的文本数据格式),字段名固定。 原书给的完整例子(照抄,这是知识本身):

{
  "timestamp": "2025-09-18T10:23:54Z",
  "level": "ERROR",
  "event": "user_login_failed",
  "user_id": "12345",
  "ip_address": "192.168.1.10",
  "reason": "invalid_password"
}

同一个例子换到我们的主线:两行都写「Payment failed」的裸日志,排查时无法区分; 带上下文的结构化日志写明是订单 A123、用户 78910、信用卡、余额不足—— 谁受影响、哪一步失败、为什么、什么时候,四个问题一条日志答完2。

结构化之后,日志从「要肉眼翻的文本」变成「可以查询的数据」: 按 IP 筛所有失败登录、按用户算错误率、按小时数密码尝试次数,都是一条查询3。

2.2 五条最佳实践(原书的清单,接住)

  1. 分级:DEBUG(开发排错细节)< INFO(服务启动、用户登录这类大事)< WARN(不致命但蹊跷)< ERROR(功能坏了)< FATAL(系统要停);
  2. 带关联 ID(correlation ID):分布式系统里一笔请求穿过多个服务,给每笔请求一个唯一 ID 写进每行日志,才能把散在各服务的日志串回同一个故事4;
  3. 绝不记敏感数据:密码、卡号、PII(个人身份信息)要么脱敏(改成认不出原值的样子)、要么哈希(用算法搅成不可逆的乱码)5;
  4. 跨服务统一格式:所有服务用同一套字段名,集中分析才成立。

2.3 代码怎么写(原书的 Python 例子,照抄)

原书给了一个 JSONFormatter 的例子:自定义一个日志格式化器,把每条记录转成 JSON, 并自动生成 correlation_id6。输出长这样:

  {"timestamp": "2025-09-18 12:20:45", "level": "INFO", "message": "User login successful", "correlation_id": "9e3a..."}
  {"timestamp": "2025-09-18 12:20:46", "level": "ERROR", "message": "Payment failed due to insufficient funds", "correlation_id": "3f4b..."}

2.4 为什么日志是开发者的事,不是运维的事

原书给了五条理由,本质是同一件事的不同侧面:写日志的人是半夜读日志的人7:

理由 机制
加快事故解决 模糊日志(「Error in service」)让定位根因靠猜;具体日志(「transaction failed for order_id=A123 due to insufficient funds」)一眼定位。MTTR(平均修复时长)差距由此而来
开发者为自己的代码值班 SRE 推行的「自己的代码自己背」意味着凌晨 2 点被叫起来的人就是写代码的人——知道自己要读,日志自然会写好
日志是反馈环 哪个 API 最常被调?有没有暴力破解登录的迹象?新功能上线后有没有意外报错?答案都在日志里
可观测平台依赖它 Prometheus/Grafana/OpenSearch/Splunk 的告警和仪表盘,原料都是结构化日志
合规要求 金融、医疗行业,记「谁在何时做了什么」是法定义务,不是可选项

3. 代码级指标:把「感觉不对」变成「曲线破了阈值」

3.1 解决什么问题

日志给细节,但海量日志里看不出趋势。原书的对比例子:日志告诉你 「14:01:45 有一条 503」;指标给你一张图——每秒请求数 14:00 开始掉、错误率 14:01 开始飙8。 两者合起来才是完整的可观测图景。

关键立场:不要只依赖基础设施指标(CPU、内存),要从代码里主动暴露业务级指标—— 每分钟处理多少订单、API 平均响应时间、缓存命中率、ML 推理延迟9。

3.2 四种指标类型(名字必须留,Prometheus 生态的通用语)

类型 行为 例子
Counter(计数器) 只增不减 请求总数、错误总数
Gauge(仪表盘值) 可上可下 当前内存占用、活跃会话数
Histogram(直方图) 把值分桶统计 响应时间分进 <100ms / <500ms / <1s 各档
Summary(摘要) 直方图的统计聚合版 p95 延迟(第 95 百分位:比它快的请求占 95%)

3.3 代码怎么写(原书的 Python 例子,照抄)

用 prometheus_client 库,两行定义指标,处理请求时打点, start_http_server(8000) 开一个 /metrics 端点供 Prometheus 来抓取10。

抓走的数据长这样(照抄):

  # TYPE app_requests_total counter
  app_requests_total 42.0
  app_request_latency_seconds_bucket{le="0.1"} 12.0
  app_request_latency_seconds_bucket{le="0.5"} 38.0
  app_request_latency_seconds_bucket{le="1.0"} 42.0
  app_request_latency_seconds_count 42.0
  app_request_latency_seconds_sum 20.57

读法:42 个请求里,12 个快于 0.1 秒,38 个快于 0.5 秒,全部快于 1 秒—— 直方图桶的存在,让「p95 延迟」这类 SLO 算得出来。数据进 Grafana 画图、配告警11。

3.4 五条最佳实践

  1. 技术和业务指标都暴露(别只有 CPU,要有「每秒订单数」这种 KPI);
  2. 命名一致,加服务名前缀(如 payment_requests_total);
  3. 基数要低:标签值必须有限——把 user_id 当标签会让时间序列爆炸,监控系统的存储被撑垮;
  4. 对齐 SLI/SLO:指标要能直接算服务等级指标(延迟、错误率)和目标;
  5. 本地先验证指标暴露正确再上线12。

判断(我们的,不是书里的): 第 3 条「基数要低」是本章含金量最高的一句劝, 也是新人最容易踩的坑:user_id 当标签,十万用户就是十万条时间序列。 原书在日志节、指标节、追踪节里把这条反模式重复了三遍——重复是有意的: 高基数是成本失控的第一大来源,而且是在「一切正常」的时候悄悄发生的。 如果错,会错在: 某些新系统(原生支持高基数的可观测后端)正在放宽这条限制; 若读者所在平台是这类系统,这条禁令的代价评估要重写,但「先想清楚标签的取值集合有多大」 这个习惯仍然成立。

4. 把可观测性建进微服务:契约、传播、采样

这是全书最硬的一节。中心主张:系统碎成几十个独立部署的服务后,可观测性不再是工具选择, 而是架构属性——每个服务必须「自我描述」13。

4.1 可观测性契约(observability contract)

原书把它定义成「每个服务必须满足的、不可讨价还价的接口」。内容三块14:

第一,身份坐标。 每个信号都带三个字段:service.name(稳定可读的名字)、 service.version(语义版本或 Git SHA)、deployment.environment(dev/staging/prod)。 原书说,出事时能按 version=1.12.0 切片,「值它的黄金重量」——切到具体版本, 才知道是不是刚上的新版闯的祸。

第二,三个标准端点。 每个服务都发布:

端点 回答谁的问题 答什么
/healthz(存活) 平台(Kubernetes) 进程活着没、卡死没?卡了就重启它
/readyz(就绪) 负载均衡 能安全收流量了吗?(检查数据库、缓存、消息队列等下游)
/metrics Prometheus 来抓指标

原书特别提醒:存活和就绪服务两个观众,混为一谈会出乱子—— 探活失败被重启、就绪没好就接流量,结果就是无谓的重启风暴或 5xx 洪水15。

第三,三支柱,有意为之。 契约不是「随便记点什么」,是三样各就其位: 追踪(traces,跨服务的端到端请求路径)、指标(metrics,每条路由的 RED 信号—— Rate 速率、Errors 错误、Duration 时长——加业务 KPI)、日志(结构化、带上下文、 与追踪关联——每行日志带 trace_id/span_id)。

外加一条纪律:一致性压倒聪明。命名约定只定一次(属性名 snake_case、指标带服务前缀、 span 名用「动词-资源」),用代码评审和 lint 规则强制执行——最好的可观测性, 是所有地方都能用同一种查法16。

4.2 上下文传播:一笔请求的故事如何穿过进程边界

单体应用里,栈追踪(stack trace,程序出错时自动打印的调用链)把故事讲完。 微服务里,故事跨进程、跨协议,需要一个可携带的叙事——W3C Trace Context 标准 (名字要留,业界标准)就是这套叙事:一个 trace_id 从 API 网关流入,穿过服务调用、 消息队列,进入后台 worker17。

落到我们的主线例子里,完整故事是: 用户点结账 → 服务 A 校验请求 → 服务 B 扣款 → 一条消息进队列 → 服务 C 履约发货, 五跳挂在同一个 trace_id 下,压力之下这一屏的清晰度「改变结局」18。

传播的三个现实细节:

  • HTTP 到 HTTP:用 OpenTelemetry(可观测性数据采集的标准工具集,名字留)的自动注入/提取,框架自动在请求头里带上 traceparent;
  • HTTP 到消息队列:把 trace 上下文放进消息头(每个网络请求开头附带的元数据小标签,元数据即「描述数据的数据」),消费者取出来续上——不做这步,异步环节(发送方不等回应、各干各的通信方式)就是全盲的;
  • 网关和代理:必须原样转发 trace 头,不能剥离;已有 X-Correlation-Id 的旧系统,让它从 trace_id 派生,日志和追踪才对得上19。

4.3 插桩策略:自动铺广度,手动标业务

原书的分工极清晰,照单接住20:

用自动插桩(auto-instrumentation) 用手动 span
覆盖那 80% 不该手写的:进出网络 I/O、框架、常用数据库客户端、gRPC、消息队列 标业务关键时刻:promo_applied、inventory_reserved、model_scored(促销生效、库存锁定、模型打分)
保证一致性 保证意义

原书还给了个修剪成本的洞察:将来要降本降噪时,先删的是自动生成的库噪音, 你手写的业务 span 一定会留下——因为人是在那里排障的。

4.4 在 Kubernetes 里接线

服务发布了 /metrics,Prometheus 怎么知道来抓?两条路(名字留)21:

  1. 注解方式(简单):给 Pod/Service 加 prometheus.io/scrape: "true" 和端口注解;
  2. ServiceMonitor/PodMonitor(结构化,多团队友好):Prometheus Operator 的定制资源,按标签选服务、定抓取间隔(如 15 秒)。

追踪数据走 OpenTelemetry Collector:常见拓扑是每个节点跑一个 agent(DaemonSet, 本地缓存、抗网络抖动),再转发到中央 gateway(Deployment,统一做采样、脱敏、路由的策略)—— 以后想上调采样策略,只动 gateway,不用碰应用代码22。

4.5 采样:成本与信号的权衡

全量存 trace 太贵。两种采样,一对 trade-off23:

采样方式 在哪做 行为 代价
头部采样(head) SDK(开发工具包)侧,数据一产生就定 便宜、快 可能丢掉稀有的慢请求——决定做得太早
尾部采样(tail) Collector 侧,看完整段 span 再定 「错误和慢 trace 全留,其余抽 10%」做得到 要在 gateway 攒数据,复杂

原书的起步配方:ERROR trace 全留、p95 以上延迟的全留、正常流量抽 5–10%—— 信噪比高,存储也不淹24。

4.6 出错时的语义与三支柱联动

span 要替未来的你说清「什么坏了、为什么」:标 StatusCode.ERROR,附稳定的 error.type(如 db.timeout、payment.declined)和 error.message;异常记到 span 上, 不只是写日志25。三支柱之间的跳转要一键直达:日志自动注入 trace_id/span_id, 仪表盘面板带「查看 trace」深链,日志系统里 trace_id 是一等字段而不是埋在自由文本里—— 事故中不用手抄 ID 来回粘贴,MTTR 才会真的降26。

4.7 SLO 对齐的仪表盘与「测试你的可观测性」

仪表盘不是装饰,是 SLO 的界面。五层结构(第 6 节还会展开): SLO 与错误预算燃烧率 → 关键路由的 RED → 依赖(DB、缓存、支付) → 容量(CPU、队列深度、GC) → 变更注解(部署、特性开关、schema 变更)。燃烧率告警用「多窗口、多燃烧率」—— 快窗口抓突发灾难,慢窗口抓缓慢渗漏,都不为噪音叫人27。

最有意思的是原书把可观测性当 API 来测试28:

  • 契约测试:依赖挂了时打 /readyz,它是否真的报 not ready?/metrics 是否暴露了该有的计数器和标签?
  • 集成测试:发一个请求,断言产生了一个带 http.route 的 server span,且你手写的 checkout.process span 真的出现、带着 order.id;
  • 混沌探针:注入延迟或故障,验证尾部采样真的留住了这些 trace、告警真的响了。

「不测就会漂移」——重构之后 trace 上下文丢了,只有测试能第一时间抓住。

4.8 迁移路线图与反模式

原书给了不用重写的八步路线:统一身份 → 加三个端点 → 部署 Collector(agent+gateway)→ 开自动追踪、验证跨两个服务的传播 → 日志注入 trace_id → 每个服务定三个业务指标并接 SLO 仪表盘 → 引入尾部采样 → 把契约固化进服务模板,新服务生来合规29。

五个反模式(全部高发过)30:DEBUG 日志泛滥(噪音淹没信号、成本翻倍); 高基数标签;在网关/消息队列剥掉 trace 头(链条断裂,端到端排障不可能); 命名不一致(ordersProcessed/orders_processed/order_count 并存,查询脆弱); 一张巨型仪表盘塞所有东西。

5. 按负载类型调监控:同一套契约,不同的重点

契约不变,但信号的优先级必须随负载变。原书分了四类,对照表(表 3.1)接住31:

负载 最要紧的指标 典型死法 典型 SLO
CPU 密集型(批处理、视频转码、高频交易) 每核 CPU 利用率(别取平均,热点会被平均掉)、CPU 被限流时长、队列长度、延迟分布 负载下的延迟尖刺 p95 延迟 < 200ms
内存密集型(缓存层、内存数据库) 工作集/RSS(实际驻留内存,不是申请量)、缓存命中率、GC 停顿、OOM 被杀次数 OOM、缓存不命中 缓存命中率 > 95%
I/O 密集(日志采集、ETL、API 网关) 磁盘 IOPS/延迟、网络吞吐(单位时间处理量)与丢包、下游依赖延迟/错误率 重试、队列堆积 吞吐 > X req/s,依赖延迟 < 100ms
AI/ML 推理 GPU(显卡)利用率与显存(显卡内存)、推理延迟分布、模型准确率/漂移 显存耗尽、准确率退化 p95 推理 < 100ms,准确率 ≥ 98%

两条跨类的忠告:重试率常常掩盖 I/O 瓶颈(重试把「慢」伪装成「忙」); AI/ML 的独特之处是失败模式隐蔽——不是延迟尖刺,而是准确率漂移, 所以监控要把基础设施指标和模型级信号(预测分布、输入特征偏移)组合起来, GPU 指标用 NVIDIA DCGM 这类 exporter 暴露32。

6. 开发者拥有仪表盘:owning the glass

仪表盘曾被视为运维的物件:中央运维团队或 NOC(网络运行中心)盯着一墙屏幕, 开发者对自己代码的线上表现两眼一抹黑——交接慢、排障慢、优先级拧巴33。 本章的立场:写服务的人必须同时控制观察这个服务的镜头,这就是 owning the glass (拥有这块屏)34。

6.1 为什么是开发者的事

仪表盘是代码与开发者之间的直接反馈环:新版上线延迟涨了,应该立刻在仪表盘上看到; 配置改完错误率飙了,仪表盘应该把影响摆在你脸前35。它给四样东西: 可见性、可归责(最近这次发布到底伤没伤性能)、学习(真实流量怎么压你的设计)、 信心(部署能不能放心继续)。

6.2 四条设计原则

  1. 锚定 SLO:首屏回答「目标达到了吗」——SLO 是 99.9% 的结账请求 200ms 内完成, 第一块面板就必须答这件事;
  2. 极简:10–15 块精心挑选的面板,细节放下钻页——信息太多和信息太少一样坏;
  3. 跨服务一致:所有服务的错误率面板永远左上角、p95 永远右上角——事故中靠的是肌肉记忆,省的是分钟;
  4. 注解变化:部署、schema 迁移、特性开关直接标在时间轴上——大多数回归与变更相关,那就把变更画出来36。

外加一条:三支柱并排或互链,仪表盘是发射台,不是终点37。

6.3 业务信号只有开发者给得出

CPU 全绿、业务全挂,是原书反复警告的错配。每个服务要加业务特有的信号: 支付服务看支付成功率/拒付原因/每秒交易数;推荐服务看缓存命中率/推荐延迟/模型置信度分布; 批处理管道看每分钟处理记录数/滞后/吞吐趋势38。这些指标必须手工在代码里打点, 只有开发者能做。

一个结账服务仪表盘的五层样板:SLO 行(错误率、p95、可用性)→ RED 行(请求速率、 分路由错误率、延迟直方图)→ 依赖行(支付 API 延迟/错误、数据库查询时长、缓存命中率)→ 容量行(CPU、内存、队列深度)→ 注解行(部署、配置变更)39。

6.4 反模式与持有纪律

反模式四种:仪表盘蔓生(每服务好几张、无人维护、没有唯一真相源);虚荣仪表盘 (好看但无可行动的洞察);无主仪表盘(运维建的、开发者从不更新,很快过时); 没有上下文的告警(响了却不解释为什么,排查者还得跨工具拼故事)40。

持有纪律四条:建服务不收工直到仪表盘随服务一起发布;模板化、当代码管 (Grafana JSON 进 Git);拿仪表盘演练(事故模拟、game day 里只用仪表盘排障); 持续迭代41。

7. 案例:救回一次大促发布的收银台仪表盘

这是全书最锋利的一课,值得整段走完42:

  第一幕(全绿但全挂):
    零售公司上线新的收银微服务,监控归中央运维团队
    → 仪表盘上只有 CPU(50%)、内存(60%)、容器重启数,全绿
    → 大促开始几小时内:客诉涌入,支付失败,购物车超时,收入暴跌
    → 运维仪表盘依然全绿(CPU、内存稳稳的)
    → NOC 升级了事故,但没有应用级指标,诊断成了猜谜
    → 开发者被拉进来时,几小时过去,大额销售已损失

  第二幕(仪表盘重构):
    开发团队接管仪表盘,围绕收银服务的真正使命重构——
    「又快又稳地处理交易」
    → 顶行:支付成功率 + 结账延迟分布
    → 次行:支付网关错误率、数据库查询性能
    → 注解面板:部署与配置变更

  第三幕(几个月后,同样的高峰):
    支付网关一个配置变更导致支付失败率隐蔽而尖锐地上升
    → 支付成功率面板变红(分钟级),依赖行清楚显示网关 API 错误尖刺
    → 团队 20 分钟内回滚了配置,避免又一次大事故

  图说:基础设施指标回答「机器好不好」,业务指标回答「生意好不好」。
  大促场景里,你两个答案都需要;但大多数组织的仪表盘只有第一个。

8. 边界与局限

  1. 代码密度极高,但版本会漂移。 本章的 FastAPI/OTel/Prometheus 代码是按 2025–2026 年生态写的, 库名和端口号是当时的写法;学结构与字段,别背 API。
  2. 采样配方(留 ERROR、p95+、抽 5–10%)是经验值不是定理,原书自己也标了 illustrative; 高合规行业可能要求全量留痕,成本模型完全不同。
  3. 「契约」没有验收工具链的展开——lint 规则、模板固化各提一句,怎么做全靠读者自己补。
  4. 成本节(基数预算、保留分层)给的是原则,没有数字锚点——保留多久、预算是多少, 书里没有参照系。
  5. 章末的 MCQ/思考题(文件 20–21)是练习题,内容已被正文覆盖,不再逐题拆。

9. 可带走的

  1. 日志写成 JSON 键值对,带 event/order_id/reason/trace_id,裸文本日志等于没有日志;
  2. 四种指标类型(Counter/Gauge/Histogram/Summary)是通用语;直方图桶让 p95 算得出来;
  3. 标签基数必须有限——user_id 进日志别进指标标签,这是成本失控第一大坑;
  4. 可观测性契约三件套:身份坐标(service.name/version/environment)、/healthz /readyz /metrics、三支柱各就其位;
  5. 存活探针给平台看、就绪探针给流量看,混用=重启风暴或 5xx 洪水;
  6. trace_id 必须穿过消息队列,异步环节不传播上下文就是盲区;
  7. 自动插桩铺广度(80%),手动 span 标业务关键时刻(/checkout.process 这种);
  8. 采样起步配方:ERROR 全留、p95+ 全留、正常流量 5–10%;
  9. 仪表盘五层:SLO → RED → 依赖 → 容量 → 注解;10–15 块面板,跨服务同布局;
  10. 可观测性要当 API 测试:契约测试、集成断言、混沌探针,不测就会漂移。

10. 原文地图

主题 原书章 原文位置
结构化日志示例与查询 Importance of structured and contextual logging text/13-fm-importance-of-structured-and-contextual-logging.txt:37(搜「user_login_failed」) · text/13-fm-importance-of-structured-and-contextual-logging.txt:56(搜「specific IP address」)
日志最佳实践(分级/关联 ID/脱敏) 同上 text/13-fm-importance-of-structured-and-contextual-logging.txt:121(搜「DEBUG」) · text/13-fm-importance-of-structured-and-contextual-logging.txt:153(搜「sensitive data」)
Python JSON 日志例子 同上 text/13-fm-importance-of-structured-and-contextual-logging.txt:175(搜「JSONFormatter」)
日志为何归开发者(值班/反馈环/合规) 同上 text/13-fm-importance-of-structured-and-contextual-logging.txt:267(搜「2 AM」) · text/13-fm-importance-of-structured-and-contextual-logging.txt:299(搜「legal requirement」)
指标四类型与 Prometheus 例子 Implementing metrics at code level text/14-fm-implementing-metrics-at-code-level.txt:40(搜「Counters」) · text/14-fm-implementing-metrics-at-code-level.txt:122(搜「app_requests_total 42.0」)
指标最佳实践(命名/基数/SLO) 同上 text/14-fm-implementing-metrics-at-code-level.txt:169(搜「consistent naming」) · text/14-fm-implementing-metrics-at-code-level.txt:172(搜「cardinality」)
可观测性契约(身份/端点/三支柱) Building observability into microservices text/15-fm-building-observability-into-microservices.txt:14(搜「service.name」) · text/15-fm-building-observability-into-microservices.txt:23(搜「healthz」) · text/15-fm-building-observability-into-microservices.txt:34(搜「RED」)
存活 vs 就绪 同上 text/15-fm-building-observability-into-microservices.txt:29(搜「noisy restarts」)
W3C Trace Context 与传播 同上 text/15-fm-building-observability-into-microservices.txt:45(搜「W3C Trace Context」) · text/15-fm-building-observability-into-microservices.txt:55(搜「blind spots」)
自动 vs 手动插桩 同上 text/15-fm-building-observability-into-microservices.txt:104(搜「auto-instrumentation」) · text/15-fm-building-observability-into-microservices.txt:114(搜「business risk」)
K8s 接线与 Collector 拓扑 同上 text/15-fm-building-observability-into-microservices.txt:327(搜「prometheus.io/scrape」) · text/15-fm-building-observability-into-microservices.txt:370(搜「DaemonSet」)
采样(头/尾)与起步配方 同上 text/15-fm-building-observability-into-microservices.txt:394(搜「Head sampling」) · text/15-fm-building-observability-into-microservices.txt:400(搜「5–10%」)
错误语义与三支柱联动 同上 text/15-fm-building-observability-into-microservices.txt:410(搜「error.type」) · text/15-fm-building-observability-into-microservices.txt:427(搜「Log injection」)
仪表盘五层与 PromQL 同上 text/15-fm-building-observability-into-microservices.txt:498(搜「Top row」) · text/15-fm-building-observability-into-microservices.txt:521(搜「histogram_quantile」)
测试可观测性与迁移路线 同上 text/15-fm-building-observability-into-microservices.txt:535(搜「Contract tests」) · text/15-fm-building-observability-into-microservices.txt:575(搜「Standardize identity」)
反模式与多语言快速上手 同上 text/15-fm-building-observability-into-microservices.txt:610(搜「Everything in DEBUG」) · text/15-fm-building-observability-into-microservices.txt:629(搜「Node.js」)
负载类型监控与表 3.1 Tailoring monitoring for different workloads text/16-fm-tailoring-monitoring-for-different-workloads.txt:17(搜「per core」) · text/16-fm-tailoring-monitoring-for-different-workloads.txt:295(搜「Table 3.1」)
AI/ML 监控(漂移/DCGM) 同上 text/16-fm-tailoring-monitoring-for-different-workloads.txt:140(搜「drift」) · text/16-fm-tailoring-monitoring-for-different-workloads.txt:151(搜「DCGM」)
owning the glass 与四原则 Developer ownership of service dashboards text/17-fm-developer-ownership-of-service-dashboards.txt:7(搜「owning the glass」) · text/17-fm-developer-ownership-of-service-dashboards.txt:57(搜「SLO-driven」)
业务信号与仪表盘样板 同上 text/17-fm-developer-ownership-of-service-dashboards.txt:79(搜「Payment success rate」) · text/17-fm-developer-ownership-of-service-dashboards.txt:96(搜「Row 1」)
仪表盘反模式与持有纪律 同上 text/17-fm-developer-ownership-of-service-dashboards.txt:129(搜「Dashboard sprawl」) · text/17-fm-developer-ownership-of-service-dashboards.txt:155(搜「Grafana JSON in Git」)
收银台案例三幕 Case study of checkout dashboard that saved a launch text/18-fm-case-study-of-checkout-dashboard-that-saved-a-la.txt:7(搜「all green」) · text/18-fm-case-study-of-checkout-dashboard-that-saved-a-la.txt:13(搜「20 minutes」)
章结论 Conclusion text/19-fm-conclusion.txt:4(搜「core design principle」)

  1. 出处:「Importance of structured and contextual logging」第 7 段(text/13-fm-importance-of-structured-and-contextual-logging.txt:7,搜「practically useless」)与第 22 段(text/13-fm-importance-of-structured-and-contextual-logging.txt:22,搜「Elasticsearch」)。 ↩

  2. 出处:「Importance of structured and contextual logging」第 84–111 段(text/13-fm-importance-of-structured-and-contextual-logging.txt:93,搜「payment_failed」;text/13-fm-importance-of-structured-and-contextual-logging.txt:111,搜「who was affected」)。 ↩

  3. 出处:「Importance of structured and contextual logging」第 52–66 段(text/13-fm-importance-of-structured-and-contextual-logging.txt:56,搜「specific IP address」)。原书结论:「这一结构化方法把日志从原始文本变成可查询的数据。」 ↩

  4. 出处:「Importance of structured and contextual logging」第 138 段(text/13-fm-importance-of-structured-and-contextual-logging.txt:138,搜「correlation ID」)。 ↩

  5. 出处:「Importance of structured and contextual logging」第 153 段(text/13-fm-importance-of-structured-and-contextual-logging.txt:153,搜「raw passwords」)。 ↩

  6. 出处:「Importance of structured and contextual logging」第 166–232 段(text/13-fm-importance-of-structured-and-contextual-logging.txt:175,搜「JSONFormatter」;text/13-fm-importance-of-structured-and-contextual-logging.txt:229,搜「9e3a」)。 ↩

  7. 出处:「Importance of structured and contextual logging」第 267 段(text/13-fm-importance-of-structured-and-contextual-logging.txt:267,搜「2 AM」)与第 299 段(text/13-fm-importance-of-structured-and-contextual-logging.txt:299,搜「legal requirement」)。 ↩

  8. 出处:「Implementing metrics at code level」第 13 段(text/14-fm-implementing-metrics-at-code-level.txt:13,搜「503 Service Unavailable」)。 ↩

  9. 出处:「Implementing metrics at code level」第 16 段(text/14-fm-implementing-metrics-at-code-level.txt:16,搜「business and application-level metrics」)。 ↩

  10. 出处:「Implementing metrics at code level」第 62–113 段(text/14-fm-implementing-metrics-at-code-level.txt:74,搜「app_requests_total」;text/14-fm-implementing-metrics-at-code-level.txt:101,搜「start_http_server」)。 ↩

  11. 出处:「Implementing metrics at code level」第 146 段(text/14-fm-implementing-metrics-at-code-level.txt:146,搜「Grafana dashboards」)。 ↩

  12. 出处:「Implementing metrics at code level」第 166–178 段(text/14-fm-implementing-metrics-at-code-level.txt:172,搜「unbounded label values」)。 ↩

  13. 出处:「Building observability into microservices」第 4 段(text/15-fm-building-observability-into-microservices.txt:4,搜「architectural property」)。 ↩

  14. 出处:「Building observability into microservices」第 14–38 段(text/15-fm-building-observability-into-microservices.txt:14,搜「service.name」;text/15-fm-building-observability-into-microservices.txt:27,搜「scrapable endpoint」)。 ↩

  15. 出处:「Building observability into microservices」第 29 段(text/15-fm-building-observability-into-microservices.txt:29,搜「noisy restarts」)。原文:「把两者当一回事会造成吵闹的重启或 5xx 风暴。」 ↩

  16. 出处:「Building observability into microservices」第 38 段(text/15-fm-building-observability-into-microservices.txt:38,搜「Consistency over cleverness」)。 ↩

  17. 出处:「Building observability into microservices」第 45 段(text/15-fm-building-observability-into-microservices.txt:45,搜「W3C Trace Context」)。 ↩

  18. 出处:「Building observability into microservices」第 98 段(text/15-fm-building-observability-into-microservices.txt:98,搜「fulfilled the order」)。 ↩

  19. 出处:「Building observability into microservices」第 52–61 段(text/15-fm-building-observability-into-microservices.txt:55,搜「blind spots」;text/15-fm-building-observability-into-microservices.txt:61,搜「X-Correlation-Id」)。 ↩

  20. 出处:「Building observability into microservices」第 104–121 段(text/15-fm-building-observability-into-microservices.txt:111,搜「80%」;text/15-fm-building-observability-into-microservices.txt:117,搜「Auto for consistency」)。 ↩

  21. 出处:「Building observability into microservices」第 317–366 段(text/15-fm-building-observability-into-microservices.txt:327,搜「prometheus.io/scrape」;text/15-fm-building-observability-into-microservices.txt:344,搜「ServiceMonitor」)。 ↩

  22. 出处:「Building observability into microservices」第 370 段(text/15-fm-building-observability-into-microservices.txt:370,搜「DaemonSet」)。 ↩

  23. 出处:「Building observability into microservices」第 394–397 段(text/15-fm-building-observability-into-microservices.txt:394,搜「Head sampling」)。 ↩

  24. 出处:「Building observability into microservices」第 400 段(text/15-fm-building-observability-into-microservices.txt:400,搜「keep ERROR traces」)。 ↩

  25. 出处:「Building observability into microservices」第 410–416 段(text/15-fm-building-observability-into-microservices.txt:410,搜「error.type」)。 ↩

  26. 出处:「Building observability into microservices」第 423–433 段(text/15-fm-building-observability-into-microservices.txt:427,搜「Log injection」)。 ↩

  27. 出处:「Building observability into microservices」第 498–525 段(text/15-fm-building-observability-into-microservices.txt:498,搜「Top row」;text/15-fm-building-observability-into-microservices.txt:525,搜「multi-window」)。 ↩

  28. 出处:「Building observability into microservices」第 531–545 段(text/15-fm-building-observability-into-microservices.txt:535,搜「Contract tests」;text/15-fm-building-observability-into-microservices.txt:531,搜「drifts」)。 ↩

  29. 出处:「Building observability into microservices」第 571–600 段(text/15-fm-building-observability-into-microservices.txt:575,搜「Standardize identity」;text/15-fm-building-observability-into-microservices.txt:596,搜「service templates」)。 ↩

  30. 出处:「Building observability into microservices」第 610–622 段(text/15-fm-building-observability-into-microservices.txt:610,搜「Everything in DEBUG」;text/15-fm-building-observability-into-microservices.txt:616,搜「Dropping context」)。 ↩

  31. 出处:「Tailoring monitoring for different workloads」第 13–26 段(text/16-fm-tailoring-monitoring-for-different-workloads.txt:17,搜「per core」)与第 180–295 段(text/16-fm-tailoring-monitoring-for-different-workloads.txt:295,搜「Table 3.1」)。 ↩

  32. 出处:「Tailoring monitoring for different workloads」第 140–157 段(text/16-fm-tailoring-monitoring-for-different-workloads.txt:140,搜「drift」;text/16-fm-tailoring-monitoring-for-different-workloads.txt:151,搜「DCGM」)。 ↩

  33. 出处:「Developer ownership of service dashboards」第 4 段(text/17-fm-developer-ownership-of-service-dashboards.txt:4,搜「Network Operations Center」)。 ↩

  34. 出处:「Developer ownership of service dashboards」第 7 段(text/17-fm-developer-ownership-of-service-dashboards.txt:7,搜「owning the glass」)。原文:「开发者不仅写服务,还控制观察服务健康的镜头。」 ↩

  35. 出处:「Developer ownership of service dashboards」第 13 段(text/17-fm-developer-ownership-of-service-dashboards.txt:13,搜「feedback loop」)。 ↩

  36. 出处:「Developer ownership of service dashboards」第 42–51 段(text/17-fm-developer-ownership-of-service-dashboards.txt:42,搜「anchored in SLOs」;text/17-fm-developer-ownership-of-service-dashboards.txt:51,搜「root cause of performance regressions」)。 ↩

  37. 出处:「Developer ownership of service dashboards」第 69 段(text/17-fm-developer-ownership-of-service-dashboards.txt:69,搜「launchpad」)。 ↩

  38. 出处:「Developer ownership of service dashboards」第 79–89 段(text/17-fm-developer-ownership-of-service-dashboards.txt:89,搜「manual instrumentation」)。 ↩

  39. 出处:「Developer ownership of service dashboards」第 96–108 段(text/17-fm-developer-ownership-of-service-dashboards.txt:96,搜「Row 1」)。 ↩

  40. 出处:「Developer ownership of service dashboards」第 129–142 段(text/17-fm-developer-ownership-of-service-dashboards.txt:129,搜「Dashboard sprawl」;text/17-fm-developer-ownership-of-service-dashboards.txt:138,搜「Alerts without context」)。 ↩

  41. 出处:「Developer ownership of service dashboards」第 152–161 段(text/17-fm-developer-ownership-of-service-dashboards.txt:152,搜「part of development」;text/17-fm-developer-ownership-of-service-dashboards.txt:158,搜「game days」)。 ↩

  42. 出处:「Case study of checkout dashboard that saved a launch」第 4–16 段(text/18-fm-case-study-of-checkout-dashboard-that-saved-a-la.txt:7,搜「all green」;text/18-fm-case-study-of-checkout-dashboard-that-saved-a-la.txt:13,搜「under 20 minutes」)。CPU 50%、内存 60% 为原书数字。 ↩