← 返回文章列表
使用指南 4 分钟阅读 炬鲸团队

零改代码接入链路追踪:OpenTelemetry 自动埋点实战

用 OpenTelemetry 自动埋点,不改业务代码即可接入链路追踪。本文以 Java、Python 为例给出完整配置,覆盖生产采样、容器化部署,附验证步骤与常见问题排查。

为什么要用自动埋点

分布式链路追踪最大的阻力不是技术,是埋点成本。手动在业务代码里加 span,要改代码、要评审、要回归,很多团队卡在这一步就放弃了。OpenTelemetry 的自动埋点(auto-instrumentation)把这件事做到了"不改一行代码"。

自动埋点的原理是运行时注入:Java 靠 Agent 在类加载时改写字节码,Python 靠 monkey patch 替换标准库和框架的调用入口。它拦截的是中间件和客户端的边界,而不是你的业务逻辑,所以对代码零侵入,同时还能拿到跨进程的 trace 上下文。

本文假设你已经有炬鲸 OBSERVE 的接入地址和 token,没有的话先到控制台的"接入向导"里创建一个项目。

以 Java 服务为例

自动埋点靠的是 Java Agent。下载 OTel Java Agent 的 jar 包,然后在启动命令里加一行:

java -javaagent:/opt/otel/opentelemetry-javaagent.jar   -Dotel.service.name=order-service   -Dotel.traces.exporter=otlp   -Dotel.exporter.otlp.endpoint=https://otlp.jjhub.cn:4317   -Dotel.exporter.otlp.headers="Authorization=Bearer <token>"   -jar app.jar

四个参数说清楚:service.name 是服务名,用于在链路拓扑里分组;traces.exporter 指定导出器;otlp.endpoint 指向 OBSERVE 的 OTLP 接收端;headers 带上鉴权。Agent 会拦截 Spring MVC、MySQL 驱动、Redis、Kafka、HTTP Client 等常见组件的调用,自动生成 span。

不同语言怎么做

原理一致,只是载体不同:

  • Go:没有 Agent 机制,推荐用 go.opentelemetry.io/contrib/instrumentation 里现成的中间件包,net/http、gin、gRPC 都有,改一行 import 即可。
  • Python:用 opentelemetry-instrument 命令启动,Flask、Django、Celery 等框架零改动。
  • Node.js@opentelemetry/auto-instrumentations-node 一行 require 搞定。

以 Python 为例:

pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
OTEL_SERVICE_NAME=user-service OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.jjhub.cn:4317 opentelemetry-instrument python app.py

生产环境的两个补充

自动埋点默认全量采集,直接上生产会带来两笔开销:一是 span 数据量暴增、存储成本上升;二是部分高频组件(如每次 DB 查询都打 span)会拖慢请求。建议两件事一起做:

调采样率。在 Agent 参数里加:

-Dotel.traces.sampler=parentbased_traceidratio -Dotel.traces.sampler.arg=0.1

上面是保留 10% 的链路。父 span 被采样的请求,整条链路都保留,不会出现"半条链路"。

容器化部署。Kubernetes 环境里推荐用 initContainer 把 Agent jar 挂进 Pod,而不是打进镜像,升级 Agent 不用重新构建镜像。核心是加一个共享 volume,把 agent 目录挂到主容器的 /opt/otel

顺手把日志和指标也接上

链路通了之后,建议顺便把日志和指标也走 OTel 协议统一上报,避免链路、日志、指标各用一套采集器。以 Java Agent 为例,加两个参数:

-Dotel.logs.exporter=otlp -Dotel.metrics.exporter=otlp

加上之后,同一份 Agent 同时上报三种信号,service.name 保持一致,在 OBSERVE 里点开一个 span 就能直接跳到对应的日志和指标面板,排查时不用在三套系统之间来回切换。

接完之后验证三步

接上不代表生效,按这三步确认:

  1. 在"链路追踪"页面按 service.name 过滤,看是否有新服务出现,有即说明数据上报成功。
  2. 找一条完整链路点开,确认跨服务的父子关系正确、耗时字段(比如 DB 查询耗时)有值。
  3. 压测或触发一次真实请求,看采样率是否符合预期,同时观察服务自身的 CPU 和 P99 延迟有没有被埋点明显抬高。

常见坑

四个高频问题。一是 exporter 版本和 OTLP 协议不匹配,报 unimplemented,把 endpoint 从 4318(HTTP)换成 4317(gRPC)或反过来试试。二是容器里忘了把 OTLP 端口在防火墙、安全组放通。三是 service.name 没设,所有服务都叫 unknown_service,拓扑图会挤成一团。四是主机时间不同步,跨服务的 span 时间轴错乱、父子关系看起来"倒挂"——分布式链路对时钟很敏感,所有主机务必用 NTP 校时。

自动埋点覆盖不到的私有协议或自研 RPC,再用手动埋点补齐即可。先自动、后手动,这个顺序能让你在第一天就看到完整链路。