Spring BootにOpenTelemetryを入れるとき、最初に迷うのは名前がほぼ同じstarterが2つあることです。spring-boot-starter-opentelemetry と opentelemetry-spring-boot-starter。語順が逆なだけに見えますが、提供元も設定キーもテレメトリの命名規約も違います。この記事では、どちらを選ぶか、Mavenにどう書くか、OTLPの送信先をどのプロパティで指定するかを整理したうえで、Spring Boot 4.1.2で実際に動かして分かった「既定で何が送られるか」「ログが届かない原因」を書きます。版と日付は2026年11月3日時点です。
まとめ
- Spring Boot 4系なら
org.springframework.boot:spring-boot-starter-opentelemetry。バージョン指定は不要で、設定はmanagement.*プロパティです。 - Spring Boot 2.6以降の2系・3.1以降の3系なら
io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter(最新2.33.1)。BOMで版を揃え、設定はotel.*です。このstarterは実装上Spring Boot 4にも対応済みです。 - 公式starterを入れただけでは、送られるのはメトリクスだけです。トレースは送信先を書いたときだけ送られ、既定のサンプリング率0.1では101リクエスト中13スパンしか届きませんでした。
- ログはSpring Bootが標準でブリッジしません。Logbackアペンダーを足すときはアペンダーの版をSpring Bootが管理するOpenTelemetry SDKの版に合わせる必要があります。4.1.2に最新の2.33.1-alphaを入れると、エラーで送信スレッドが落ち、ログは1件も届きません。
- Spring Boot 4.2では送信先を1つのプロパティで共通指定できるようになり、OpenTelemetryのセマンティック規約も選べるようになります(4.2.0-RC1公開済み)。
2つのstarterの違い|groupIdによる判別
判別はgroupIdで行います。
| 項目 | Spring Boot公式 | OpenTelemetry版 |
|---|---|---|
| groupId | org.springframework.boot | io.opentelemetry.instrumentation |
| artifactId | spring-boot-starter-opentelemetry | opentelemetry-spring-boot-starter |
| 提供元 | Spring Bootチーム | OpenTelemetryコミュニティ |
| 対応Boot | 4.0以降 | 2.6+/3.1+(docs表記)・4系も動作 |
| 実装基盤 | Micrometer+OTel SDK | OpenTelemetry Java SDK |
| 命名規約 | Micrometer規約 | OTelセマンティック規約 |
| 設定キー | management.* | otel.*/OTEL_* |
| 版の指定 | 不要(Bootが管理) | BOMで指定 |
OpenTelemetryそのもの(3つのシグナル、OTLP、Collector)を先に押さえたい場合は、OpenTelemetryの仕組みとCollectorの導入手順を読んでおくと、以下の設定が何を送っているのか掴みやすくなります。
公式starterが引き込む依存(4.1.2でActuatorは入らない)
spring-boot-starter-opentelemetry はSpring Boot 4.0で追加されました。Maven Centralの4.1.2のPOMが直接引き込むのは、spring-boot-starter-micrometer-metrics、spring-boot-micrometer-tracing-opentelemetry、spring-boot-opentelemetry と、実行時に使う micrometer-registry-otlp(メトリクスのOTLP送出)、micrometer-tracing-bridge-otel(トレースの橋渡し)、opentelemetry-exporter-otlp です。Webアプリにこのstarterだけを足して mvn dependency:tree を取ると、解決版はOpenTelemetry SDK 1.62.0、Micrometer 1.17.2、Micrometer Tracing 1.7.2でした。
この依存ツリーに spring-boot-starter-actuator は出てきません。Actuatorのエンドポイントが要らなければ入れなくてよく、必要になった時点で足せば済みます。エンドポイントの公開範囲を決めるときはSpring Boot Actuatorのexposure.includeとaccessの設定を参照してください。Spring Boot 4そのものの変更点はSpring Boot 4の変更点と3系との違いにまとめています。
OpenTelemetry版starterのSpring Boot 4対応(docs表記と実装のずれ)
opentelemetry-spring-boot-starter はOpenTelemetry Java Instrumentationの一部として配布され、最新は2.33.1(2026年10月26日)です。公式ドキュメントの対応表記は今も「works with Spring Boot 2.6+ and 3.1+」のままで、4.xは明記されていません。
ただし、実装上はSpring Boot 4への対応が追加されています。CHANGELOGでは2.23.0に「Spring starter: support Spring Boot 4」が入り、2.24.0でSpring Boot 4のRestClient、2.27.0でSpring Boot 4のActuator metricsモジュールが無いときの ClassNotFoundException が直っています。docsに明記が無いぶん、版を上げるときはCHANGELOGを読む手間が残ります。
Bootのバージョンで決める選び分け
Spring Boot 3系には公式starterが無いので、starterとしての選択肢はOpenTelemetry版だけです。4系では両方使えます。既存の監視がMicrometerのメトリクス名やActuator前提で組まれているなら公式starter、バックエンドのダッシュボードがOpenTelemetryのセマンティック規約前提ならOpenTelemetry版を選びます。計装範囲を最大化したいならstarterではなくJavaエージェントです(後述)。
3系に新しく計装を入れる計画なら、先にサポート期限を見てください。Spring公式のサポート期限によると、3.5のOSSサポートは2026年6月30日に終わり、3系は全ブランチがOSS未サポートです(3.5の商用サポートは2032年6月30日まで)。4系は4.0が2026年12月31日、4.1が2027年7月31日までです。各ブランチの期限はSpring Bootのバージョン一覧とサポート期限で確認できます。
Spring Boot 4.1で公式starterを導入する手順
Spring Boot 4.1.2のシステム要件はJava 17〜27、Spring Framework 7.0.10以上、Maven 3.6.3以上またはGradle 8.14以上(9.x可)です。
Maven・Gradleへの公式starter依存の追加
Spring Bootの依存管理下にあるので、バージョンは書きません。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-opentelemetry</artifactId>
</dependency>
Gradleなら次の1行です。start.spring.ioでは依存の選択画面で「OpenTelemetry」を選ぶと同じものが入ります。
implementation 'org.springframework.boot:spring-boot-starter-opentelemetry'
OTLP送信先の設定とシグナル別の既定動作
送信先はシグナルごとに指定します。トレースとログは management.opentelemetry.*.export.otlp.endpoint ですが、メトリクスだけが management.otlp.metrics.export.url という別の体系です(Spring Boot公式ドキュメントの対応表)。規則から推測して書くと外します。
management.otlp.metrics.export.url=http://localhost:4318/v1/metrics
management.opentelemetry.tracing.export.otlp.endpoint=http://localhost:4318/v1/traces
management.opentelemetry.logging.export.otlp.endpoint=http://localhost:4318/v1/logs
既定の挙動を確かめるため、4318番でOTLP/HTTPを受けて件数を数える受信サーバーを立て、Spring Boot 4.1.2のWebアプリ(spring-boot-starter-webmvcと公式starterだけ)に101回リクエストを送りました。
| 設定 | /v1/metrics | /v1/traces | /v1/logs |
|---|---|---|---|
| プロパティなし | 届く | 来ない | 来ない |
| traces・logsのendpoint指定 | 届く | 13スパン | 来ない |
| 上記+probability=1.0 | 届く | 101スパン | 来ない |
メトリクスのURLは既定値が http://localhost:4318/v1/metrics なので、何も書かなくても送られます。トレースとログはendpointを書いたときだけ送信の設定が作られます。ログはendpointを書いても届きませんでした。理由は後の「ログをOTLPで送る設定」で説明します。ポート4318はOTLP/HTTPです。gRPC(4317)に送るなら management.opentelemetry.tracing.export.otlp.transport=grpc のように明示します(既定は http)。
サンプリング率の既定値0.1とDevToolsによる上書き
上の表で101リクエストに対して13スパンしか届かなかったのは、management.tracing.sampling.probability の既定が0.1だからです。この検証のように親スパンのないリクエストを全件サンプリングするには1.0にします。ただし、既定のサンプラーは親の採否を引き継ぐため、上流で非採用とされたトレースは1.0でも採用されません。
management.tracing.sampling.probability=1.0
開発中は全件届いて見えることがあります。spring-boot-micrometer-tracing の META-INF/spring-devtools.properties に defaults.management.tracing.sampling.probability=1.0 があり(4.1.2のjarで確認)、DevToolsが有効だと既定が1.0になるためです。「開発では全件見えたのに本番で9割消える」という食い違いはここで起きます。本番で率を上げる場合、親スパンのないトレースを同じ条件で比較すると、採用率を0.1から1.0へ変えた場合の採用件数は期待値で約10倍になります。実際の送信バイト数や保管量はスパン数・圧縮・保持設定にも依存します。Collector側のテールサンプリングは受信後の採否を決めるため、アプリからCollectorへの送信量を減らすものではなく、上流で破棄したスパンも復元できません。率の決め方はトレースサンプリングの仕組みとサンプリング率の決め方で扱っています。サンプラー種別は management.opentelemetry.tracing.sampler(既定 parent-based-trace-id-ratio)です。
サービス名・リソース属性の設定と優先順位
サービス名には spring.application.name が使われます。上書きや属性の追加は management.opentelemetry.resource-attributes で行い、環境変数 OTEL_RESOURCE_ATTRIBUTES・OTEL_SERVICE_NAME よりプロパティ側が優先されます。複数インスタンスを見分けたいならインスタンスIDを入れておきます。
management.opentelemetry.resource-attributes.service.instance.id=${HOSTNAME:local-dev}
Docker Composeによるローカル受信環境の構築
送信先が無いまま起動すると、メトリクスの送信が失敗し続けます。手元で確かめるなら、spring-boot-docker-compose を依存に足し、compose.yamlに grafana/otel-lgtm か otel/opentelemetry-collector-contrib のサービスを書いておくと、Spring Bootが3シグナルの接続先を自動で設定します。grafana/otel-lgtm はGrafana・Tempo・Loki・Mimirが1つのイメージに入っており、届いたトレースをそのまま画面で見られます。Grafana側の構成はGrafana OpenTelemetry連携の構成が詳しいです。
OTLPログ送信の設定|アペンダーとSDKのバージョン整合
公式ドキュメントは、SdkLoggerProvider のBeanは作るものの「Spring Boot doesn’t support bridging logs to this bean out of the box」と書いています。endpointを指定してもログが届かなかったのはこのためで、Logbackのログを流し込むアペンダーは自分で足します。Spring公式ブログと同じ手順で、依存・logback-spring.xml・アペンダーへ OpenTelemetry を渡すBeanの3点を用意します。
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-logback-appender-1.0</artifactId>
<version>2.28.1-alpha</version>
</dependency>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<appender name="OTEL" class="io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender"/>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="OTEL"/>
</root>
</configuration>
@Component
class OtelAppenderInstaller implements InitializingBean {
private final OpenTelemetry openTelemetry;
OtelAppenderInstaller(OpenTelemetry openTelemetry) { this.openTelemetry = openTelemetry; }
@Override public void afterPropertiesSet() { OpenTelemetryAppender.install(this.openTelemetry); }
}
ここで版を間違えやすくなります。アペンダーの版はSpring Bootの依存管理に入っていないので、自分で書きます。最新の2.33.1-alphaを書いて4.1.2で動かすと、起動もコンソール出力も正常なのに、/v1/logs には1件も届きませんでした。デバッグログを有効にすると、ログを送るスレッドが NoClassDefFoundError: io/opentelemetry/api/incubator/common/ExtendedAttributes で落ちていました。2.33.1-alphaはOpenTelemetry API 1.67.0系(api-incubatorは1.67.0-alpha)を前提にしていますが、Spring Boot 4.1.2はSDKを1.62.0に固定しているので、版の違うjarが混ざるためです。
アペンダーは、POMが依存するOpenTelemetry APIの版がSpring Bootの管理版と一致するものを選びます。Maven CentralのPOMで確かめた対応は次のとおりで、4.1.2(SDK 1.62.0)には2.28.x系が合います。2.28.1-alphaに差し替えると、同じ101リクエストでログが届きました。
| logback-appender | OpenTelemetry API |
|---|---|
| 2.27.0-alpha | 1.61.0 |
| 2.28.0-alpha/2.28.1-alpha | 1.62.0 |
| 2.29.0-alpha | 1.63.0 |
| 2.32.0-alpha | 1.66.0 |
| 2.33.0-alpha/2.33.1-alpha | 1.67.0 |
自分の環境の管理版は mvn dependency:tree で io.opentelemetry:opentelemetry-sdk の版を見れば分かります。Spring Bootを上げてSDKの版が変わったら、アペンダーも合わせて上げてください。版ずれのエラーはアプリのログではなく送信スレッドの標準エラーにしか出ないので、ログ収集基盤で「アプリのログが来ない」と気づくまで見落としやすい不具合です。Collector側でファイルから拾う方式との比較はOpenTelemetryのログ実装(直接送信とfilelog receiver)を参照してください。
独自スパンを足す|@Observedは既定で無効
HTTPの入口以外、たとえばサービス層のメソッドにスパンを付けたいときは、Micrometerの @Observed を使います。
@Service
class OrderService {
@Observed(name = "order.price", contextualName = "calc-price")
String price() { return "100"; }
}
この注釈は付けただけでは効きません。spring-boot-starter-aspectj を依存に足し、management.observations.annotations.enabled=true を指定する必要があります(4.1.2のメタデータで既定値はfalse)。サンプリング1.0で101リクエストを送ると、プロパティ未指定では101スパン(HTTPのみ)、trueにすると202スパン(HTTP+calc-price)でした。依存だけ足して「スパンが増えない」ときは、このプロパティを確認します。メトリクスの計器を自分で設計する話はOpenTelemetryのメトリクス実装で扱っています。
Spring Boot 4.2で変わるOTel設定
4.2.0-RC1は2026年10月22日にMaven Centralへ公開され、GA版は11月3日時点で未公開です。4.2.0-M2のリリースノートから、この記事の設定に関係する3点を挙げます。
- 送信先の共通指定:
management.opentelemetry.otlp.endpoint・headers・compressionを1回書けば、トレース・ログ・メトリクスで共有されます。HTTPでは/v1/tracesなどのパスが自動で付き、シグナルごとの指定があればそちらが優先されます。上で書いたメトリクスだけキーが違う問題は、これで3行書き分けなくて済むようになります。 - OpenTelemetryのセマンティック規約:
management.observations.conventions=open-telemetryで選べます。対象はstableな規約だけで、management.observations.http.server.requests.nameのような名前の変更プロパティは効かなくなります。 - MDCのキー名:
management.tracing.mdc.trace-id-key・span-id-key(既定traceId・spanId)で変えられます。
統一を求めていたissue #47962 は、このPR #50461に引き継がれて2026年8月24日にクローズされました。4.1の間は3行の書き分けが必要です。
Spring Boot 3系の導入手順|BOM 2.33.1で版を揃えるOpenTelemetry版
OpenTelemetry BOMのimportによるバージョン統一
OpenTelemetryのモジュールは版が揃っている前提なので、BOMで一括管理します。MavenでSpring BootのBOMも同じdependencyManagementにimportする場合は、OpenTelemetryのBOMを先に宣言します。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-instrumentation-bom</artifactId>
<version>2.33.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-spring-boot-starter</artifactId>
</dependency>
otel.*プロパティとservice.nameの解決順
otel:
propagators:
- tracecontext
- baggage
resource:
attributes:
deployment.environment.name: staging
service:
name: order-api
namespace: ec-backend
サービス名は公式ドキュメントの6段階で決まります。優先度の高い順に otel.service.name(または OTEL_SERVICE_NAME)、otel.resource.attributes の service.name、spring.application.name、build-info.properties、META-INF/MANIFEST.MF の Implementation-Title、既定値 unknown_service:java です。バックエンドに unknown_service:java が並んでいたら、上の5つがどれも未設定です。計装ごと止めたいときは otel.sdk.disabled=true です。
既定で有効な計装9件とMicrometerブリッジ
設定なしで計装されるのは、JDBC、Logback、Logback MDC、Spring Web、Spring Web MVC、Spring WebFlux、Kafka、MongoDB、R2DBCです。Micrometerブリッジだけは既定で無効なので、既存のMicrometerメトリクスも一緒に送るなら otel.instrumentation.micrometer.enabled=true を書きます。逆に絞りたいときは otel.instrumentation.common.default-enabled=false で一括無効にし、使うものだけ個別に有効化します。こちらのstarterはLogbackの計装が既定で入っているので、ログ送信のためにアペンダーを手で足す必要はありません。
OTEL_LOG_LEVELが効かないJava環境でのデバッグログ設定
テレメトリが届かず、エージェントのログを見たくて OTEL_LOG_LEVEL=debug を設定しても、Javaでは何も変わりません。この変数はJavaScript SDKなどで使うもので、OpenTelemetry Javaエージェント2.33.1のjarを展開して文字列を検索しても OTEL_LOG_LEVEL・otel.log.level は見つかりませんでした。
Javaエージェントでデバッグ出力を有効にするのは OTEL_JAVAAGENT_DEBUG=true(システムプロパティは -Dotel.javaagent.debug=true)です。出力先は otel.javaagent.logging(環境変数 OTEL_JAVAAGENT_LOGGING)で切り替え、標準エラーへ出す simple(既定)、出さない none、アプリのslf4jロガーへ流す application があります。
starterで導入しているならエージェントは動いていません。公式starterはSpring Bootのロギング設定で logging.level.io.opentelemetry=DEBUG のようにSDKのパッケージのレベルを上げます。OpenTelemetry版starterには otel.spring-starter.debug=true があり、2.32.0でこの指定時のデバッグログが修正されています。
Javaエージェントとstarterの使い分け|native imageと起動オーバーヘッドが判断軸
OpenTelemetryは、JVM起動時に -javaagent で差し込むJavaエージェントも提供しています(最新2.33.1)。公式ドキュメントは、エージェントのほうが「More out of the box instrumentation」、つまり標準で計装できる範囲が広いとしています。既存アプリへの後付けならエージェントが素直です。
公式がstarterを勧める条件は、GraalVMのnative image(エージェントが動かない)、エージェントの起動オーバーヘッドが要件を超える、別のJava監視エージェントと競合する、設定を application.yaml に集約したい、YAMLの宣言的構成で書きたい、の5つです。native imageは代わりの手段が無いので、そこだけで決まります。逆に5つのどれにも当てはまらない3系のアプリなら、starterよりエージェントのほうが計装範囲を広く取れます。Spring公式ブログは、エージェントは版の組み合わせに敏感でnative imageで扱いにくいとして、Spring側のstarterを推しています。
経路の乗り換えで壊れるもの|Micrometer規約とOTelセマンティック規約の非互換
3系+OpenTelemetry版starterから4系+公式starterへ移すとき、見落としやすいのがテレメトリの命名規約です。公式starterはMicrometerのObservation APIとレジストリを経由するため、メトリクス名や属性はMicrometerの規約になります。Spring Bootのドキュメントも、エージェントとOpenTelemetry版starterについて「the metrics and traces use the semantic conventions defined by OTel libraries」と書き、規約が別であることを明示しています。
依存の差し替えでメトリクス名やスパン属性のキーが変わると、旧名称を参照するダッシュボードやアラートがデータを取得できなくなる場合があります。データ欠落時の通知動作は監視基盤とルール設定に依存し、Grafana管理のアラートでは既定でDatasourceNoDataアラートが生成されます。4.2の management.observations.conventions=open-telemetry を使えば差は縮まりますが、stableな規約に限られるので、全部の名前が一致する前提は置けません。
切り替えは一度にやらず、旧構成と新構成を別々のアプリインスタンスで並行稼働させ、同等のリクエストに対するテレメトリを比較します。新しい名前でダッシュボードとアラートを作り直し、両方が同じ事象を検知することを確かめてから旧経路を止めます。ステージングだけで済ませると、本番にしか無いバッチや外部連携のメトリクスの欠落を見逃します。並行稼働中の監視設計や切り替え後の運用まで手が回らない場合は、保守運用・内製化支援で監視の引き継ぎから相談を受けています。
よくある質問
spring-boot-starter-opentelemetry と opentelemetry-spring-boot-starter は同じものですか?
別物です。前者はgroupIdが org.springframework.boot のSpring Boot 4.0以降の公式starter、後者はgroupIdが io.opentelemetry.instrumentation のOpenTelemetryプロジェクト製です。設定キー(management.* か otel.* か)と命名規約も違います。
Mavenの依存座標はどう書けばよいですか?
Spring Boot 4系では groupId org.springframework.boot、artifactId spring-boot-starter-opentelemetry をバージョンなしで書きます。Spring Boot 3系では groupId io.opentelemetry.instrumentation、artifactId opentelemetry-spring-boot-starter を使い、opentelemetry-instrumentation-bom(2026年11月時点の最新は2.33.1)を dependencyManagement にimportして版を揃えます。Spring Boot 3系では spring-boot-starter-opentelemetry は依存管理に存在しないので使えません。
management.opentelemetry.logging.export.otlp.endpoint を設定してもログが届かないのはなぜですか?
公式starterはログをOTLPへ流すブリッジを持っていません。opentelemetry-logback-appender-1.0 を足し、logback-spring.xmlにアペンダーを登録して、OpenTelemetryAppender.install() で OpenTelemetry を渡します。アペンダーの版はSpring Bootが管理するSDKの版に合わせます。Spring Boot 4.1.2(SDK 1.62.0)なら2.28.x系です。最新の2.33.1-alphaを入れると、送信スレッドが NoClassDefFoundError で落ちてログは1件も届きません。
OTEL_LOG_LEVEL を設定してもデバッグログが出ないのはなぜですか?
OTEL_LOG_LEVEL はJavaエージェントの設定ではないので、Javaでは効きません。エージェントのデバッグ出力は OTEL_JAVAAGENT_DEBUG=true で有効にし、出力先は OTEL_JAVAAGENT_LOGGING で simple/none/application から選びます。starterで導入しているなら、logging.level.io.opentelemetry=DEBUG でSDKのログレベルを上げます。
トレースが一部しかバックエンドに届かないのはなぜですか?
management.tracing.sampling.probability の既定値は0.1です。Spring Boot 4.1.2で101リクエストを送ったところ、届いたのは13スパンで、1.0にすると101スパンになりました。DevToolsが有効な開発環境では既定が1.0になるので、本番だけ減ったように見えます。
関連記事
- OpenTelemetryとは?仕組み・Collectorの導入手順とPrometheusとの違い【2026年10月】
- Spring Boot 4とは?最新バージョン4.1の変更点・新機能とSpring Boot 3との違い【2026年10月】
- Spring Bootバージョン一覧とサポート期限(EOL)【2026年10月】最新版は4.1、4.0の無償サポートは12月末終了
- Spring Boot Actuatorの設定|exposure.includeとaccessの使い分け【4.1対応】
- トレースサンプリングとは?ヘッドベースとテールベースの仕組み・OpenTelemetry/X-Ray実装・サンプリング率の決め方を実装目線で解説【2026年版】