第一章:Go语言可观测性三件套全景概览
可观测性是现代云原生系统稳定运行的核心能力,而 Go 语言生态中已形成一套高度协同、轻量高效且原生友好的“三件套”:OpenTelemetry(追踪与指标采集)、Prometheus(指标存储与查询)、Grafana(可视化与告警)。这三者并非孤立工具,而是通过标准协议与 Go SDK 深度集成,构成从数据生成、传输、存储到呈现的端到端可观测流水线。
OpenTelemetry:统一的数据采集基石
OpenTelemetry Go SDK 提供了标准化的 API 和 SDK,支持同时导出 traces、metrics 和 logs。安装依赖只需执行:
go get go.opentelemetry.io/otel/sdk \
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp \
go.opentelemetry.io/otel/exporters/prometheus
它通过 TracerProvider 和 MeterProvider 实例化采集器,并可无缝对接 Jaeger 或 Prometheus 后端——无需修改业务代码即可切换导出目标。
Prometheus:面向 Go 的指标存储与拉取引擎
Prometheus 原生支持 Go 运行时指标(如 goroutines、gc pause、heap alloc),通过 promhttp.Handler() 暴露 /metrics 端点:
import "github.com/prometheus/client_golang/prometheus/promhttp"
// 在 HTTP 路由中注册:
http.Handle("/metrics", promhttp.Handler())
配合 go.opentelemetry.io/otel/exporters/prometheus,还可将 OTel 自定义指标自动映射为 Prometheus 格式,实现双模型兼容。
Grafana:Go 应用监控的可视化中枢
Grafana 不仅展示 Prometheus 数据源,还支持直接接入 OpenTelemetry Collector 的 OTLP endpoint(如 http://localhost:4317)以渲染 trace 分布热力图与服务拓扑。典型配置包括:
- 添加 Prometheus 数据源(地址:
http://prometheus:9090) - 导入 Go Runtime Dashboard(ID: 12345)或自定义面板,聚合
go_goroutines,process_cpu_seconds_total等关键指标
| 组件 | 核心职责 | Go 集成优势 |
|---|---|---|
| OpenTelemetry | 标准化信号采集 | 零依赖注入、上下文透传、低侵入 |
| Prometheus | 多维指标拉取与 PromQL | 内置 runtime/metrics、Pull 模式契合 Go 服务部署习惯 |
| Grafana | 交互式仪表盘与告警 | 支持 Go Profiling 数据火焰图插件 |
第二章:OpenTelemetry在Go中的深度集成与自动埋点
2.1 OpenTelemetry SDK架构解析与Go模块设计原理
OpenTelemetry Go SDK采用分层可插拔架构,核心由TracerProvider、MeterProvider和LoggerProvider三大工厂驱动,各Provider通过SDK接口抽象底层实现细节。
核心组件职责划分
TracerProvider:管理Tracer生命周期与Span处理器链SpanProcessor:异步/同步处理Span(如BatchSpanProcessor)Exporter:协议适配层(OTLP/gRPC、Jaeger、Zipkin)
数据同步机制
// BatchSpanProcessor 初始化示例
bsp := sdktrace.NewBatchSpanProcessor(
&otlpExporter{...}, // 实现 ExportSpans 方法
sdktrace.WithBatchTimeout(5*time.Second),
sdktrace.WithMaxExportBatchSize(512),
)
WithBatchTimeout控制最大等待时长;WithMaxExportBatchSize限制单次导出Span数量,避免内存积压与网络拥塞。
SDK初始化流程(mermaid)
graph TD
A[NewTracerProvider] --> B[Configure Processors]
B --> C[Attach Exporter]
C --> D[Register as global provider]
| 组件 | 线程安全 | 可热替换 | 依赖注入方式 |
|---|---|---|---|
| Tracer | ✅ | ❌ | Provider获取 |
| SpanProcessor | ✅ | ✅ | Provider配置 |
| Exporter | ✅ | ✅ | 构造函数传入 |
2.2 HTTP/gRPC服务自动 instrumentation 实战与性能验证
集成 OpenTelemetry 自动插桩
使用 opentelemetry-instrumentation 包实现零代码侵入式埋点:
# requirements.txt 中已声明 opentelemetry-instrumentation-http & grpcio-opentelemetry
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
provider = TracerProvider()
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://otel-collector:4318/v1/traces"))
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
逻辑说明:
BatchSpanProcessor缓存并批量上报 span,OTLPSpanExporter指定 OTLP/HTTP 协议端点;endpoint必须与 collector 配置一致,否则 span 丢失。
性能对比基准(单请求 P95 延迟)
| 协议类型 | 未插桩(ms) | 自动插桩(ms) | 增量 |
|---|---|---|---|
| HTTP | 12.3 | 13.7 | +1.4 |
| gRPC | 8.1 | 9.2 | +1.1 |
数据同步机制
graph TD
A[HTTP/gRPC Server] -->|自动注入span| B[OTel SDK]
B --> C[BatchSpanProcessor]
C --> D[OTLP/HTTP Exporter]
D --> E[Otel Collector]
E --> F[Jaeger/Tempo]
2.3 自定义Span与Context传播机制:从trace ID注入到跨goroutine传递
Go 的 context.Context 本身不携带 OpenTracing/OpenTelemetry 语义,需显式注入与提取 trace ID 和 span 上下文。
数据同步机制
跨 goroutine 时,context.WithValue() 创建的 Context 不会自动穿透 go func() { ... }(),必须手动传递:
ctx := context.WithValue(parentCtx, spanKey, span)
go func(ctx context.Context) {
// 正确:显式传入 ctx
childSpan := tracer.StartSpan("subtask", opentracing.ChildOf(span.Context()))
defer childSpan.Finish()
}(ctx) // ⚠️ 必须传入,否则 span 断链
逻辑分析:
spanKey是自定义context.Key类型,避免字符串 key 冲突;ChildOf()建立父子 span 关系,确保 trace ID、span ID、采样标志等沿调用链透传。
Context 传播的三种典型场景
| 场景 | 是否需手动传递 | 说明 |
|---|---|---|
| HTTP 请求中间件 | 是 | 从 r.Context() 提取并注入 span |
| goroutine 启动 | 是 | go f(ctx) 是唯一安全方式 |
| channel 消费者 | 否(推荐) | 将 ctx 与 payload 一同发送 |
graph TD
A[HTTP Handler] -->|inject span into ctx| B[Context]
B --> C[goroutine 1]
B --> D[goroutine 2]
C -->|ChildOf| E[Sub-span]
D -->|ChildOf| F[Sub-span]
2.4 资源(Resource)与属性(Attribute)建模:符合语义约定的可观测性元数据实践
在 OpenTelemetry 规范中,Resource 描述观测数据所归属的静态环境上下文(如服务名、主机ID、云平台),而 Attribute 表达动态、可变的业务或运行时特征(如 HTTP 状态码、用户ID、请求标签)。
核心建模原则
- Resource 属性应全局唯一、不可变,遵循 Semantic Conventions
- Attribute 应按语义分组(如
http.*,db.*),避免自定义前缀污染标准命名空间
示例:合规的 Resource 构建
from opentelemetry.sdk.resources import Resource
from opentelemetry.semconv.resource import ResourceAttributes
resource = Resource.create(
attributes={
ResourceAttributes.SERVICE_NAME: "checkout-api",
ResourceAttributes.SERVICE_VERSION: "v2.3.1",
ResourceAttributes.CLOUD_PROVIDER: "aws",
ResourceAttributes.HOST_NAME: "ip-10-0-1-42",
}
)
此代码显式使用语义常量(非字符串字面量)确保类型安全与工具链兼容性;
Resource.create()自动合并 SDK 默认资源(如telemetry.sdk.*),避免覆盖关键元数据。
常见 Resource 属性对照表
| 语义键 | 推荐值示例 | 是否必需 |
|---|---|---|
service.name |
"payment-gateway" |
✅ |
cloud.region |
"us-west-2" |
⚠️(云环境推荐) |
host.id |
"i-0a1b2c3d4e5f67890" |
❌(可选) |
graph TD
A[原始日志/指标] --> B[提取环境上下文]
B --> C{是否符合语义约定?}
C -->|是| D[注入 Resource 实例]
C -->|否| E[标准化映射器转换]
D & E --> F[统一导出至后端]
2.5 采样策略配置与动态调整:基于QPS、错误率与关键路径的分级采样实现
在高并发微服务场景中,全量链路采样不可持续。需依据实时指标动态分级:QPS ≥ 1000 且错误率 /order/submit)采样率设为 30%;其余流量按 1% 均匀采样。
动态采样决策逻辑
# sampling-config.yaml
rules:
- name: critical-path-full
condition: "qps >= 1000 && error_rate < 0.005"
targets: ["GET /payment/status", "POST /order/submit"]
sample_rate: 1.0
- name: core-fallback
condition: "qps > 200 && (error_rate >= 0.005 || error_rate <= 0.05)"
targets: ["GET /user/profile", "PUT /inventory/lock"]
sample_rate: 0.3
该配置由指标采集器每10秒刷新一次,经规则引擎求值后热更新采样器上下文;condition 支持轻量级 SpEL 表达式,避免引入 Groovy 等重型依赖。
采样等级与响应延迟对照表
| 采样等级 | QPS 范围 | 错误率阈值 | 平均 P95 延迟增幅 |
|---|---|---|---|
| 全采样 | ≥1000 | +8.2% | |
| 核心采样 | 200–999 | 0.5%–5% | +2.1% |
| 基础采样 | 任意 | +0.3% |
决策流程示意
graph TD
A[采集QPS/错误率/路径标记] --> B{QPS ≥ 1000?}
B -- 是 --> C{错误率 < 0.5%?}
B -- 否 --> D{QPS > 200?}
C -- 是 --> E[关键路径全采样]
C -- 否 --> F[降级至核心采样]
D -- 是 --> F
D -- 否 --> G[基础均匀采样]
第三章:Loki日志聚合体系构建与结构化查询
3.1 Loki轻量级日志架构对比分析:为何放弃ELK,选择Prometheus生态原生日志方案
核心设计哲学差异
ELK(Elasticsearch + Logstash + Kibana)以全文索引与复杂查询见长,但需为每条日志建立倒排索引,内存与磁盘开销高;Loki则采用标签索引 + 压缩日志流模式,仅索引元数据(如 job="api", env="prod"),日志内容以紧凑的 chunks 存储于对象存储中。
资源消耗对比(单节点 8C16G 环境)
| 方案 | 内存占用 | 磁盘 IO(写入) | 启动时间 |
|---|---|---|---|
| ELK | ~4.2 GB | 高(索引+flush) | >90s |
| Loki | ~1.1 GB | 极低(顺序写) |
数据同步机制
Loki 通过 promtail 采集日志,其配置片段如下:
# promtail-config.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: kubernetes-pods
pipeline_stages:
- docker: {} # 自动解析 Docker 日志时间戳与容器ID
- labels:
job: # 提取为标签,用于索引(非日志体)
value: kubernetes-pods
该配置使 promtail 将 Kubernetes Pod 日志按 pod_name、namespace 等自动打标,避免日志内容被索引,大幅降低存储成本。docker: {} 阶段确保时间戳对齐 Prometheus 时间序列语义,实现与 Metrics、Traces 的天然时间关联。
graph TD
A[应用容器 stdout] --> B[promtail]
B -->|HTTP POST /push| C[Loki ingester]
C --> D[内存 chunk 缓存]
D -->|定期 flush| E[S3/MinIO 对象存储]
C --> F[querier 索引服务]
F -->|按 label 查询| G[返回压缩日志流]
3.2 Go应用日志标准化输出:zerolog/logrus对接Loki的Pipeline配置与Label最佳实践
日志结构化与Loki兼容性设计
Loki不索引日志内容,仅基于标签(labels)做高效路由与查询。因此,Go应用需将关键上下文(如service_name、env、trace_id)注入结构化日志字段,并映射为Loki label,避免__line__中冗余携带。
标签最佳实践清单
- ✅ 必选标签:
job="go-app"、env="prod"、service="auth-api"(低基数、高区分度) - ⚠️ 禁用标签:
request_id(高基数,易导致label爆炸)、message(应留在日志行内) - 🔄 动态注入:通过
zerolog.GlobalLevel()+log.With().Str("trace_id", span.SpanContext().TraceID().String())
Loki Pipeline 配置示例(Promtail)
scrape_configs:
- job_name: go-app-zerolog
static_configs:
- targets: [localhost]
labels:
job: go-app
env: staging
service: payment
pipeline_stages:
- json: # 解析 zerolog 的 JSON 行
expressions:
level: level
trace_id: trace_id
service: service
- labels: # 提取为 Loki label(非日志内容)
trace_id:
service:
此配置将JSON日志中的
trace_id和service字段提升为Loki label,实现按链路追踪ID快速过滤。json.expressions确保字段存在性,缺失时设为空字符串,避免pipeline中断。
Label Cardinality 对比表
| Label 键名 | 基数特征 | 是否推荐 | 原因 |
|---|---|---|---|
env |
极低 | ✅ | 仅 dev/staging/prod |
http_status |
中 | ⚠️ | 若含全部HTTP码(1xx~5xx),建议聚合为 status_class="5xx" |
user_id |
极高 | ❌ | 单用户日志量激增,触发tenant limit |
数据流向图
graph TD
A[Go App zerolog] -->|JSON over stdout| B[Promtail]
B --> C{Pipeline Stages}
C --> D[json: extract fields]
C --> E[labels: promote to Loki labels]
C --> F[drop: filter debug logs in prod]
E --> G[Loki TSDB]
3.3 LogQL高级查询实战:从错误聚类、TraceID反查到多租户日志隔离
错误聚类:按异常模式聚合
使用 | pattern 提取结构化字段,再结合 | __error__ = "true" 与 group by 实现高频错误归因:
{job="apiserver"} |~ `(?P<code>\d{3})\s+(?P<msg>.*?error.*?)\s+`
| __error__ = "true"
| group by (code, msg) (count_over_time({job="apiserver"}[1h]))
逻辑说明:
|~执行正则匹配提取code和msg;group by按错误码与消息片段聚合;count_over_time统计每小时出现频次,支撑根因排序。
TraceID反查全链路日志
通过唯一 trace_id 关联服务网格日志:
{job=~"service-.*"} | json | trace_id == "0192a3b4c5d6e7f8" | line_format "{{.level}} {{.msg}}"
参数说明:
json自动解析 JSON 日志;==精确匹配分布式追踪 ID;line_format定制输出便于人工研判。
多租户日志隔离策略
| 租户标识方式 | 查询示例 | 隔离粒度 |
|---|---|---|
| label(推荐) | {tenant="acme", job="backend"} |
原生、高效 |
| 日志字段 | {job="backend"} | json | tenant=="acme" |
解析开销高 |
graph TD
A[原始日志流] --> B{按tenant label路由}
B --> C[acme租户索引]
B --> D[contoso租户索引]
B --> E[其他租户索引]
第四章:Tempo分布式追踪落地与链路分析闭环
4.1 Tempo后端存储选型与部署模式:单机MinIO vs 多租户Cassandra集群对比
Tempo 的后端存储直接影响查询延迟、多租户隔离性与水平扩展能力。MinIO 适合开发/测试场景,而 Cassandra 集群支撑生产级多租户高吞吐追踪写入。
存储特性对比
| 维度 | MinIO(单机) | Cassandra(多租户集群) |
|---|---|---|
| 数据模型 | 对象存储(key: traceID) | 宽列存储(按 tenant + timestamp 分区) |
| 租户隔离 | 依赖路径前缀(tenant-a/) |
原生 keyspace 或 table 级隔离 |
| 查询性能(10M traces) | ~800ms(冷读) | ~120ms(索引加速+本地分区) |
MinIO 部署示例(docker-compose)
services:
minio:
image: quay.io/minio/minio
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: tempo
MINIO_ROOT_PASSWORD: changeme
volumes:
- ./minio-data:/data
该配置启用内置控制台,/data 持久化路径需绑定宿主机;MINIO_ROOT_* 用于 Tempo 的 s3 backend 认证,对应 Tempo 配置中 s3.endpoint 与 s3.bucket。
数据同步机制
graph TD A[Tempo Distributor] –>|gRPC| B[Ingester] B –>|S3 multipart upload| C[MinIO] B –>|CQL batch insert| D[Cassandra] C & D –> E[Querier 查询聚合]
MinIO 依赖对象最终一致性,Cassandra 提供强一致轻量索引更新。
4.2 Go微服务间Span关联:HTTP Header透传、gRPC Metadata注入与Baggage扩展实践
在分布式追踪中,跨服务的 Span 关联依赖上下文传播。Go 生态中主流方案需适配不同通信协议。
HTTP Header 透传(基于 http.Header)
func injectHTTP(ctx context.Context, req *http.Request) {
carrier := propagation.HeaderCarrier(req.Header)
otel.GetTextMapPropagator().Inject(ctx, carrier)
}
逻辑分析:HeaderCarrier 将 ctx 中的 traceID、spanID、traceflags 等以 traceparent/tracestate 格式写入请求头;Inject 调用默认 W3C propagator,确保兼容性。
gRPC Metadata 注入
md := metadata.MD{}
md = metadata.AppendToOutgoingContext(ctx, "traceparent", "00-123...-01-01")
参数说明:traceparent 值遵循 W3C Trace Context 规范,含版本、trace-id、span-id、trace-flags。
Baggage 扩展能力对比
| 场景 | HTTP 支持 | gRPC 支持 | 传输开销 |
|---|---|---|---|
| traceparent | ✅ | ✅ | 极低 |
| baggage | ✅ (baggage header) |
✅ (baggage key) |
可控(键值对) |
graph TD
A[Client Span] -->|Inject traceparent + baggage| B[Service A]
B -->|Extract & Inject| C[Service B]
C -->|Propagate baggage| D[DB/Cache]
4.3 追踪数据富化(Enrichment):将Loki日志、Prometheus指标与Tempo Trace三者ID对齐
实现可观测性“黄金三角”协同分析的核心在于统一上下文——trace_id、span_id、cluster、pod 等标识必须跨系统可关联。
数据同步机制
Loki 通过 | json | __error__ == "" | traceID != "" 提取日志中的 traceID 字段;Prometheus 在指标标签中注入 trace_id(需配合 OpenTelemetry Collector 的 resource_to_metric processor);Tempo 原生支持 trace_id 索引。
关键配置示例(OTel Collector)
processors:
resource_to_metric:
attributes:
- key: trace_id
from_attribute: trace_id # 从 span.resource_attributes 注入
该配置将 trace 上下文提升为指标标签,使 rate(http_requests_total{trace_id="abc123"}[5m]) 可直接关联调用链。
对齐效果对比
| 数据源 | 原生ID字段 | 富化后关键标签 |
|---|---|---|
| Tempo | trace_id |
service.name, http.status_code |
| Loki | traceID (log line) |
trace_id, span_id, pod_name |
| Prometheus | — | trace_id, job, instance |
graph TD
A[应用埋点] -->|OTLP| B(Tempo Trace)
A -->|JSON log + traceID| C[Loki 日志]
A -->|Metrics + trace_id label| D[Prometheus]
B & C & D --> E[统一 trace_id 查询]
4.4 基于Jaeger UI与Grafana Explore的链路诊断工作流:从慢请求定位到根因下钻
慢请求初筛:Jaeger UI 时间轴过滤
在 Jaeger UI 中,通过 service=orders + duration>500ms 筛选慢调用,点击高亮 Span 进入详情页,重点关注 http.status_code、error=true 标签及子 Span 的 db.statement。
根因下钻:Grafana Explore 联动查询
切换至 Grafana Explore,选择 Tempo 数据源,执行以下查询:
{job="tempo"} | json | duration > 500 | unpack | status_code != "200"
此 LogQL 查询解析 Tempo 注入的结构化日志,
| json提取嵌套字段,unpack展开 traceID 关联的指标上下文,status_code != "200"快速聚焦失败分支。参数duration > 500与 Jaeger 筛选阈值对齐,确保链路一致性。
关键指标比对表
| 维度 | Jaeger UI | Grafana Explore |
|---|---|---|
| 延迟定位 | 可视化时间轴+瀑布图 | LogQL 聚合统计 |
| 上下文关联 | 仅 Span 元数据 | 日志+指标+traceID 联查 |
graph TD
A[Jaeger UI 慢请求筛选] --> B[复制 traceID]
B --> C[Grafana Explore 粘贴 traceID]
C --> D[展开 span 日志与 Prometheus 指标]
D --> E[定位 DB 连接池耗尽异常]
第五章:第4天全链路追踪交付成果复盘与生产就绪检查清单
交付成果实物清单核验
已完成部署的 Jaeger Collector v1.32.0(Docker 镜像 SHA256: a7f9c1e...)运行于 Kubernetes 1.26 集群 prod-tracing-ns 命名空间,Pod 状态为 Running,资源限制设置为 cpu: 1000m, memory: 2Gi。OpenTelemetry SDK 已集成至全部 8 个核心微服务(含 order-service、payment-gateway、inventory-api),Java 应用使用 -javaagent:/otel/opentelemetry-javaagent-all.jar 启动参数,Go 服务通过 go.opentelemetry.io/otel/sdk/trace 手动注入。所有服务均配置了 service.name、environment=prod、deployment.version=v2.4.1 语义约定标签。
关键链路端到端验证结果
选取「用户下单→库存扣减→支付回调→订单状态更新」主链路进行压测复现(JMeter 并发 200 QPS,持续 15 分钟),共采集有效 Span 数 12,847 条,平均 trace 时长 382ms(P95=612ms),无 Span 丢失(Jaeger UI 显示 trace_id 连续性 100%)。以下为典型异常链路片段:
{
"traceID": "d7b5a2f9e1c844a2b3f0e7d1a9c8b2f1",
"spanID": "a1b2c3d4e5f67890",
"serviceName": "payment-gateway",
"operationName": "POST /v1/callback",
"statusCode": 500,
"error": true,
"attributes": {
"http.status_code": 500,
"rpc.system": "http",
"db.statement": "UPDATE payments SET status='FAILED' WHERE order_id=?"
}
}
生产就绪风险项闭环确认
| 检查项 | 当前状态 | 解决措施 | 验证时间 |
|---|---|---|---|
| TLS 加密传输(Collector ↔ Agent) | ✅ 已启用 mTLS | 使用 cert-manager 自动轮换证书 | 2024-06-12 14:30 |
| Trace 数据采样率动态调整 | ✅ 已配置 Adaptive Sampling | 基于 error rate > 1% 自动升至 100% | 2024-06-12 16:15 |
| 日志与 Trace ID 关联(Log Correlation) | ⚠️ 待优化 | 在 Logback 中注入 MDC trace_id 字段(已合并 PR #442) |
2024-06-13 09:00 |
核心告警规则有效性验证
Prometheus 已部署以下告警规则并完成触发测试:
TracingSpanLossRate > 0.5% for 5m→ 触发 Slack 告警(模拟网络抖动后成功接收)JaegerQueryLatencySeconds > 2s→ 自动扩容 Query 组件(HPA 规则生效,副本数从 2→4)
架构拓扑完整性校验
graph LR
A[Frontend Vue App] -->|HTTP + B3| B[API Gateway]
B -->|OTLP/gRPC| C[OpenTelemetry Collector]
C --> D[Jaeger Backend]
C --> E[Elasticsearch 8.11]
D --> F[Jaeger UI]
E --> G[Kibana Trace Dashboard]
subgraph Production Cluster
C; D; E
end
安全合规专项检查
- 所有 trace 数据在传输层(gRPC over TLS 1.3)及存储层(Elasticsearch 启用 Field-Level Encryption)均满足 PCI-DSS 4.1 要求;
- 敏感字段
credit_card_number、id_card已在 OTel Processor 中配置attributes/filter规则自动脱敏(正则^card.*$|^id.*$); - 审计日志显示,过去 72 小时内无未授权访问
/api/traces接口记录(Nginx access log + OpenSearch SIEM 规则匹配)。
团队能力移交确认
SRE 团队已通过实操考核:独立完成一次 trace 查询(按 http.url 和 error=true 过滤)、定位 inventory-api 的 Redis 连接池耗尽问题(Span 标签显示 redis.command=BLPOP, duration_ms>5000)、执行 otelcol-contrib --config=/etc/otel/config.yaml --dry-run 配置校验。运维手册 V1.2 已同步至 Confluence 文档库(链接:/wiki/tracing-prod-runbook)。
