コンテンツにスキップ

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 に移動します。コレクター設定がまだ作成されていない場合は、サンプルファイルをコピーします。

cd /usr/local/datakit/conf.d/opentelemetry
sudo cp opentelemetry.conf.sample opentelemetry.conf

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 を再起動して設定を反映させます。

sudo datakit service restart

DataKit HTTP サービスにアクセスできることを確認します。

curl http://127.0.0.1:9529/v1/ping

二、アプリケーションを 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_EXPORTERnone に設定し(または JVM パラメータで -Dotel.logs.exporter=none を設定)、OpenTelemetry Log Exporter を無効にして、同じログが異なる経路で重複送信されるのを防ぎます。

OpenTelemetry Java Agent は、現在の Span の以下のフィールドを、Logback または Log4j のログイベントの MDC(Mapped Diagnostic Context)コピーに自動的に注入します。

  • trace_id:現在の Trace ID
  • span_id:現在の Span ID
  • trace_flags:W3C Trace Flags

アプリケーションは、OpenTelemetry ログ依存関係を追加したり、ビジネスコードを変更したりする必要はありません。ログ形式でこれらの MDC フィールドを参照するだけです。DataKit がファイルからログを収集した後、Pipeline を使用して trace_idspan_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"

serviceenvversion は、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_idspan_idtrace_flags として抽出します。trace_idspan_id は、Guanceでログとトレースを関連付けるために必要なキーフィールドです。

DataKit を再起動して、ログ収集設定と Pipeline を反映させます。

sudo datakit service restart

ログファイルのパス、ログ形式、またはフィールドの順序が変更された場合は、logfilesmultiline_match、および Pipeline ルールを同期して変更する必要があります。ファイル収集のオプションの詳細については、DataKit ログ収集 を参照してください。

四、データ送信パラメータ

Java Agent は、環境変数、JVM システムプロパティ、および設定ファイルをサポートしています。優先順位は高い順に、JVM システムプロパティ、環境変数、設定ファイルです。システムプロパティを環境変数に変換する場合、名前は大文字に変換され、.-_ に置き換えられます(例:otel.service.nameOTEL_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でのサービス所属に使用されます。envversion も設定し、環境やバージョンでフィルタリングできるようにすることをお勧めします。その他のカスタムリソース属性は、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 自身のログ出力方法。 デフォルトは simplenoneapplication も選択可能。
OTEL_JAVAAGENT_DEBUG otel.javaagent.debug 詳細な Agent デバッグログを出力します。 デフォルトは false。トラブルシューティング時のみ一時的に true に設定します。

OTEL_JAVAAGENT_LOGGING は Java Agent 自身の診断ログを制御し、アプリケーションログの収集方法とは関係ありません。このドキュメントでは、アプリケーションログは DataKit によってファイルから収集されるため、OTEL_LOGS_EXPORTERnone に保つ必要があります。

接続の確認

  1. アプリケーションを起動し、標準エラー出力に opentelemetry-javaagent - version が表示され、OTLP export error がないことを確認します。
  2. Web フレームワーク、HTTP クライアント、またはデータベースを経由するアプリケーションのエンドポイントにリクエストを送信し、同時にリクエスト処理コード内でアプリケーションログを生成します。
  3. ログファイルを確認し、リクエストスコープ内のログに空でない trace_idspan_id が含まれていることを確認します。
tail -f /opt/order-service/logs/application.log
  1. HTTP を使用して送信する場合、DataKit ホストで OTLP 受信ログを確認します。
sudo tail -f /usr/local/datakit/log/gin.log | grep '/otel/v1/'

/otel/v1/traces または /otel/v1/metrics への POST リクエストがあり、応答コードが 200 の場合、DataKit がデータを受信したことを示します。

  1. Guanceの「ログエクスプローラー」に移動し、service:order-service で検索します。リクエストログを開き、trace_idspan_id がフィールドとして抽出されていることを確認します。次に、ログ詳細の関連トレースリンクから対応する Trace を表示します。または、「APM > トレース」に移動し、service:order-service で検索して、トレースに関連付けられたログを表示することもできます。

Trace が生成されない場合は、一時的に OTEL_JAVAAGENT_DEBUG=true を追加してアプリケーションを再起動し、Agent のロード、インストルメンテーションマッチング、エンドポイント、プロトコル、ネットワークエラーを確認します。ログは存在するがトレースフィールドがない場合は、ログが有効な Span の範囲内で生成されているか、実際に使用されているログ設定ファイルに MDC 形式が含まれているか、アプリケーションが対応するログフレームワークの自動インストルメンテーションを無効にしていないかを確認する必要があります。ファイルにトレースフィールドがあるがGuanceに表示されない場合は、DataKit のファイル読み取り権限、ログパス、Pipeline のマッチング結果を確認する必要があります。トラブルシューティングが完了したら、大量のログと追加のパフォーマンスオーバーヘッドを避けるために、デバッグを無効にする必要があります。

参考

フィードバック

このページは役に立ちましたか?