可观测性常被讲成"买一套 APM 就完事",真相是它有三根柱子,每根柱子都有不止一个工具,而且工具之间是竞争关系而非互补关系。指标看趋势、日志看现场、链路看单次请求——三根柱子对齐到同一套 ID,才算真正"可观测"。本文把八篇笔记按三大支柱重新归位:指标(Prometheus / Micrometer / Grafana)、日志(ELK / Loki)、链路(OpenTelemetry / Jaeger / SkyWalking),最后给出几套能直接落地的组合方案。读的时候先认柱子,再认工具,别一上来就比谁更强。


一、指标支柱:Prometheus 拉取采集,Micrometer 做 Java 门面,Grafana 负责可视化

Prometheus 用拉取模型采集时序:定期访问各目标的 /metrics,按标签存样本,PromQL 做聚合、速率和告警判断,服务发现可对接 Kubernetes。它适合指标,不适合长期无限基数的日志,本地 TSDB 有保留期,更久的历史要远程写到专门存储。Micrometer 是 Java 应用的指标门面,像 SLF4J 对应日志——业务代码只对 MeterRegistry 打 Timer、Counter 和 Gauge,底层可以接到 Prometheus、Influx 或云厂商,Spring Boot Actuator 默认就用它暴露 /actuator/prometheus。Grafana 是开源可视化与告警平台,数据源可以是 Prometheus、Loki、Tempo、MySQL 等,它不采集数据,只负责把已经有的指标变成人能看懂的图。

三个容易踩的坑

  • 标签基数失控(Prometheus + Micrometer)。指标设计要稳定:名称表达含义,标签控制基数,不要把用户 ID 当标签;自定义指标要表达业务语义(如下单成功次数),而不是随便包一层方法耗时。
  • 告警抖动与无人负责(Grafana)。告警要有 for 时长,避免抖动;权限上只读与编辑分开,生产仪表盘走版本库;空有漂亮图而没有负责人,监控仍然无效。
  • 只看机器不看业务(Micrometer)。先把 JVM 和 HTTP 默认指标用起来,再加业务计数;应用关闭时要关掉 registry 避免线程泄漏,和追踪配合时"指标看趋势,链路看单次"。

什么时候用:微服务、网关、定时任务先上 Prometheus + Micrometer 出指标,再用 Grafana 固化面板;秒级抖动要用合适的 range 才能看清趋势,和 Grafana 配合时先在 Prometheus 把查询写对再放到面板。


二、日志支柱:ELK 倒排索引 vs Loki 标签索引(同类竞争)

ELK 指 Elasticsearch、Logstash 与 Kibana:应用把记录打到文件或 syslog 后,Logstash 或 Beats 采集、切分字段并写入 Elasticsearch,Kibana 负责检索、仪表盘和告警。三者分工清楚——一个存储检索、一个管线、一个展示。Loki 是 Grafana 实验室的日志系统,口号是"像 Prometheus 一样按标签索引,而不把全文做倒排索引":Promtail 或 Alloy 采集时只把 job、namespace、pod 等标签写进索引,正文压缩存在对象存储,查询用 LogQL 先按标签筛流再解析字段。两者是同类竞争关系——Loki 高基线查询快、成本低,但随便搜一句报错会比 Elasticsearch 慢。

四个容易踩的坑

  • 索引生命周期与映射(ELK)。日志按天建索引时必须配 ILM 把热数据留热节点、冷数据迁移或删除,否则磁盘会被快速吃光;字段要预先约定,避免动态映射把 status 既当 keyword 又当 text。
  • 查故障的路径(ELK)。先用 Kibana Discover 按 traceId 筛,再看聚合趋势,这比先上仪表盘更贴近真实排障路径。
  • 标签基数爆炸(Loki)。控制标签基数,不要把用户 ID 或请求路径当成标签,否则索引会爆炸;保留期与压缩块大小要按磁盘预算约定。
  • 只索引标签(Loki)。正文不在索引里,所以任意全文搜索比 ES 慢,适合已有 Prometheus/Grafana 的团队"点一个波峰跳到日志",不适合全文检索型需求。

