恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

从零自建全链路可观测性:OTel+Prometheus+Tempo+Loki+Grafana实战

  • 首页
  • 资讯中心
  • /
  • 从零自建全链路可观测性:OTel+Prometheus+Tempo+Loki+Grafana实战

相关资讯

2026 RFID盘点任务怎么编排:从创建到复核的完整流程 2026/10/11 4:32:01
52pojie 的 Windows 系统编程帖:枚举进程、读指标、查连接为什么都要调用两次 2026/10/11 4:27:00
启动Flink报错:[ERROR] Could not get JVM parameters properly. 2026/10/11 4:27:00

最新资讯

通达信指标黄金分割线分析技术支撑压力线
AI Agent接入桌面自动化:让大模型看屏幕点鼠标完成翻译
富途牛牛指标期货支撑压力线指标
PCA人脸识别原理与实战:从特征脸到门禁部署
文华指标公式大全期货波浪线倚天财经指标
OBS美颜设置教程:通过虚拟摄像头实现直播瘦脸与磨皮

今日推荐

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

从零自建全链路可观测性:OTel+Prometheus+Tempo+Loki+Grafana实战

发布时间:2026/10/11 4:32:01
从零自建全链路可观测性:OTel+Prometheus+Tempo+Loki+Grafana实战 凌晨两点四十线上告警把整个值班群炸醒了。订单服务超时率突然飙到百分之十几我登录服务器翻业务日志一堆context deadline exceeded堆栈看不出是哪个下游拖垮的打开监控面板只看到订单服务自身 CPU 冲到 85%却完全看不到它对支付、库存、积分这三个下游的调用耗时分布。同一场事故日志、指标、链路三个视角各自为战我花了将近两个小时才把线索拼出完整轮廓。那次之后我下定决心把日志、指标、链路追踪真正打通而不是继续维持每个系统各存各的状态。这篇文章就是我们从零落地全链路可观测性的完整过程技术栈是标题里那套组合OpenTelemetry 负责统一埋点和数据采集Prometheus 存指标Tempo 存链路Loki 存日志最后全部汇入 Grafana 一个入口查询。文章覆盖架构选型、埋点接入、组件配置、告警规则、排障工作流以及从测试环境走向生产时最容易翻车的几个细节。适合正在选型或已经决定自建可观测体系、但还缺一张完整施工图的团队参考。1. 为什么要自己搭一套可观测性体系从能跑到能查1.1 监控碎片化带来的真实代价大多数团队不是没有监控而是监控碎了一地。业务团队看日志运维团队看指标后端想追链路结果发现只有少数几个核心服务埋了点。平时各看各的都能糊弄过去一旦出现跨服务调用超时、数据不一致这类问题传统排查方式的效率低得令人绝望。我把之前事故的排查时间拆开算过一笔账真正定位到根因只花了二十分钟但把日志里的报错、面板上的指标、数据库慢查询三条线索关联起来消耗了一个多小时。日志只有一个异常堆栈没有 trace ID没有上游参数上下文指标是聚合后的平均值根本看不到具体是哪个用户的哪次请求出了问题链路追踪倒是能看到调用关系但只覆盖了订单服务和网关支付、库存两个环节完全是断头路。这就是典型的数据都有但连不起来。可观测性和监控的根本区别就在这里。监控回答系统现在是不是有问题可观测性要回答问题出在哪、影响谁、根因是什么。如果日志、指标、链路三个维度的数据不能互相跳转、互相印证那本质上还是多个独立监控系统的堆叠不叫可观测性。1.2 全链路到底链的是什么全链路可观测性里的全链路第一层含义是请求链路也就是一次用户请求从网关进入经过各个微服务到最后访问数据库或第三方接口的完整路径第二层含义是数据链路指同一个请求在日志、指标、链路三个数据形态中都能被识别出来并且能通过统一标识互相关联。展开说就是三条数据线指标Metrics系统健康度的体温计。它是周期性聚合的数值适合回答服务是否健康、容量是否够、是否需要告警。但它天然丢失了单个请求的细节只能看到规律看不到个体。日志Logs事件明细的记录本。适合回答具体发生了什么异常、错误信息是什么。但它没有结构化的调用关系几万条日志里找一条相关记录非常吃力。链路追踪Traces一次请求的行车记录仪。记录请求经过的每个节点、每次调用的耗时和状态适合回答这个请求为什么慢、卡在哪个环节。但它不适合做全局聚合告警因为数据量太大、成本太高。有个比较贴切的比喻指标是心电图告诉你心脏跳动是否规律日志是病历本记录每次就诊的详细情况链路追踪是问诊过程把症状和检查结果串成一条完整的故事线。三者缺一个医生都可能误诊。这也是我们在技术选型时不打算省任何一块的原因。1.3 为什么选这套开源组合而不是商业方案既然要打通三条数据线最省事的路径其实是采购商业可观测平台开箱即用啥都不用操心。我们当时也认真评估过这条路最终放弃的原因有三个。第一是成本。商业平台按数据量计费尤其是链路追踪随着业务流量上涨费用增长得非常快。如果采样率调低节省了成本却丢了排障能力陷入两难。第二是数据主权。业务日志和调用链数据中往往包含客户信息和内部敏感数据放到第三方平台需要额外的合规评估和脱敏改造。第三是定制化能力。商业平台的黑盒部分太多告警策略、面板布局、数据保留策略都只能在平台提供的框架里玩想深度定制很痛苦。于是我们把目光投向 OpenTelemetry Prometheus Grafana Loki/Tempo 这套开源方案。它们的优势很直白组件之间存在原生协同Grafana 原生支持 Loki 和 Tempo 的数据源查询与跳转整个链路数据都留存在自己的基础设施里成本可控、安全性可把控每个组件都是事实标准级别的社区生态网上踩坑经验一抓一大把团队学习曲线相对平缓。对比维度商业可观测平台开源自建组合初期接入速度快控制台点几下就好慢需要自己部署配置数据量成本按写入量/查询量计费增长快只花存储和机器钱可控数据私密性数据出域需合规评估完全内网数据不出边界定制深度受平台限制全部开源想改就改运维负担平台方负责自己维护需要一定工程能力当然这套方案对团队有一定的运维要求至少要有人能看懂 YAML、会部署容器服务。如果团队完全没有基础设施能力商业方案依然是合理选择。但如果你正在读这篇文章大概率是想自己掌控整套体系的人那下面的内容应该对你有用。2. 整体架构与选型思路四个组件如何各司其职2.1 一条请求从产生到展示的完整数据流先给一张整体图景。这里我用文字描述数据流你可以边看边在脑子里画线应用服务启动时接入 OpenTelemetry SDKSDK 会自动或手动埋点生成链路 Span 和指标数据。这些数据通过 OTLP 协议发送给本地运行的 OpenTelemetry Collector。Collector 是一个数据路由器它收到数据后按配置分发链路数据转发给 Tempo指标数据转发给 Prometheus日志数据则通常由 Promtail 或 Collector 的日志接收器采集后转发给 Loki。Grafana 位于最上层通过数据源插件分别连接 Prometheus、Loki、Tempo在同一个界面上提供指标查询、日志检索、链路追溯三种能力。这套流程的关键点在于应用只和 OpenTelemetry SDK 打交道不需要感知下游存储的具体是什么。就算以后想把指标换成一个兼容 Prometheus 协议的其他存储应用代码一行都不用改只改 Collector 的路由配置即可。这就是引入 OpenTelemetry 作为统一入口的最大价值。2.2 组件分工与选型理由先看一张分工表后面再逐个解释关键选型逻辑组件数据类型查询方式典型职责OpenTelemetry统一埋点 API / 数据协议OTLP生成 Span、指标、日志负责跨服务传播上下文Prometheus指标时序数据PromQL指标聚合、告警计算、长期存储Grafana可视化面板面板/Explore统一查询入口关联所有数据源Loki日志LogQL日志集中存储与全文检索Tempo链路追踪数据TraceQL按 trace ID 或条件查询调用链详情Prometheus 在指标领域几乎不需要解释它是云原生监控的事实标准。选它的理由很朴素生态最成熟Exporter 资源丰富告警规则写法团队熟悉Loki 的日志指标也可以直接通过 LogQL 暴露给 Prometheus 做告警。Loki 和 Elasticsearch 的选择是很多人纠结的地方。我们对比过两者的运维成本ES 需要维护集群、管理分片、处理索引生命周期数据量大之后还要单独规划冷热节点Loki 完全依赖标签索引加对象存储写入路径是压缩后落盘不需要建全文索引几百 GB 的日志量跑在一台普通机器上都不费力。对于以检索排障为主、不需要复杂全文分析的中小型团队来说Loki 的性价比优势太明显了。代价是 LogQL 的查询语法需要重新学但它的设计思路和 PromQL 很像工程师上手速度很快。Tempo 选型的关键点是后端存储。很多链路系统强制依赖 Elasticsearch 或专用数据库存储成本非常高Tempo 可以直接把 trace 数据写入对象存储比如 MinIO 或者云上的对象存储服务成本是 ES 的几分之一。而且 Grafana 对 Tempo 的集成深度是其他链路后端比不了的日志里的 trace ID 可以直接一键跳转指标里的 exemplar 也可以直接点进链路详情。2.3 部署形态本地联调与生产集群分开规划组件选型定了接下来是部署形态。我们分了两个阶段本地和测试环境直接用 Docker Compose 拉起一整套让各服务联调时不依赖远端环境。Compose 里包含 Prometheus、Grafana、Loki、Tempo、MinIO作为 Tempo 和 Loki 的存储后端再加一个模拟的 OTel Collector。全部服务加起来内存占用大约 5~6GB一台开发机完全跑得动。这样每个开发者都能在本地复现日志跳链路、指标跳链路的完整体验。生产环境则基于 Kubernetes 部署。Prometheus 用现成的监控栈方式部署组件包括 node_exporter 采集节点指标、kube-state-metrics 采集资源对象状态、blackbox_exporter 做 HTTP 探活Loki 和 Tempo 使用官方 Helm Chart存储指向对象存储Grafana 用官方 Helm Chart 部署并挂载预置的 Dashboard 和数据源配置。这里有个经验不要一开始就把所有组件都追求高可用。可观测性体系本身的可用性要求低于业务系统先保证数据能采、能查、能告警等运行稳定了再逐步给 Prometheus 做双副本、给 Grafana 做多副本。一上来就上 Thanos 之类的扩展方案只会让排查问题时的复杂度翻倍。3. OpenTelemetry 接入一次请求从网关到数据库的完整埋点3.1 从自动埋点开始先让链路看得见OpenTelemetry 的接入路径分成自动埋点和手动埋点两类。自动埋点通过语言相关的 Agent 或 SDK 钩子在不修改业务代码的情况下给常见框架生成 Span。以 Java 服务为例只需要在启动命令里加上 javaagent 参数java -javaagent:/opt/otel/opentelemetry-javaagent.jar \ -Dotel.service.nameorder-service \ -Dotel.exporter.otlp.endpointhttp://otel-collector:4317 \ -Dotel.traces.samplerparentbased_traceidratio \ -Dotel.traces.sampler.arg0.2 \ -jar app.jarJava Agent 会自动给 Spring MVC、数据库连接池、HTTP Client、消息队列客户端等组件创建 Span。这种方式的优点是接入成本极低一两天就能让所有 Java 服务都有链路数据缺点是业务语义缺失比如创建订单调用支付这类业务动作在链路里只会显示成几个底层 HTTP Span看不出真正意图。Go 的接入就比 Java 麻烦一点因为 Go 没有统一的字节码增强机制只能通过 SDK 手动埋点或者依赖框架的集成中间件。一个最简单的 Go 服务初始化示例package main import ( context go.opentelemetry.io/otel go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc go.opentelemetry.io/otel/sdk/resource sdktrace go.opentelemetry.io/otel/sdk/trace semconv go.opentelemetry.io/otel/semconv/v1.26.0 ) func initTracer() (*sdktrace.TracerProvider, error) { ctx : context.Background() exporter, err : otlptracegrpc.New(ctx, otlptracegrpc.WithEndpoint(otel-collector:4317), otlptracegrpc.WithInsecure(), ) if err ! nil { return nil, err } tp : sdktrace.NewTracerProvider( sdktrace.WithBatcher(exporter), sdktrace.WithResource(resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceName(order-service), )), ) otel.SetTracerProvider(tp) return tp, nil }经验建议技术债重的老项目先上自动埋点打通全链路新服务或核心服务从一开始就规划手动埋点补足业务语义。两条腿走路谁也别偏废。3.2 跨服务传播trace 是怎么串起来的链路追踪的灵魂在于上下文传播。一个 trace 由全局唯一的trace_id标识其中包含多个span_id各自对应一次调用服务 A 调用服务 B 时必须把当前 trace 的上下文信息传递给服务 B服务 B 创建的 Span 才能挂到同一条 trace 上。OpenTelemetry 采用 W3C Trace Context 标准通过 HTTP 头traceparent传递信息。这个头的格式是版本号-trace_id-span_id-采样标记举个例子traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01OpenTelemetry 的自动埋点已经帮我们处理了绝大多数 HTTP 场景的透传真正容易漏的是消息队列场景。比如订单服务把支付结果通知发到 Kafka如果生产者没有把上下文塞进消息 header消费方的处理 Span 就会变成一条新的 trace整条链路在消息边界处断掉。排查这个问题的方法很简单查看消费方日志里的 trace ID 是否和生产方一致如果不一致基本就是消息头没传。消息队列场景需要在生产端手动注入上下文消费者端提取上下文再创建 Span。Kafka 客户端在 OpenTelemetry 生态里有专门的 instrumentation 库Java 和 Go 都有对应实现接上之后它会自动处理消息 header 的注入与提取这是我们后来接入时被验证最省心的方案。3.3 采样策略成本控制的第一道闸门链路数据是三个信号里最烧钱的。一次请求可能产生几十个 Span每个 Span 包含资源属性和时间戳在高峰期全量采样会让 Tempo 的存储增长失控。因此上线前必须定好采样策略。默认的采样是parentbased_traceidratio含义是根据 trace ID 的哈希值按比例采样子 Span 跟随父 Span 决策这样能保证一条 trace 要么完整保留、要么完全丢弃。我们在测试环境用 100% 采样生产环境先用 10%后续根据日活和存储情况调整。如果业务对排障要求更高比如要保证所有错误请求都能被保留就需要使用尾部采样Tail Sampling。它的做法是Collector 先缓冲一段时间内的所有 Span等一个 trace 的全部 Span 到达后由采样决策器统一决定是否保留。可以配置成包含错误状态的 Span 必须保留、P99 以上耗时的慢链路保留、其余按比例采样。重要提示尾部采样会显著增加 Collector 的内存消耗因为要缓冲数据等待决策决策窗口越长消耗越大。我们的配置是等待 30 秒错误链路和慢链路全留其余按 10% 保留单 Collector 的内存从 2GB 涨到了 6GB 左右。3.4 手动埋点业务语义才是链路追踪的灵魂自动埋点解决有没有链路的问题手动埋点解决链路能不能看懂的问题。我个人的原则是任何你在业务代码里写日志、打点、记录异常的地方都值得考虑加一个自定义 Span。举个例子订单创建流程涉及库存扣减、优惠券核销、支付单生成三个子步骤。自动埋点只能看到对三个服务的 HTTP 调用但通过手动埋点可以在主流程外面套一个名为create_order的业务 Span给这个 Span 加上订单号、用户 ID、商品数量等业务属性这样不光是排障连业务报表分析都能复用这些数据。ctx, span : tracer.Start(ctx, create_order, trace.WithAttributes( attribute.String(order.id, orderId), attribute.String(user.id, userId), attribute.Int(item.count, itemCount), ), ) defer span.End() if err : deductInventory(ctx); err ! nil { span.RecordError(err) span.SetStatus(codes.Error, inventory deduction failed) return err }span.RecordError和span.SetStatus是容易被忽略的两个方法。前者把异常堆栈记录到 Span 事件中后者标记 Span 为错误状态两者都会成为尾部采样保留链路的依据。而且这些信息会展示在 Grafana 的 Span 详情里比单独去翻日志效率高得多。手动埋点还有一个额外好处它能促进团队梳理业务流程。埋点的过程其实就是给系统画了一张动态调用图很多隐藏的循环依赖、多余的中间层调用都是在埋点时被暴露出来的。4. Prometheus 指标接入与告警先对齐指标再谈面板4.1 指标从哪来三路输入一个出口链路数据打通之后下一步是指标体系。我们的指标来源分三类最终统一汇总到 Prometheus争取所有告警都从这一个数据源出。第一类是应用业务指标。OpenTelemetry SDK 支持生成 Counter、Histogram 等指标类型通过 OTLP 发送给 Collector再由 Collector 的 Prometheus remote write 出口转发。我们在业务服务里定义了请求总量、错误量、处理耗时直方图、下游调用耗时等指标这些是 RED 监控法的数据基础。第二类是基础设施指标。每台节点上部署 node_exporter 采集 CPU、内存、磁盘 IO、网络流量Kubernetes 环境下由 kube-state-metrics 提供 Pod、Deployment、Namespace 的状态指标。这类指标不用自己写部署即得但一定要在告警规则里覆盖到否则半夜磁盘写满往往比业务故障更早拖垮系统。第三类是黑盒探测指标。blackbox_exporter 从外部视角定时探测各服务的 HTTP 健康检查地址可以配置probe_success和probe_duration_seconds这两个核心指标。黑盒探测的价值在于即使服务进程还活着只要响应超时外部探针能立刻发现并告警比内部指标更早反映真实用户体验。三类指标在 Prometheus 内部共存全部通过 PromQL 统一查询和计算这也是我们把 Prometheus 放在核心位置的原因它不仅是存储还是告警规则的计算引擎。4.2 prometheus.yml 里最容易忽略的细节初次上手 Prometheus 时很多人从网上抄一份配置就跑起来结果丢指标、丢数据也没察觉。下面这份是我们在生产环境压实过的精简配置注释标出了关键点global: scrape_interval: 15s evaluation_interval: 15s rule_files: - /etc/prometheus/rules/*.yml remote_write: - url: http://otel-collector:9090/api/v1/otlp # 只有需要把应用指标转发给类似 Prometheus 的存储时才配置 scrape_configs: - job_name: node static_configs: - targets: [node-exporter:9100] - job_name: blackbox metrics_path: /probe params: module: [http_2xx] static_configs: - targets: [https://gateway.example.com/healthz] relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance两个细节值得注意。第一scrape_interval和evaluation_interval建议保持一致否则会出现数据每 15 秒刷新一次、但告警规则每 30 秒才评估一次的错位感延迟类问题会晚一两轮才能触发告警。第二blackbox 探针的relabel_configs必须配置否则所有探测目标在指标里显示的instance标签都是同一个值面板上完全无法区分探测的是哪个服务。在 Kubernetes 环境下我们推荐放弃手动写static_configs改用 ServiceMonitor 机制。它可以自动发现带指定标签的服务并拉取指标配合 Prometheus Operator 使用后新增一个服务只需要给 Service 打几个标签Prometheus 就能自动接入指标不用任何人去改配置文件。4.3 告警规则少而准比多而全重要告警配置我踩过最大的坑是告警疲劳。第一版规则我们写了将近 40 条结果一天能收到几百条消息大部分是误报和瞬时段抖动真正重要的告警反而被淹没在通知流里。后来痛定思痛把规则砍到十几个核心项。现在保留的告警分三类可用性类服务探活失败持续 1 分钟、实例宕机性能类错误率超过阈值、P95 延迟超限、CPU/内存持续高位容量类磁盘使用率超过 85%、日志写入量异常暴增一条比较典型的规则长这样groups: - name: order-service rules: - alert: OrderServiceHighErrorRate expr: | sum(rate(http_server_request_errors_total{serviceorder-service}[5m])) / sum(rate(http_server_requests_total{serviceorder-service}[5m])) 0.05 for: 3m labels: severity: critical annotations: summary: 订单服务错误率超过5% description: 订单服务最近5分钟错误率 {{ $value | humanizePercentage }}for: 3m这个字段非常关键。它表示指标需要连续 3 分钟超过阈值才真正触发告警能过滤掉绝大部分瞬时抖动。阈值怎么定不要凭感觉拍脑袋去 Grafana 上拉历史数据看基线业务正常时错误率是 0.1%那阈值定 1% 已经算激进如果正常就有 3% 的错误率把阈值定 5% 只是自欺欺人。建议先把面板跑两周拿到真实基线再设告警阈值。告警分级和通知渠道同样重要。我们目前分两级warning级别发到团队群的机器人提醒关注critical级别才走电话或短信抢占式的通知。这样既能保证重要问题不遗漏又不会让所有人对所有消息都麻木。4.4 高基数与标签爆炸Prometheus 的隐形杀手Prometheus 所有指标都靠标签组合定位但标签组合的数量是有上限的。一个常见错误是把用户 ID、订单 ID 这类高基数值放进指标标签比如给某个业务指标打上user_id标签。假设一天有十万活跃用户这个指标的基数瞬间增加十万倍Prometheus 内存会随之暴涨最终把整个实例拖垮。数据量估算方式很简单一个指标序列在内存中大约占 1~2 字节不含标签名仅样本值序列数量等于指标名 × 每个标签值的笛卡尔积。如果有 1000 个指标、每个指标有 10 万个标签组合那就是 1 亿条序列再大的机器也扛不住。判断某个标签是否适合放指标里标准很直接它是否符合低基数特征比如服务名、实例 IP、接口路径、状态码这些取值范围很小适合做标签凡是取值范围会随时间无限增长的比如用户 ID、订单号、IP 地址都不适合。那想查询某个用户的请求量怎么办去日志里查或者用 trace 的属性查别为难 Prometheus。5. Grafana Loki Tempo三合一的排障工作流5.1 把四个数据源接进 Grafana组件都跑起来之后最后一步是把它们纳入 Grafana 统一管理。Grafana 的数据源配置支持两种方式界面上手工添加或通过 provisioning 配置文件的声明式管理。生产环境建议用 provisioning这样数据源配置能随版本管理新环境拉起后不用人工点界面。一份标准的 provisioning 配置长这样apiVersion: 1 datasources: - name: Prometheus type: prometheus url: http://prometheus:9090 isDefault: true - name: Loki type: loki url: http://loki:3100 - name: Tempo type: tempo url: http://tempo:3200 jsonData: httpMethod: POST配置完成后建议先在 Explore 页面分别验证四个数据源能否查到数据再开始搭面板。很多团队一上来就忙着画漂亮的 Dashboard结果数据源本身连接有问题面板一团糟最后还以为是组件配置错了。5.2 Loki 不是 Elasticsearch日志索引思路完全不同Loki 的日志检索方式和 ES 有本质区别。ES 会对日志内容建全文倒排索引Loki 则是对日志流的标签建索引日志内容本身不索引查询时按标签筛选后在匹配的日志块里做扫描。这决定了 LogQL 的写法习惯和 ES 完全不同。举个例子我们要查订单服务最近 15 分钟所有包含 timeout 的日志LogQL 是这样写的{serviceorder-service} | timeout | trace_id4bf92f3577b34da6a3ce929d0e0e4736前面花括号里是标签筛选器后面用管道操作符逐级过滤内容。|表示包含!~表示正则排除还可以配合| json把 JSON 结构化的日志字段提取出来做条件过滤。为了发挥 Loki 的优势强烈建议业务日志统一输出为 JSON 格式并固定包含service、trace_id、span_id、level、message五个基础字段。结构化日志配合 LogQL 的 JSON 解析器能做到秒级定位某次请求在某个服务上的全部日志这在故障排查时非常高效。日志采集链路我们用的是 Promtail它直接部署在每个节点上读取容器 stdout 文件并打上标签转发到 Loki。这里有个性能提醒Promtail 默认会把每行日志都做一次 hash 用于内容寻址如果单机日志量非常大需要适当调大batchsize和batchwait避免批量发送过于频繁把 Loki 的写入压力打上去。5.3 从日志跳到 Trace、从指标跳到 Trace全链路最有价值的体验可观测性体系建完之后最有价值的体验就是排障时不再需要在多个系统之间来回切换。我们总结了一套标准的排障操作流看到服务错误率告警后先到 Grafana 面板看整体趋势确认异常时间段。然后打开 Loki按{serviceorder-service} | levelerror筛选该时间段的错误日志在日志里找到trace_id字段。点击 trace IDGrafana 自动跳转到 Tempo 的链路详情页完整展示这次请求从网关到下游每个服务的调用耗时和状态。顺着链路能看到是支付服务超时还是数据库查询慢再点进对应 Span 查看当时的参数和异常信息根因基本就浮出水面了。这套流程能跑通核心依赖是日志里必须带 trace ID。我们踩过这类坑某服务确实打印了 trace ID但字段名不统一有的叫traceId、有的叫trace_id导致 Loki 里的跳转按钮时灵时不灵。后来强制约定所有服务日志统一用trace_id字段名并在上线检查清单里加了校验步骤。Prometheus 与 Tempo 的联动则通过 exemplar 机制实现。exemplar 是指标样本上附带的一个额外信息可以把 trace ID 挂到某个指标样本上。配置了 exemplar 之后在 Grafana 面板上看到某个时间点的延迟峰值可以直接点击数据点查看该时间窗口的示例链路不需要再去日志里翻 trace ID。Prometheus 侧开启 exemplar 存储需要在配置里加一行storage: exemplar: max_exemplars: 100000加上之后面板和 Explore 页面才能显示 exemplar 标记。这个功能在慢请求根因分析时特别好用指标告诉你这里慢了exemplar 帮你直接打开到底是哪条请求慢了、慢在哪一步跳转。5.4 黄金信号看板的落地版看板设计我们遵循 RED 方法也就是 Rate请求速率、Errors错误率、Duration耗时分布三维。按服务维度拆分成一行每一行包含请求量曲线体现流量变化和业务起伏错误率曲线搭配告警规则快速定位异常时段P50/P95/P99 延迟曲线三条线分开画比只画平均值有用得多平均值会把长尾掩盖掉面板右上角一定要放时间选择器这样排障时可以快速切换到出问题的时间窗口比对前后变化。为了让日志和链路联动面板的每个图表都可以加数据源链接把当前服务的名称作为变量传给 Loki 或 Tempo 的查询页面。点击图标就能带着上下文跳转比手动复制服务名再粘贴查询高效得多。一个很实用的技巧是在面板的模板变量里定义service和trace_id两个变量。统一入口页面放一个 trace ID 搜索框值班人员在接到告警电话时把日志里的 trace ID 粘进去一键跳到 Tempo 看完整链路——这比让值班人员在多个系统里翻来翻去要省太多时间。6. 从测试环境走向生产上线前必须过的几道坎6.1 数据量估算与保留周期测试环境跑通之后最容易低估的是生产环境的数据量。可观测性组件消耗的存储和带宽相当可观上线前不做容量估算第一周就可能把磁盘打爆。我们的估算思路是按保留 7 天的时序指标、30 天的日志、7 天的链路数据来计算。粗略经验值如下数据类型单 GB 估算一天的典型体量100 个服务、中低流量保留期需要的存储Prometheus 指标单样本约 1~2 字节约 2~5 GB7 天20~40 GBLoki 日志压缩后约为原始 1/5原始 50~100 GB30 天300~600 GBTempo 链路按采样率计算10% 采样下 10~20 GB7 天70~150 GB这只是非常粗略的量级实际取决于服务的请求量、Span 数量、日志冗余度。建议上线前先在测试环境跑一周统计三个组件的实际日增数据量再按增长系数放大 1.5 到 2 倍做容量规划。千万不要按看起来够用来买存储。6.2 组件自身的高可用可观测性不能成为新的单点可观测性体系刚上线时往往是单实例部署这在测试环境没问题但生产上如果 Prometheus 挂了告警系统变成摆设那就本末倒置了。我们做了两级规划。第一级Grafana、Prometheus、Loki、Tempo 都属于无状态或有状态但可恢复的组件。Prometheus 至少双副本使用 WAL 机制保证近期数据不丢Grafana 多副本加共享配置Loki 和 Tempo 的数据都在对象存储中采用多副本部署单实例挂掉不影响查询。第二级链路和日志组件必须依赖对象存储不要用本地磁盘。Loki 和 Tempo 的官方部署方式都支持配置对象存储后端比如 MinIO 或云厂商的对象存储服务。对象存储本身是托管的、几乎不会丢数据这比本地磁盘的可靠性高一个数量级。我们生产环境早期偷懒让 Loki 写本地盘结果一次节点故障丢了半天日志后来全部迁到对象存储才踏实。还要考虑采集端的容错。OpenTelemetry Collector 是数据入口如果它挂了应用侧的数据会积压在 SDK 的缓冲里。SDK 默认的导出重试和队列机制能撑几分钟但长时间故障仍会丢数据。建议 Collector 至少部署两个副本并在前面做负载均衡。6.3 性能开销可观测性不是免费的每次谈到接入 OpenTelemetry总有人问性能损耗。负责任地说自动埋点会给请求路径增加少量开销通常在 5% 以内的延迟影响和 3% 以内的 CPU 消耗对于大多数业务系统完全可接受。但在接入前还是应该做一次压测验证 SDK 的批处理配置是否合理。三个容易踩的性能坑第一SDK 的导出器默认是批处理模式不要随手改成同步导出否则每次请求都同步等待数据上传延迟会翻倍。第二不要把所有日志都打到 stdout 又全量采集到 Loki。很多服务为了排查方便把正确的业务流程也输出成 info 日志量一大Loki 的写入压力陡增。建议在日志代码中区分 debug/info/warn/errorLoki 采集端按 level 标签过滤生产只采 info 及以上。第三Collector 需要开启 gzip 压缩。OTLP 默认是 protobuf 编码不压缩的话网络带宽消耗很可观。在 Collector 的 exporter 配置里加compression: gzip带宽能省 70% 以上。6.4 权限与安全别把观测系统裸奔在公网可观测性系统存的都是内部最敏感的数据——业务日志、请求参数、链路信息比数据库本身还容易泄露信息。因此安全加固不能省。Grafana 必须放在反代后面开启认证。我们用的是 OAuth 接入企业内部的 SSO并做了角色权限普通开发只给 Viewer 权限运维和 SRE 给 Admin 权限。Prometheus、Loki、Tempo 的端口不能直接暴露到公网只允许内网或通过 Grafana 的数据源代理访问。日志脱敏也要在接入前处理。我们的做法是在应用侧统一封装日志库对手机号、身份证、token 等字段做脱敏替换后再输出避免敏感数据直接落进 Loki。这个事越早做越省事等日志量大了再回改所有服务都要跟着动返工成本很高。6.5 上线后期我们踩过的几个真实坑最后分享几个运行期真实踩过、花了时间才解决的坑希望你能绕开。坑一Collector 没有开批量压缩导致连接数爆炸。最初我们把 Collector 部署在服务端所有应用直连 OTLP 端口高峰期出现大量 TCP 连接堆积。后来在应用 SDK 侧开启 gRPC 批量和一小时级的连接复用问题消失。如果是大集群建议在每台节点上以 DaemonSet 方式跑一个 Collector 作为本地代理服务只连本机 Collector再由它统一转发能大幅减少连接数。坑二尾部采样配置不当导致内存暴涨。我们在测试环境把 tail sampling 的等待时间设成 5 分钟结果流量一大Collector 内存直接冲到 10GB。后来把决策时间缩短到 30 秒并调整了内存限制才稳定下来。记住尾部采样对 Collector 内存的压力与流量、等待时间成正比这俩参数一定要按实际流量压测后再定。坑三业务日志里没有 trace ID。这是最常见也是最隐蔽的坑。某个老服务没接入 SDK或者 SDK 上下文提取失败导致它的日志打印出来的 trace_id 是空的排障时链路跳转直接断掉。我们后来加了一个启动检查每个服务必须打印一条带 trace_id 的健康日志由脚本定期校验没有 trace ID 的服务会被标红督办整改。坑四Prometheus 规则重算开销没注意。引入大量复杂的 PromQL 计算后Prometheus 的评估时间明显变长。解决办法是使用 Recording Rule把复杂的查询预先计算成新指标比如把每服务的错误率预计算为job:service:error_rate_5m面板查询直接读预计算指标避免每次渲染都全量扫描原始数据。这套体系从测试环境到生产环境前后花了大约三周时间其中真正写代码的时间很短大部分时间都花在选型、参数调优和踩坑修复上。现在再发生线上故障我们的排障流程已经稳定成固定动作看指标确认影响面查日志拿到 trace ID跳 Tempo 看完整链路定位根因处理恢复。整个过程通常在十几分钟内完成比过去在多个系统间人肉串联线索快了不止一个量级。如果你也正在做类似的落地我的建议是不要贪多求全先让一条核心链路完整跑通——从应用埋点到指标、日志、链路三条数据都能查到再逐步扩展覆盖范围和告警体系。可观测性这件事永远是一点点做出来的不是一次性部署完就完事的。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号