Managed Service for OpenTelemetry は、Java アプリケーションからトレースデータを収集し、アプリケーション トポロジー、トレース、異常および低速トランザクション分析、SQL 分析を提供します。ゼロコードのエージェント設定から完全な SDK コントロールに至るまで、3 つのインストルメンテーションアプローチが利用可能です。
| アプローチ | 工数 | 使用する場合 |
|---|---|---|
| OpenTelemetry Java エージェント (推奨) | 最小:JAR をアタッチするだけで、コード変更は不要 | ほとんどのアプリケーション。まずはここから始めてください。 |
| OpenTelemetry SDK for Java | 中程度:インストルメンテーションコードの記述 | カスタムスパン、属性、またはサポートされていないフレームワーク |
| エージェント + SDK の組み合わせ | 中程度:エージェントが基本をカバーし、SDK がカスタムスパンを追加 | 自動カバレッジに加えて、ターゲットを絞ったカスタムインストルメンテーション |
サンプルコード
動作するリファレンスとして、サンプルプロジェクトをクローンするか参照してください:
git clone https://github.com/alibabacloud-observability/java-demo.git
cd java-demo/opentelemetry-demoメソッド 1:OpenTelemetry Java エージェントによる自動インストルメンテーション
OpenTelemetry Java エージェントは、起動時に JVM にアタッチし、コードを変更することなく数百のライブラリとフレームワークをインストルメント化します。これは、ほとんどのアプリケーションにとって推奨される開始点です。
ステップ 1:エージェントのダウンロード
GitHub Releases から最新のエージェント JAR をダウンロードします:
# wget
wget -O opentelemetry-javaagent.jar \
https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
# または curl
curl -Lo opentelemetry-javaagent.jar \
https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jarステップ 2:JVM パラメーターの設定とアプリケーションの起動
-javaagent フラグを -jar 引数の前に追加します。HTTP または gRPC プロトコルのいずれかを選択します。
HTTP
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=<your-service-name>,service.version=<your-version>,deployment.environment=<your-env> \
-Dotel.exporter.otlp.protocol=http/protobuf \
-Dotel.exporter.otlp.traces.endpoint=<traces-endpoint> \
-Dotel.exporter.otlp.metrics.endpoint=<metrics-endpoint> \
-Dotel.logs.exporter=none \
-jar /path/to/your/app.jarプレースホルダーを実際の値に置き換えてください:
| プレースホルダー | 説明 | 例 |
|---|---|---|
<your-service-name> | アプリケーションを識別する名前 | order-service |
<your-version> | アプリケーションのバージョン | 1.0.0 |
<your-env> | デプロイメント環境 | production |
<traces-endpoint> | 「前提条件」セクションに記載のトレースエンドポイント | http://tracing-analysis-dc-hz-internal.aliyuncs.com/adapt_ggxw4l****@7323a5caae3****_ggxw4l****@53df7ad2afe****/api/otlp/traces |
<metrics-endpoint> | 「前提条件」セクションに記載のメトリクスエンドポイント | http://tracing-analysis-dc-hz-internal.aliyuncs.com/adapt_ggxw4l****@7323a5caae3****_ggxw4l****@53df7ad2afe****/api/otlp/metrics |
例:
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=order-service,service.version=1.0.0,deployment.environment=production \
-Dotel.exporter.otlp.protocol=http/protobuf \
-Dotel.exporter.otlp.traces.endpoint=http://tracing-analysis-dc-hz-internal.aliyuncs.com/adapt_ggxw4l****@7323a5caae3****_ggxw4l****@53df7ad2afe****/api/otlp/traces \
-Dotel.exporter.otlp.metrics.endpoint=http://tracing-analysis-dc-hz-internal.aliyuncs.com/adapt_ggxw4l****@7323a5caae3****_ggxw4l****@53df7ad2afe****/api/otlp/metrics \
-Dotel.logs.exporter=none \
-jar /path/to/your/app.jargRPC
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=<your-service-name>,service.version=<your-version>,deployment.environment=<your-env> \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.headers=Authentication=<token> \
-Dotel.exporter.otlp.endpoint=<endpoint> \
-Dotel.logs.exporter=none \
-jar /path/to/your/app.jarプレースホルダーを実際の値に置き換えてください:
| プレースホルダー | 説明 | 例 |
|---|---|---|
<token> | 「前提条件」セクションに記載の認証トークン | ggxw4l****@7323a5caae3****_ggxw4l****@53df7ad2afe**** |
<endpoint> | 「前提条件」セクションに記載の gRPC エンドポイント | http://tracing-analysis-dc-hz-internal.aliyuncs.com:8090 |
例:
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=order-service,service.version=1.0.0,deployment.environment=production \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.headers=Authentication=ggxw4l****@7323a5caae3****_ggxw4l****@53df7ad2afe**** \
-Dotel.exporter.otlp.endpoint=http://tracing-analysis-dc-hz-internal.aliyuncs.com:8090 \
-Dotel.logs.exporter=none \
-jar /path/to/your/app.jarOpenTelemetry Collector を介してトレースデータを転送するには、-Dotel.exporter.otlp.headers=Authentication=<token>を削除し、<endpoint>をオンプレミスマシンの Collector アドレスに設定します。
ステップ 3:トレースデータの検証
[アプリケーション] ページで、アプリケーション名をクリックします。
アプリケーションの詳細ページにトレースが表示されることを確認します。
トラブルシューティング:
データが表示されない場合は、エンドポイントとトークンが正しいことを確認してください。
デバッグロギングを有効にして、エージェントの動作を調査してください:
-Dotel.javaagent.debug=true起動コマンドから削除せずにエージェントを一時的に無効にしてください:
-Dotel.javaagent.enabled=false
方法 2:OpenTelemetry SDK for Java を使用した手動インストルメンテーション
どの操作でスパンを生成するか、どの属性を持たせるかを完全に制御する必要がある場合、または自動エージェントがフレームワークに対応していない場合は、 OpenTelemetry SDK for Java を使用します。
ステップ 1:Maven 依存関係の追加
pom.xml に次の内容を追加します。
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-trace</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-semconv</artifactId>
<version>1.30.0-alpha</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-bom</artifactId>
<version>1.30.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>ステップ 2:トレーサーの初期化
エクスポーター、リソース属性、トレーサーを構成するヘルパークラスを作成します。環境に合ったプロトコルを選択してください。
HTTP
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
public class OpenTelemetrySupport {
static {
// このサービスを記述するリソースを定義します
Resource resource = Resource.getDefault()
.merge(Resource.create(Attributes.of(
ResourceAttributes.SERVICE_NAME, "<your-service-name>",
ResourceAttributes.SERVICE_VERSION, "<your-version>",
ResourceAttributes.DEPLOYMENT_ENVIRONMENT, "<your-env>",
ResourceAttributes.HOST_NAME, "<your-host-name>"
)));
// OTLP HTTP エクスポーターを使用してトレーサープロバイダーを構築します
SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(OtlpHttpSpanExporter.builder()
.setEndpoint("<endpoint>") // 「前提条件」の項で取得したトレースエンドポイント
.build()).build())
.setResource(resource)
.build();
// SDK をグローバルに登録します
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
.setTracerProvider(sdkTracerProvider)
.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
.buildAndRegisterGlobal();
tracer = openTelemetry.getTracer("OpenTelemetry Tracer", "1.0.0");
}
private static Tracer tracer;
public static Tracer getTracer() {
return tracer;
}
}gRPC
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
public class OpenTelemetrySupport {
static {
// このサービスを記述するリソースを定義します
Resource resource = Resource.getDefault()
.merge(Resource.create(Attributes.of(
ResourceAttributes.SERVICE_NAME, "<your-service-name>",
ResourceAttributes.SERVICE_VERSION, "<your-version>",
ResourceAttributes.DEPLOYMENT_ENVIRONMENT, "<your-env>",
ResourceAttributes.HOST_NAME, "<your-host-name>"
)));
// OTLP gRPC エクスポーターを使用してトレーサープロバイダーを構築します
SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder()
.setEndpoint("<endpoint>") // 「前提条件」の項で取得した gRPC エンドポイント
.addHeader("Authentication", "<token>") // 「前提条件」の項で取得した認証トークン
.build()).build())
.setResource(resource)
.build();
// SDK をグローバルに登録します
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
.setTracerProvider(sdkTracerProvider)
.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
.buildAndRegisterGlobal();
tracer = openTelemetry.getTracer("OpenTelemetry Tracer", "1.0.0");
}
private static Tracer tracer;
public static Tracer getTracer() {
return tracer;
}
}ステップ 3:スパンの作成
トレーサーを使用して、親スパンと子スパンを作成します。各スパンは、属性やエラーステータスとともに、作業の単位をキャプチャします。
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.context.Scope;
public class Main {
public static void parentMethod() {
// 親スパンを開始します
Span span = OpenTelemetrySupport.getTracer().spanBuilder("parent span").startSpan();
try (Scope scope = span.makeCurrent()) {
span.setAttribute("good", "job");
childMethod();
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, "handle parent span error");
} finally {
span.end();
}
}
public static void childMethod() {
// 子スパンを開始します -- コンテキストを介して親に自動的にリンクされます
Span span = OpenTelemetrySupport.getTracer().spanBuilder("child span").startSpan();
try (Scope scope = span.makeCurrent()) {
span.setAttribute("hello", "world");
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, "handle child span error");
} finally {
span.end();
}
}
public static void main(String[] args) {
parentMethod();
}
}ステップ 4:アプリケーションの起動と確認
アプリケーションを起動し、 Managed Service for OpenTelemetry コンソール を開きます。 [Applications] ページでアプリケーション名をクリックし、トレースが表示されることを確認します。
メソッド 3: Java エージェントと SDK の組み合わせ
広範な自動カバレッジにはエージェントを使用し、ターゲットを絞ったカスタムスパンには SDK を使用します。エージェントは起動時に opentelemetry-sdk-extension-autoconfigure 依存関係を介して SDK を自動構成するため、メソッド 2 の OpenTelemetrySupport ヘルパークラスは不要です。
ステップ 1: エージェントのダウンロード
メソッド 1 のステップ 1 で説明しているように、OpenTelemetry Java エージェントをダウンロードします。
ステップ 2: Maven 依存関係の追加
メソッド 2 のステップ 1 の依存関係に加えて、次の内容を追加します:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-extension-annotations</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
<version>1.23.0-alpha</version>
</dependency>opentelemetry-sdk-extension-autoconfigure 依存関係は、エージェントの設定を SDK に自動的に転送するため、コード内でエクスポーターやリソース属性を構成する必要はありません。ステップ 3: トレーサーの取得
エージェントが SDK の初期化を処理するため、グローバルトレーサーを直接取得します:
OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
Tracer tracer = openTelemetry.getTracer("instrumentation-library-name", "1.0.0");ステップ 4: カスタム計装の追加
エージェントに加えて計装を追加するには、次の 3 つの手法があります。
手法 1: 自動作成されたスパンへの属性追加
既に計装されたメソッド内で Span.current() を呼び出し、ビジネス属性を追加します。
@RequestMapping("/async")
public String async() {
Span span = Span.current();
span.setAttribute("user.id", "123456");
userService.async();
child("vip");
return "async";
}手法 2: @WithSpan を使用したアノテーションベースの計装
メソッドに @WithSpan アノテーションを付与して、スパンを自動的に作成します。パラメーターを記録するには @SpanAttribute を使用します。
@WithSpan
private void child(@SpanAttribute("user.type") String userType) {
System.out.println(userType);
biz();
}手法 3: トレーサーを使用した手動でのスパン作成
完全な制御を行うには、トレーサー API でスパンを構築します。この例では、コンテキストを非同期スレッドに伝播させる方法も示しています。
private void biz() {
Tracer tracer = GlobalOpenTelemetry.get().getTracer("tracer");
Span span = tracer.spanBuilder("biz (manual)")
.setParent(Context.current().with(Span.current())) // オプション -- 自動的に設定されます
.startSpan();
try (Scope scope = span.makeCurrent()) {
span.setAttribute("biz-id", "111");
// コンテキストを非同期タスクに伝播
es.submit(() -> {
Span asyncSpan = tracer.spanBuilder("async")
.setParent(Context.current().with(span))
.startSpan();
try {
Thread.sleep(1000L); // 非同期タスクをシミュレート
} catch (Throwable e) {
// エラー処理
}
asyncSpan.end();
});
Thread.sleep(1000); // ビジネスロジックをシミュレート
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, "handle biz error");
} finally {
span.end();
}
}コントローラーとサービスの完全なコード:
コントローラー (com.alibaba.arms.brightroar.console.controller):
package com.alibaba.arms.brightroar.console.controller;
import com.alibaba.arms.brightroar.console.service.UserService;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.extension.annotations.SpanAttribute;
import io.opentelemetry.extension.annotations.WithSpan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
private ExecutorService es = Executors.newFixedThreadPool(5);
// 手法 1: 自動作成されたスパンへの属性追加
@RequestMapping("/async")
public String async() {
System.out.println("UserController.async -- " + Thread.currentThread().getId());
Span span = Span.current();
span.setAttribute("user.id", "123456");
userService.async();
child("vip");
return "async";
}
// 手法 2: アノテーションベースの計装
@WithSpan
private void child(@SpanAttribute("user.type") String userType) {
System.out.println(userType);
biz();
}
// 手法 3: 手動でのスパン作成
private void biz() {
Tracer tracer = GlobalOpenTelemetry.get().getTracer("tracer");
Span span = tracer.spanBuilder("biz (manual)")
.setParent(Context.current().with(Span.current()))
.startSpan();
try (Scope scope = span.makeCurrent()) {
span.setAttribute("biz-id", "111");
es.submit(new Runnable() {
@Override
public void run() {
Span asyncSpan = tracer.spanBuilder("async")
.setParent(Context.current().with(span))
.startSpan();
try {
Thread.sleep(1000L); // 非同期タスクをシミュレート
} catch (Throwable e) {
}
asyncSpan.end();
}
});
Thread.sleep(1000); // ビジネスロジックをシミュレート
System.out.println("biz done");
OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
openTelemetry.getPropagators();
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, "handle biz error");
} finally {
span.end();
}
}
}サービス (com.alibaba.arms.brightroar.console.service):
package com.alibaba.arms.brightroar.console.service;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Async
public void async() {
System.out.println("UserService.async -- " + Thread.currentThread().getId());
System.out.println("my name is async");
System.out.println("UserService.async -- ");
}
}ステップ 5: JVM パラメーターの構成とアプリケーションの起動
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=<your-service-name> \
-Dotel.exporter.otlp.headers=Authentication=<token> \
-Dotel.exporter.otlp.endpoint=<endpoint> \
-jar /path/to/your/app.jar例:
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=ot-java-agent-sample \
-Dotel.exporter.otlp.headers=Authentication=b590xxxxuqs@3a75d95xxxxx9b_b59xxxxguqs@53dxxxx2afe8301 \
-Dotel.exporter.otlp.endpoint=http://tracing-analysis-dc-bj:8090 \
-jar /path/to/your/app.jarOpenTelemetry Collector を介してトレースデータを転送するには、-Dotel.exporter.otlp.headers=Authentication=<token>を削除し、<endpoint>をオンプレミス環境の Collector のアドレスに設定してください。
Managed Service for OpenTelemetry コンソール を開きます。[Applications] ページでアプリケーション名をクリックし、トレースが表示されることを確認します。
サポート対象の Java フレームワーク
OpenTelemetry Java エージェントは、次のフレームワークを自動的に計装します。最新かつ完全な一覧については、 「Supported libraries, frameworks, application servers, and JVM」 をご参照ください。