什么时候用:要全文检索、复杂聚合选 ELK;已经有 Prometheus+Grafana 栈、主要按服务/命名空间查日志选 Loki 更顺。两者不要同时铺两套互相不通的日志系统。


三、链路支柱:OpenTelemetry 统一标准,Jaeger 与 SkyWalking 二选一(同类竞争)

OpenTelemetry 把跟踪、指标和日志统成一套发射标准,让业务代码不再绑定某个 APM 厂商。核心是 SDK 里的 TracerProvider、MeterProvider、LoggerProvider,以及把数据送出去的 Exporter;跟踪用 Span 表示一次调用,上下文用 W3C Trace Context 跨进程传播。Collector 负责采样、批量和尾部路由,应放在业务进程外。Jaeger 是面向微服务的分布式追踪系统,兼容 OpenTracing / OpenTelemetry:一次请求拆成若干 Span 用 TraceId 串起来,采集端发给 Collector 再写入 Cassandra 或 Elasticsearch。SkyWalking 是 Apache 的 APM,用探针或 eBPF 采集调用链、指标和日志关联,Java 探针以 JavaAgent 方式织入,把 Span 报到 OAP 再存到 Elasticsearch 或 BanyanDB。Jaeger 与 SkyWalking 是同类竞争关系——都能做链路追踪,区别在 Jaeger 偏轻量 tracing、SkyWalking 自带拓扑图与更完整的 APM 视角。

三个容易踩的坑

  • 链路要带业务 ID(OTel)。订单号、用户 ID、租户 ID 写进 span attributes,否则不能跟着一次请求跨服务查;常见错误是只开自动插桩不打业务属性,最后看到的全是 HTTP 路径而没有订单号。
  • 采样统一做(OTel + Jaeger + SkyWalking)。采样要在 Collector 统一做,不要每个服务随意丢,错误与慢请求应保留全量;服务名要稳定,不要把版本号写进 service 名导致拓扑碎片化。
  • 上下文透传断链(三者共通)。跨线程、MQ 和 HTTP 头要透传 TraceId,否则链路会断;SkyWalking 版本升级探针要先在预发验证,织入失败会让应用起不来。

什么时候用:微服务、网关、消息消费、定时任务都接 OpenTelemetry,而不是各写一套埋点;单体小项目可以先只开跟踪。避免同时插两家 APM agent 争夺字节码。上线前先定好后端是 Jaeger、Tempo 还是云厂商再选 Exporter;把 SkyWalking 当排障入口而不是再堆一套互不相通的仪表盘。


四、组合方案:三根柱子怎么拼

单工具解决不了可观测性,组合才是常态。常见拼法:

  • 指标 + 可视化:Prometheus + Grafana 是默认组合,Micrometer 负责 Java 侧出数;先在 Prometheus 把查询写对,再用 Explore 临时查,确认后再固化到面板。
  • 日志二选一:要么 ELK(要全文检索),要么 Loki(已有 Prometheus/Grafana 栈、按标签查);两者是竞争而非互补,别同时铺。
  • 链路二选一:OpenTelemetry 打底做统一标准,后端选 Jaeger 或 SkyWalking;OTel Collector 统一做采样,三柱对齐同一套 trace_id,才能从 Grafana 一个波峰跳到这条链、再跳到这条日志。
  • 日志与跟踪关联:打日志时带上 trace_id,三柱对齐才能把一次告警对到一段调用链、再对到现场日志。

附:可观测性选型矩阵

需求 用什么 不要用什么 / 注意
Java 指标出数 Micrometer(接 Prometheus) 不要把用户 ID 当标签
时序采集与告警 Prometheus + Alertmanager 不适合无限基数日志,历史要远程写
指标可视化 Grafana 别只炫图,要有负责人和 for 时长
全文检索日志 ELK(Elasticsearch + Logstash + Kibana) 必须配 ILM,否则磁盘爆
标签索引日志 Loki + LogQL 任意全文搜索比 ES 慢,控制标签基数
统一埋点标准 OpenTelemetry 别同时插两家 APM agent 抢字节码
分布式链路(轻量) Jaeger 采样统一做,服务名别带版本号
链路 + APM 拓扑 SkyWalking 探针升级先预发验证,织入失败起不来