Java应用启动无Span上报主因是未启用OpenTelemetry Java Agent或手动初始化SDK;Spring Boot 3.x需使用io.opentelemetry.instrumentation的starter并匹配版本;service.name格式须合法;采样器需配arg参数;Collector队列配置不当会导致丢数据。

Java应用启动时没上报Span,OTEL_EXPORTER_OTLP_ENDPOINT 配置对了但就是没数据
OpenTelemetry Java SDK 默认不自动导出,光配 endpoint 不够,得显式启用 OTLP 导出器并确保初始化完成。常见现象是应用跑起来了,otel.exporter.otlp.endpoint 也设对了(比如 http://localhost:4318),但后端接收不到任何 Span。
- 必须在 JVM 启动参数里加上
-javaagent:/path/to/opentelemetry-javaagent.jar(推荐方式),或手动初始化 SDK;纯依赖application.properties配置不会触发导出器加载 -
OTEL_EXPORTER_OTLP_PROTOCOL默认是http/protobuf,如果后端只支持 gRPC(如旧版 Collector),要显式设为grpc,否则连接会静默失败 - 检查日志里有没有
Failed to export spans或Connection refused,这类错误常被忽略——Java agent 默认不打印导出失败详情,需加-Dio.opentelemetry.javaagent.debug=true开启调试日志
Spring Boot 3.x 项目里 OpenTelemetryAutoConfiguration 不生效
Spring Boot 3+ 基于 Jakarta EE,而早期 OpenTelemetry Spring Boot Starter(如 opentelemetry-spring-boot-starter 1.0.x)仍依赖 javax.* 包,类加载失败导致自动配置跳过,@Bean 根本不注册。
- 用 Spring Boot 3 必须选
io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter(注意 groupId 是io.opentelemetry.instrumentation,不是io.opentelemetry.contrib) - 确认 Maven 依赖版本与 Spring Boot 版本对齐:Boot 3.2.x 对应 starter 1.30.x,Boot 3.3.x 对应 1.32.x+,错一个 patch 版都可能因
ObservabilityProperties类结构变化而失效 - 如果用了
@EnableAspectJAutoProxy或自定义Advisor,可能干扰 OpenTelemetry 的 Controller 方法拦截——此时 Span 名称变成invoke而非真实接口路径,需在配置中加otel.instrumentation.spring-webmvc.enabled=true
otel.resource.attributes 里的 service.name 没出现在 Jaeger UI
资源属性(Resource)是 OpenTelemetry 数据的“身份标签”,但 service.name 不生效往往不是配置写错,而是被 SDK 默认值覆盖或格式不合法。
-
service.name必须是 ASCII 字符、数字、下划线、短横线和点,不能含空格或中文;写成my-service-名称会导致整个 Resource 初始化失败,SDK 回退到默认unknown_service:java - 如果同时通过 JVM 参数(
-Dotel.resource.attributes=service.name=myapp)和代码SdkTracerProvider.builder().setResource(...)设置,后者优先级更高,容易误覆盖 - Jaeger UI 默认按
servicetag 过滤,但 OpenTelemetry 导出到 Jaeger 时会把service.name映射为service,若用的是 OTLP → Collector → Jaeger 链路,要确认 Collector 配置里exporters.jaeger的endpoint指向 Jaeger Collector 的 gRPC 端口(14250),不是 UI 的 HTTP 端口(16686)
高并发下 Span 数量暴增,otel.traces.sampler 设成 traceidratio 也没降下来
采样器只控制新 Span 是否创建,不影响已生成 Span 的导出行为。如果看到内存增长快、gRPC 请求超时、Collector 日志刷满 Dropped 1234 spans,问题大概率不在采样率本身。
立即学习“Java免费学习笔记(深入)”;
-
otel.traces.sampler设为traceidratio时,必须配套指定otel.traces.sampler.arg=0.1(表示 10%),漏掉.arg会导致采样器退化为always_on - HTTP 客户端(如 OkHttp、Apache HttpClient)默认开启全量插桩,每个重试请求、302 跳转都会生成 Span;用
otel.instrumentation.http-client.experimental-span-attributes=true可减少冗余属性,但更有效的是关掉非核心客户端插桩:otel.instrumentation.apache-httpasyncclient.enabled=false - Java agent 内存缓冲区默认 2048 个 Span,高吞吐下频繁 flush 会拖慢应用;可调大
-Dotel.bsp.schedule.delay=30s和-Dotel.bsp.max.export.batch.size=512,但要注意 batch size 过大会增加单次导出失败的风险
真正卡点往往藏在 Collector 的队列长度和 exporter 超时设置里,Java 端再怎么调参,如果 Collector 的 queue_size 是默认 1000,又没开持久化,丢数据是必然的。










