OpenTelemetry JAVA¶
OpenTelemetry Java Agent は、JVM の -javaagent パラメータを使用して実行時にバイトコードを注入します。アプリケーションのコードを変更することなく、一般的な Java Web フレームワーク、HTTP クライアント、JDBC、RPC、メッセージキュー、JVM ランタイムなどのテレメトリデータを収集できます。
このドキュメントでは、DataKit の OpenTelemetry コレクターを使用して Trace と Metric を受信します。アプリケーションログはローカルファイルに書き込まれ、DataKit の logging コレクターが読み取ってGuanceに転送します。
Java アプリ + OpenTelemetry Java Agent -- OTLP Trace/Metric --> DataKit --> Guance
Java アプリ -- trace_id/span_id を含むログファイル --> DataKit logging --> Guance
前提条件¶
- Java 8 以降
- DataKit がインストールされ、ターゲットのGuanceワークスペースに接続されていること
- Java アプリケーションから DataKit へのネットワーク到達性:OTLP/HTTP は DataKit HTTP ポート
9529、OTLP/gRPC はデフォルトで4317を使用 - Java Agent が対象のフレームワークまたはコンポーネントに対して自動インストルメンテーションをサポートしていること
一、OpenTelemetry コレクターを有効にする¶
DataKit がホストにインストールされている場合¶
DataKit インストールディレクトリの conf.d/opentelemetry に移動します。コレクター設定がまだ作成されていない場合は、サンプルファイルをコピーします。
opentelemetry.conf に少なくとも以下の受信設定が含まれていることを確認します。
[[inputs.opentelemetry]]
# カスタム属性をGuanceでタグとして保持する場合は、ここにホワイトリストを追加します。
# 属性名のドットはアンダースコアに変換されます(例:team.name -> team_name)。
customer_tags = ["team", "project"]
[inputs.opentelemetry.http]
http_status_ok = 200
trace_api = "/otel/v1/traces"
metric_api = "/otel/v1/metrics"
[inputs.opentelemetry.grpc]
addr = "127.0.0.1:4317"
max_payload = 16777216
上記の設定により、以下の受信アドレスが有効になります。
| プロトコル | データタイプ | DataKit 受信アドレス |
|---|---|---|
| OTLP/HTTP + Protobuf | Trace | http://<DataKit-IP>:9529/otel/v1/traces |
| OTLP/HTTP + Protobuf | Metric | http://<DataKit-IP>:9529/otel/v1/metrics |
| OTLP/gRPC | Trace、Metric | http://<DataKit-IP>:4317 |
このドキュメントでは、OTLP 経由でアプリケーションログを送信しないため、logs_api の設定は不要です。ログファイルの収集は、三、ログ収集とトレースの関連付け で設定します。
アプリケーションと DataKit が同じホストにない場合は、gRPC の addr をアプリケーションからアクセス可能なアドレス(例:0.0.0.0:4317)に変更します。また、実際のデプロイに応じて、DataKit HTTP リスニングアドレス、ファイアウォール、およびその他のネットワークアクセス制御を調整します。OTLP 受信ポートをインターネットに直接公開しないでください。
DataKit を再起動して設定を反映させます。
DataKit HTTP サービスにアクセスできることを確認します。
二、アプリケーションを OpenTelemetry に接続する¶
Java Agent のダウンロード¶
OpenTelemetry 公式リポジトリから最新の Java Agent をダウンロードします。
sudo mkdir -p /opt/opentelemetry
sudo curl -fL \
https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar \
-o /opt/opentelemetry/opentelemetry-javaagent.jar
利用可能なバージョンは OpenTelemetry Java Instrumentation Release ページ で確認できます。本番環境では、検証済みの Agent バージョンを固定し、アップグレード前にリリースノートを確認して回帰テストを実行することをお勧めします。
環境変数を使用した起動¶
以下は、OTLP/HTTP + Protobuf の例です。OTEL_EXPORTER_OTLP_ENDPOINT はベースアドレスで、Java Agent は Trace と Metric に自動的に /v1/traces、/v1/metrics を追加し、最終的に DataKit の /otel/v1/* ルートに対応します。ログはファイル収集されるため、OTEL_LOGS_EXPORTER=none を維持し、同じログが重複して送信されるのを防ぎます。
export JAVA_TOOL_OPTIONS="-javaagent:/opt/opentelemetry/opentelemetry-javaagent.jar"
export OTEL_SERVICE_NAME="order-service"
export OTEL_RESOURCE_ATTRIBUTES="env=prod,version=1.0.0,team=backend"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="otlp"
export OTEL_LOGS_EXPORTER="none"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:9529/otel"
export OTEL_PROPAGATORS="tracecontext,baggage"
java -jar app.jar
JAVA_TOOL_OPTIONS は、その環境で起動するすべての JVM に影響します。同じ起動環境に他の Java プロセスがある場合は、誤った注入を避けるために、次のセクションの明示的な -javaagent パラメータを使用することをお勧めします。
JVM パラメータを使用した起動¶
システムプロパティは -jar の前に指定する必要があります。
java -javaagent:/opt/opentelemetry/opentelemetry-javaagent.jar \
-Dotel.service.name=order-service \
-Dotel.resource.attributes=env=prod,version=1.0.0,team=backend \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=otlp \
-Dotel.logs.exporter=none \
-Dotel.exporter.otlp.protocol=http/protobuf \
-Dotel.exporter.otlp.endpoint=http://127.0.0.1:9529/otel \
-Dotel.propagators=tracecontext,baggage \
-jar app.jar
OTLP/gRPC の使用¶
OTLP/gRPC を使用する場合は、プロトコルとアドレスを変更するだけです。gRPC アドレスには /v1/traces などの HTTP パスを追加しないでください。
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:4317"
Tomcat¶
<CATALINA_BASE>/bin/setenv.sh に環境変数と Agent パラメータを設定します。
export CATALINA_OPTS="$CATALINA_OPTS -javaagent:/opt/opentelemetry/opentelemetry-javaagent.jar"
export OTEL_SERVICE_NAME="order-service"
export OTEL_RESOURCE_ATTRIBUTES="env=prod,version=1.0.0"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="otlp"
export OTEL_LOGS_EXPORTER="none"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:9529/otel"
保存後、Tomcat を再起動します。他のアプリケーションサーバーでも、-javaagent を実際に JVM を起動するパラメータに追加し、同じ JVM に Agent が一度だけロードされるようにします。
三、ログ収集とトレースの関連付け¶
OpenTelemetry Log 方式でアプリケーションログを送信しない場合は、アプリケーションがログをローカルファイルに書き込み、DataKit の logging コレクターでファイルログを収集できます。この方式を使用する場合は、OTEL_LOGS_EXPORTER を none に設定し(または JVM パラメータで -Dotel.logs.exporter=none を設定)、OpenTelemetry Log Exporter を無効にして、同じログが異なる経路で重複送信されるのを防ぎます。
OpenTelemetry Java Agent は、現在の Span の以下のフィールドを、Logback または Log4j のログイベントの MDC(Mapped Diagnostic Context)コピーに自動的に注入します。
trace_id:現在の Trace IDspan_id:現在の Span IDtrace_flags:W3C Trace Flags
アプリケーションは、OpenTelemetry ログ依存関係を追加したり、ビジネスコードを変更したりする必要はありません。ログ形式でこれらの MDC フィールドを参照するだけです。DataKit がファイルからログを収集した後、Pipeline を使用して trace_id と span_id をログフィールドとして抽出することで、Guanceでログとトレースの関連付けを実現できます。
!!! note
有効な Span のコンテキスト内で生成されたログのみがトレースフィールドを含みます。アプリケーションの起動ログ、スケジュールタスクログ、またはインストルメンテーションの対象外の非同期タスクログには `trace_id` や `span_id` が含まれない場合がありますが、これは正常な動作です。フィールド名は、Java Agent が注入する `trace_id`、`span_id`、`trace_flags` を使用する必要があります。`traceId` に変更したり、ID を手動で生成したりしないでください。
Logback によるファイル出力¶
Logback 1.0 以降は、Java Agent の MDC 自動インストルメンテーションをサポートしています。以下の内容を logback.xml または logback-spring.xml に追加し、ログディレクトリは実際の状況に応じて変更します。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_DIR" value="/opt/order-service/logs"/>
<property name="LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [trace_id=%X{trace_id} span_id=%X{span_id} trace_flags=%X{trace_flags}] - %msg%n"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_DIR}/application.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/application.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>7</maxHistory>
<totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</configuration>
Spring Boot アプリケーションがすでにデフォルトの Logback 設定を使用している場合は、application.properties でファイル出力を有効にし、ファイルログ形式を上書きすることもできます。
logging.file.name=/opt/order-service/logs/application.log
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [trace_id=%mdc{trace_id} span_id=%mdc{span_id} trace_flags=%mdc{trace_flags}] - %msg%n
Log4j 2 によるファイル出力¶
Log4j 2.7 以降は、Java Agent のコンテキストデータ自動インストルメンテーションをサポートしています。以下の内容を log4j2.xml または log4j2-spring.xml に追加します。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<Property name="LOG_DIR">/opt/order-service/logs</Property>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5p %c{36} [trace_id=%X{trace_id} span_id=%X{span_id} trace_flags=%X{trace_flags}] - %m%n%throwable</Property>
</Properties>
<Appenders>
<RollingFile name="FILE"
fileName="${LOG_DIR}/application.log"
filePattern="${LOG_DIR}/application.%d{yyyy-MM-dd}.%i.log.gz">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<DefaultRolloverStrategy max="7"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="FILE"/>
</Root>
</Loggers>
</Configuration>
上記のいずれかの設定で生成されるログの先頭行の形式は同じです。例:
2026-08-12 10:20:30.123 [http-nio-8080-exec-1] INFO c.e.OrderController [trace_id=4bf92f3577b34da6a3ce929d0e0e4736 span_id=00f067aa0ba902b7 trace_flags=01] - order created
DataKit ファイル収集の設定¶
アプリケーションが動作するホストで /usr/local/datakit/conf.d/logging/java_otel.conf を作成します。
[[inputs.logging]]
logfiles = ["/opt/order-service/logs/*.log"]
source = "java"
service = "order-service"
pipeline = "java_otel.p"
character_encoding = "utf-8"
# Java の例外スタックトレースを対応するログにマージします。日付で始まる行を新しいログとして扱います。
enable_multiline = true
multiline_match = '''^\d{4}-\d{2}-\d{2}'''
remove_ansi_escape_codes = true
from_beginning = false
[inputs.logging.tags]
env = "prod"
version = "1.0.0"
service、env、version は、Java Agent の OTEL_SERVICE_NAME および OTEL_RESOURCE_ATTRIBUTES と一致させる必要があります。DataKit の実行ユーザーは、ログディレクトリに対するトラバース権限と、ログファイルに対する読み取り権限を持っている必要があります。
次に、/usr/local/datakit/pipeline/java_otel.p を作成します。
grok(_, "%{TIMESTAMP_ISO8601:time} \\[%{DATA:thread_name}\\] %{LOGLEVEL:status}%{SPACE}%{NOTSPACE:class_name} \\[trace_id=%{DATA:trace_id} span_id=%{DATA:span_id} trace_flags=%{DATA:trace_flags}\\] - %{GREEDYDATA:msg}")
default_time(time)
この Pipeline は、MDC の値をログのトップレベルフィールド trace_id、span_id、trace_flags として抽出します。trace_id と span_id は、Guanceでログとトレースを関連付けるために必要なキーフィールドです。
DataKit を再起動して、ログ収集設定と Pipeline を反映させます。
ログファイルのパス、ログ形式、またはフィールドの順序が変更された場合は、logfiles、multiline_match、および Pipeline ルールを同期して変更する必要があります。ファイル収集のオプションの詳細については、DataKit ログ収集 を参照してください。
四、データ送信パラメータ¶
Java Agent は、環境変数、JVM システムプロパティ、および設定ファイルをサポートしています。優先順位は高い順に、JVM システムプロパティ、環境変数、設定ファイルです。システムプロパティを環境変数に変換する場合、名前は大文字に変換され、. と - は _ に置き換えられます(例:otel.service.name は OTEL_SERVICE_NAME に対応)。
基本パラメータ¶
| 環境変数 | JVM システムプロパティ | 説明 | 推奨値または例 |
|---|---|---|---|
OTEL_SERVICE_NAME |
otel.service.name |
サービス名。未設定の場合はデフォルトで unknown_service:java になります。 |
order-service、本番環境では明示的に設定する必要があります。 |
OTEL_RESOURCE_ATTRIBUTES |
otel.resource.attributes |
リソース属性。形式はカンマ区切りの key=value です。 |
env=prod,version=1.0.0,team=backend |
OTEL_TRACES_EXPORTER |
otel.traces.exporter |
Trace エクスポーター。 | DataKit に送信する場合は otlp に設定します。無効にする場合は none に設定します。 |
OTEL_METRICS_EXPORTER |
otel.metrics.exporter |
Metric エクスポーター。 | JVM/Runtime メトリクスを送信する場合は otlp に設定します。無効にする場合は none に設定します。 |
OTEL_LOGS_EXPORTER |
otel.logs.exporter |
Log エクスポーター。 | このドキュメントでは DataKit がログファイルを収集するため、重複送信を避けるために none に固定します。 |
OTEL_PROPAGATORS |
otel.propagators |
サービス間のコンテキスト伝播形式。 | デフォルトは tracecontext,baggage。全リンクで互換性を維持する必要があります。 |
OTEL_SDK_DISABLED |
otel.sdk.disabled |
OpenTelemetry SDK を無効にします。 | デフォルトは false。緊急時に無効にする場合は true に設定します。 |
OTEL_JAVAAGENT_ENABLED |
otel.javaagent.enabled |
Java Agent を無効または有効にします。 | デフォルトは true。 |
OTEL_JAVAAGENT_CONFIGURATION_FILE |
otel.javaagent.configuration-file |
Java Agent の properties 設定ファイルのパス。 | /etc/otel/otel.properties |
service.name は、Guanceでのサービス所属に使用されます。env と version も設定し、環境やバージョンでフィルタリングできるようにすることをお勧めします。その他のカスタムリソース属性は、DataKit の customer_tags ホワイトリストに追加した後にのみタグとして保持され、属性名の . は _ に変換されます。
OTLP パラメータ¶
| 環境変数 | JVM システムプロパティ | 説明 | 推奨値または例 |
|---|---|---|---|
OTEL_EXPORTER_OTLP_PROTOCOL |
otel.exporter.otlp.protocol |
すべてのシグナルの OTLP プロトコル。 | http/protobuf または grpc。Java Agent 2.x のデフォルトは http/protobuf ですが、明示的に設定することをお勧めします。 |
OTEL_EXPORTER_OTLP_ENDPOINT |
otel.exporter.otlp.endpoint |
すべてのシグナルで共通のベースアドレス。 | HTTP:http://datakit-host:9529/otel;gRPC:http://datakit-host:4317。 |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT |
otel.exporter.otlp.traces.endpoint |
Trace のみに使用されるアドレス。共通アドレスより優先されます。 | HTTP:http://datakit-host:9529/otel/v1/traces。 |
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT |
otel.exporter.otlp.metrics.endpoint |
Metric のみに使用されるアドレス。共通アドレスより優先されます。 | HTTP:http://datakit-host:9529/otel/v1/metrics。 |
OTEL_EXPORTER_OTLP_HEADERS |
otel.exporter.otlp.headers |
すべての OTLP リクエストに含まれるリクエストヘッダー。複数の値はカンマで区切ります。 | x-tenant=tenant-a;DataKit の expected_headers と一致させる必要があります。 |
OTEL_EXPORTER_OTLP_COMPRESSION |
otel.exporter.otlp.compression |
OTLP リクエストの圧縮方式。 | ホスト間で送信する場合は gzip に設定できます。 |
OTEL_EXPORTER_OTLP_TIMEOUT |
otel.exporter.otlp.timeout |
1 回のエクスポートのタイムアウト(ミリ秒)。 | デフォルトは 10000。 |
共通のエンドポイントと特定のデータタイプのエンドポイントが同時に存在する場合、特定のデータタイプの設定が優先されます。例えば、OTEL_EXPORTER_OTLP_TRACES_ENDPOINT が設定されている場合、Trace は OTEL_EXPORTER_OTLP_ENDPOINT を使用しません。
DataKit の OTLP/HTTP 収集は Protobuf のみをサポートしているため、http/protobuf を使用し、http/json は使用しないでください。HTTP の共通エンドポイントを使用する場合は、http://<DataKit-IP>:9529/otel に設定します。特定のデータタイプの独立したエンドポイントを設定する場合は、完全な /otel/v1/<signal> パスを含める必要があります。
サンプリングとバッチ送信パラメータ¶
| 環境変数 | JVM システムプロパティ | 説明 | デフォルト値または例 |
|---|---|---|---|
OTEL_TRACES_SAMPLER |
otel.traces.sampler |
Trace ヘッドサンプラー。 | デフォルトは parentbased_always_on。比率サンプリングには parentbased_traceidratio を使用できます。 |
OTEL_TRACES_SAMPLER_ARG |
otel.traces.sampler.arg |
サンプラーの引数。 | 0.1 はルート Trace の 10% をサンプリングすることを意味します。 |
OTEL_BSP_SCHEDULE_DELAY |
otel.bsp.schedule.delay |
Span バッチエクスポート間隔(ミリ秒)。 | デフォルトは 5000。 |
OTEL_BSP_MAX_QUEUE_SIZE |
otel.bsp.max.queue.size |
エクスポート待ちの Span キュー上限。 | デフォルトは 2048。 |
OTEL_BSP_MAX_EXPORT_BATCH_SIZE |
otel.bsp.max.export.batch.size |
1 バッチでエクスポートする Span の最大数。 | デフォルトは 512。キュー上限を超えることはできません。 |
OTEL_BSP_EXPORT_TIMEOUT |
otel.bsp.export.timeout |
Span バッチエクスポートのタイムアウト(ミリ秒)。 | デフォルトは 30000。 |
OTEL_METRIC_EXPORT_INTERVAL |
otel.metric.export.interval |
Metric エクスポート間隔(ミリ秒)。 | デフォルトは 60000。 |
本番環境では、トラフィックとデータ予算に基づいてサンプリングレートを設定する必要があります。アプリケーション側のヘッドサンプリングと DataKit 側のサンプリングを同時に有効にすると、最終的な保持率はさらに低下するため、サンプリングの場所を統一的に計画する必要があります。
ログとデバッグパラメータ¶
| 環境変数 | JVM システムプロパティ | 説明 | デフォルト値または例 |
|---|---|---|---|
OTEL_JAVAAGENT_LOGGING |
otel.javaagent.logging |
Agent 自身のログ出力方法。 | デフォルトは simple。none、application も選択可能。 |
OTEL_JAVAAGENT_DEBUG |
otel.javaagent.debug |
詳細な Agent デバッグログを出力します。 | デフォルトは false。トラブルシューティング時のみ一時的に true に設定します。 |
OTEL_JAVAAGENT_LOGGING は Java Agent 自身の診断ログを制御し、アプリケーションログの収集方法とは関係ありません。このドキュメントでは、アプリケーションログは DataKit によってファイルから収集されるため、OTEL_LOGS_EXPORTER は none に保つ必要があります。
接続の確認¶
- アプリケーションを起動し、標準エラー出力に
opentelemetry-javaagent - versionが表示され、OTLP export error がないことを確認します。 - Web フレームワーク、HTTP クライアント、またはデータベースを経由するアプリケーションのエンドポイントにリクエストを送信し、同時にリクエスト処理コード内でアプリケーションログを生成します。
- ログファイルを確認し、リクエストスコープ内のログに空でない
trace_idとspan_idが含まれていることを確認します。
- HTTP を使用して送信する場合、DataKit ホストで OTLP 受信ログを確認します。
/otel/v1/traces または /otel/v1/metrics への POST リクエストがあり、応答コードが 200 の場合、DataKit がデータを受信したことを示します。
- Guanceの「ログエクスプローラー」に移動し、
service:order-serviceで検索します。リクエストログを開き、trace_id、span_idがフィールドとして抽出されていることを確認します。次に、ログ詳細の関連トレースリンクから対応する Trace を表示します。または、「APM > トレース」に移動し、service:order-serviceで検索して、トレースに関連付けられたログを表示することもできます。
Trace が生成されない場合は、一時的に OTEL_JAVAAGENT_DEBUG=true を追加してアプリケーションを再起動し、Agent のロード、インストルメンテーションマッチング、エンドポイント、プロトコル、ネットワークエラーを確認します。ログは存在するがトレースフィールドがない場合は、ログが有効な Span の範囲内で生成されているか、実際に使用されているログ設定ファイルに MDC 形式が含まれているか、アプリケーションが対応するログフレームワークの自動インストルメンテーションを無効にしていないかを確認する必要があります。ファイルにトレースフィールドがあるがGuanceに表示されない場合は、DataKit のファイル読み取り権限、ログパス、Pipeline のマッチング結果を確認する必要があります。トラブルシューティングが完了したら、大量のログと追加のパフォーマンスオーバーヘッドを避けるために、デバッグを無効にする必要があります。