自动埋点省事但覆盖不到业务语义,手动埋点精准但费工。本文给出 Java/Python 的自动埋点启动方式、手动 Span 写法、属性命名规范,以及验证链路是否真正打通的步骤。
OpenTelemetry 的自动埋点靠注入 Agent 在运行时改写字节码或挂解释器钩子,不改代码就能拿到 HTTP 请求、数据库调用、消息队列这些通用信息。它覆盖的是「框架层面」的 span:入站请求、出站调用、SQL 执行。
但它覆盖不到业务语义。自动埋点知道你调了 POST /orders,却不知道这笔订单的金额、用户 ID、用了哪张优惠券。排查线上问题,缺的往往正是这些业务维度——自动埋点能告诉你「哪条调用链慢了」,却说不清「哪类订单慢了」。
Java 服务只需在启动命令加一行,就能拿到完整的链路:
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=order-service \
-Dotel.exporter.otlp.endpoint=http://collector:4317 \
-Dotel.traces.exporter=otlp \
-jar order-service.jar
Python 用 opentelemetry-instrument 包裹启动命令,配合 opentelemetry-bootstrap 自动装好各库对应的 instrumentor:
opentelemetry-bootstrap -a install
opentelemetry-instrument \
--traces_exporter otlp \
--exporter_otlp_endpoint http://collector:4317 \
python app.py
跑起来后,先发一条请求,回到控制台看是否出现完整的调用链。链路没打通之前,先别急着做手动埋点——问题大概率在采集端或网络,而不是代码里。
手动埋点不是把所有逻辑都包一层 span,只在三处动手:
transaction_id 贯穿。user.id、order.amount 这类维度,排查时能按业务条件过滤。Java 里给 span 补属性:
Span span = tracer.spanBuilder("process-order").startSpan();
span.setAttribute("order.amount", 99.5);
span.setAttribute("user.id", uid);
try (Scope scope = span.makeCurrent()) {
// 业务逻辑
} catch (Exception e) {
span.recordException(e);
span.setStatus(StatusCode.ERROR);
throw e;
} finally {
span.end();
}
recordException 和 setStatus(ERROR) 别省:告警和采样策略都依赖 span 的状态码。出错了不标记,尾采样可能把关键链路采没,出问题时你会发现自己最需要的那条 trace 不见了。
属性名统一用点分小写(order.amount 而不是 orderAmount),团队先约定一份属性清单,避免各服务各写一套。接入后按 trace id 在控制台验证:span 树是否完整、业务属性是否带上、错误 span 是否标记。抽一条出错请求,确认能从告警一路下钻到异常栈,才算真正接好。