Application Real-Time Monitoring Service (ARMS) のアプリケーションモニタリングを使用して一般的な Java フレームワークでアプリケーションをモニタリングする場合、ARMS エージェントはフレームワークを自動的にインストルメントします。ビジネスコードを変更することなく、トレース情報を収集できます。トレース情報にビジネス メソッドの実行ステータスを反映させるには、OpenTelemetry SDK for Java を使用して、コードにカスタム インストルメンテーション コードを追加できます。このトピックでは、SDK を使用してアプリケーションをインストルメントし、トレース コンテキスト、カスタム baggage、および属性をキャプチャする方法について説明します。
ARMS でサポートされているコンポーネントとフレームワークについては、「ARMS でサポートされている Java コンポーネントとフレームワーク」をご参照ください。
前提条件
アプリケーションは アプリケーションモニタリング でモニタリングされます。
ARMS エージェントは V2.9.1.2 以降です。このバージョンより前の場合は、更新 してください。
依存関係の追加
次の Maven 依存関係を追加して、OpenTelemetry SDK for Java を導入します。詳細については、「インストルメンテーション」をご参照ください。
<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-sdk</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-bom</artifactId>
<version>1.23.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
<dependencyManagement>ARMS と OpenTelemetry ベースのインストルメンテーションの互換性
用語
ここでは、一般的に使用される用語のみを紹介します。その他の名称については、「OpenTelemetry 仕様」をご参照ください。
Span:リモート呼び出しや内部メソッド呼び出しなど、リクエスト内の特定の操作。
SpanContext:traceId や spanId などの情報を含む、単一のリクエストトレースのコンテキスト。
Attribute:主要な情報を記録するために使用される、Span の追加の属性フィールド。
Baggage:トレース全体に伝搬されるキーと値のペア。
OpenTelemetry SDK for Java の使用
SDK を使用して、次の操作を実行できます。
インストルメンテーション コードを使用して新しい Span を作成する。
Span に属性を追加する。
トレース コンテキストで baggage 項目を伝搬する。
トレース コンテキストにアクセスし、traceId や spanId などの識別子を出力する。
次のサンプルコードは、SDK を使用して上記の操作を実行する方法を示しています。
SDK を使用して手動で作成された OpenTelemetry インスタンスを直接使用するのではなく、GlobalOpenTelemetry.get() メソッドを呼び出して OpenTelemetry インスタンスを取得する必要があります。そうしないと、SDK インストルメンテーションによって生成された Span データは、ARMS エージェント v4.x を使用すると表示されなくなります。
@RestController
@RequestMapping("/ot")
public class OpenTelemetryController {
private Tracer tracer;
private ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
@PostConstruct
public void init() {
OpenTelemetrySdk.builder()
.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
.buildAndRegisterGlobal();
tracer = GlobalOpenTelemetry.get().getTracer("manual-sdk", "1.0.0");
ses.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Span span = tracer.spanBuilder("schedule")
.setAttribute("schedule.time", System.currentTimeMillis())
.startSpan();
try (Scope scope = span.makeCurrent()) {
System.out.println("scheduled!"); // スケジュールされました!
Thread.sleep(500L);
span.setAttribute("schedule.success", true);
System.out.println(Span.current().getSpanContext().getTraceId()); // トレース ID を取得します。
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, t.getMessage());
} finally {
span.end();
}
}
}, 10, 30, TimeUnit.SECONDS);
}
@ResponseBody
@RequestMapping("/parent")
public String parent() {
Span span = tracer.spanBuilder("parent").setSpanKind(SpanKind.SERVER).startSpan();
try (Scope scope = span.makeCurrent()) {
// Baggage を使用して、サービスのカスタムタグを伝搬します。
Baggage baggage = Baggage.current().toBuilder()
.put("user.id", "1")
.put("user.name", "name")
.build();
try (Scope baggageScope = baggage.storeInContext(Context.current()).makeCurrent()) {
child();
}
span.setAttribute("http.method", "GET");
span.setAttribute("http.uri", "/parent");
} finally {
span.end();
}
return "parent";
}
private void child() {
Span span = tracer.spanBuilder("child").startSpan();
try (Scope scope = span.makeCurrent()) {
System.out.println("current traceId = " + Span.current().getSpanContext().getTraceId()); // 現在の traceId =
System.out.println("userId in baggage = " + Baggage.current().getEntryValue("user.id")); // baggage 内の userId =
Thread.sleep(1000);
} catch (Throwable e) {
span.setStatus(StatusCode.ERROR, e.getMessage());
} finally {
span.end();
}
}
}詳細:
initメソッドで、OpenTelemetryControllerのスケジュールされたタスクが ScheduledExecutorService を使用して開始されます。スケジュールされたタスクが開始されると、Span が作成され、タスクが終了するとこの Span が閉じられます。parentメソッドのOpenTelemetryControllerでは、OpenTelemetry SDK の複数のメソッドが呼び出されます。このメソッドが呼び出されるたびに、
parentという名前の Span が作成され、メソッドが終了するとこの Span が閉じられます。また、Baggage SDK を呼び出して、
user.idとuser.nameという名前の2 つの Baggage ペアを追加します。これらの2 つの Baggage は、ダウンストリーム アプリケーションに伝搬されます。手順 2.a で作成された Span に 2 つの属性が追加されます。
childメソッドのOpenTelemetryControllerでは、次の操作が実行されます。
エージェントバージョンの比較
次の表に示すように、ARMS エージェントのバージョンによって、上記の手順に対するサポートが異なります。
手順 | ARMS エージェント v4.x 以降 | ARMS エージェント v3.x 以前 |
1 | サポートされています。新しい Span が生成されます。 | サポートされています。新しい Span が生成されます。 |
2.1 | サポートされています | サポートされています |
2.2 | サポートされています | サポートされていません |
2.3 | サポートされています | サポートされています |
3.1 | サポートされています | サポートされています。手順 2.a で作成された Span のメソッドスタックとして、この span が使用されます。 |
3.2 | サポートされています。出力される traceId は、エージェントによって提供されるものと同じです。 | サポートされていません。出力される traceId は、エージェントによって提供されるものとは異なります。 |
3.2 | サポートされています | サポートされています |
インストルメンテーションの効果
ARMS エージェント v4.x 以降
手順 1:
OpenTelemetry SDK を介して生成された Span は正常に表示できます。

手順 2 と手順 3:
OpenTelemetry SDK によって生成された Span (赤いボックスで示されている) と Tomcat のインストルメンテーションによって生成された Span (黄色のボックスで示されている) は、同じトレースの一部です。OpenTelemetry SDK によって生成された Span に関連付けられた属性は正常に設定されています (青いボックスで示されている)。

ARMS エージェント v3.x 以降
手順 1:

手順 2 と手順 3:
OpenTelemetry SDK によって生成されたスパン(赤枠内)と Tomcat のイベントトラッキングによって生成されたスパン(黄枠内)は、同じトレースの一部です。これらのうち、
childという名前のスパンは、parentという名前のスパン内のメソッドスタックとして存在します。さらに、OpenTelemetry SDK によって生成されたスパンに関連付けられた属性が正常に設定されています(青枠内)。

関連手順
トレース ID をアプリケーション ビジネスログに関連付けることで、エラーをすばやく特定、分析、および解決するためにアクセスできます。