OpenTelemetry API を使用した Java カスタム インスツルメンテーション
概要
OpenTelemetry API を使用してアプリケーションを手動でインスツルメントする理由はいくつかあります。
ddtrace
ライブラリは、これらの目標を達成するためのさまざまなテクニックを提供しています。次のセクションでは、Datadog で使用するために OpenTelemetry API を使用してカスタムインスツルメンテーションを行う方法を説明します。
セットアップ
OpenTelemetry はバージョン 1.24.0 以降の Java でサポートされています。
OpenTelemetry を Datadog トレースプロバイダーを使用するように構成するには
自動インスツルメンテーションとセットアップの説明をまだお読みでない場合は、Java セットアップ手順からお読みください。
OpenTelemetry SDK ではなく OpenTelemetry API のみを依存関係に含めていることを確認してください。
システム プロパティ dd.trace.otel.enabled
または環境変数 DD_TRACE_OTEL_ENABLED
を true
に設定します。
スパンタグの追加
カスタムスパンタグを追加する
customer.id
などのアプリケーションコード内の動的な値に対応するカスタムタグをスパンに追加します。
import io.opentelemetry.api.trace.Span;
public void doSomething() {
Span span = Span.current();
span.setAttribute("user-name", "Some User");
}
すべてのスパンにグローバルにタグを追加する
dd.tags
プロパティを使用すると、アプリケーションに対して生成されたすべてのスパンにタグを設定できます。これは、アプリケーション、データセンター、または Datadog に表示したいその他のタグの統計をグループ化するのに役立ちます。
java -javaagent:<DD-JAVA-AGENT-PATH>.jar \
-Ddd.tags=datacenter:njc,<TAG_KEY>:<TAG_VALUE> \
-jar <YOUR_APPLICATION_PATH>.jar
子スパンからルートスパンにエラーを設定する
子スパンからルートスパンにエラーを設定するには、次のように現在のスパンで setStatus
メソッドを使用します。
import static io.opentelemetry.api.trace.StatusCode.ERROR;
import io.opentelemetry.api.trace.Span;
public void doSomething() {
Span span = Span.current();
span.setStatus(ERROR, "Some error details...");
}
子スパンからルートスパンにタグとエラーを設定する
この例では、子スパンからルートスパンにタグとエラーを設定する方法を示します。
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.ContextKey;
import io.opentelemetry.context.Scope;
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.ResourceAttributes;
import java.util.concurrent.TimeUnit;
public class Example {
private final static ContextKey<Span> CONTEXT_KEY =
ContextKey.named("opentelemetry-traces-local-root-span");
public void begin() {
tracer = GlobalOpenTelemetry.getTracer("my-scope", "0.1.0");
Span parentSpan = tracer.spanBuilder("begin").startSpan();
try (Scope scope = parentSpan.makeCurrent()) {
createChildSpan();
} finally {
parentSpan.end();
}
}
private void createChildSpan() {
Span childSpan = tracer.spanBuilder("child-span").startSpan();
try {
Span rootSpan = Context.current().get(CONTEXT_KEY);
if (null != rootSpan) {
rootSpan.setAttribute("my-attribute", "my-attribute-value");
rootSpan.setStatus(StatusCode.ERROR, "Some error details...");
}
} finally {
childSpan.end();
}
}
}
タグの追加
対応するフレームワークインスツルメンテーションを使用しない場合や、より深いアプリケーションのトレースをする場合、完全なフレームグラフのため、またはコードの断片の実行時間を測定するために、コードにカスタムインスツルメンテーションを追加できます。
アプリケーションコードの変更が不可能な場合は、環境変数 dd.trace.methods を使用してこれらのメソッドの詳細を記述します。
既存の @Trace または同様のアノテーションがある場合、またはアノテーションを使用して Datadog 内の不完全なトレースを完了する場合は、トレースアノテーションを使用します。
トレースアノテーションで説明されているように、OpenTelemetry の @WithSpan
アノテーションを使ってトレースを作成することもできます。
トレースアノテーション
メソッドに @WithSpan
を追加すると、OpenTelemetry と dd-java-agent.jar
の実行時にトレースされます。Agent がアタッチされていない場合、このアノテーションはアプリケーションに影響を与えません。
OpenTelemetry の @WithSpan
アノテーションは opentelemetry-instrumentation-annotations
の依存によって提供されます。
import io.opentelemetry.instrumentation.annotations.WithSpan;
public class SessionManager {
@WithSpan
public static void saveSession() {
// ここにメソッドの実装
}
}
新しいスパンを手動で作成する
現在のトレースコンテキスト内に新しいスパンを手動で作成するには
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
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.ResourceAttributes;
import java.util.concurrent.TimeUnit;
public class Example {
public void doSomething() {
Tracer tracer = GlobalOpenTelemetry.getTracer("my-scope", "0.1.0");
Span span = tracer.spanBuilder("my-resource").startSpan();
try (Scope scope = span.makeCurrent()) {
// 処理内容
} catch (Throwable t) {
span.recordException(t);
throw t;
} finally {
span.end();
}
}
}
スパン イベントの追加
スパン イベントを追加するには SDK バージョン 1.40.0 以上が必要です。
addEvent
API を使用してスパン イベントを追加できます。このメソッドには必須パラメーター name
があり、オプションで attributes
と timestamp
を受け取ります。メソッドは指定されたプロパティを持つ新しいスパン イベントを作成し、対象のスパンに関連付けます。
- Name [required]: イベント名を表す文字列。
- Attributes [optional]: 以下のプロパティを持つ 0 個以上のキーと値のペア。
- キーは空でない文字列である必要があります。
- 値として指定できるのは次のいずれかです。
- プリミティブ型: string、Boolean、number。
- 同一プリミティブ型の要素のみを含む配列 (例: string の配列)。
- 入れ子の配列や異なるデータ型を混在させた配列は使用できません。
- Timestamp [optional]: イベント発生時刻を表す UNIX タイムスタンプ。
Instant
オブジェクトを想定します。
以下の例は、スパンにイベントを追加するさまざまな方法を示しています。
Attributes eventAttributes = Attributes.builder()
.put(AttributeKey.longKey("int_val"), 1L)
.put(AttributeKey.stringKey("string_val"), "two")
.put(AttributeKey.longArrayKey("int_array"), Arrays.asList(3L, 4L))
.put(AttributeKey.stringArrayKey("string_array"), Arrays.asList("5", "6"))
.put(AttributeKey.booleanArrayKey("bool_array"), Arrays.asList(true, false))
.build();
span.addEvent("Event With No Attributes");
span.addEvent("Event With Some Attributes", eventAttributes);
詳細は OpenTelemetry 仕様 を参照してください。
例外の記録
例外を記録するには recordException
API を使用します。このメソッドには必須パラメーター exception
があり、オプションで UNIX timestamp
を受け取ります。標準化された例外属性を含む新しいスパン イベントを作成し、対象のスパンに関連付けます。
以下の例は、例外を記録するさまざまな方法を示しています。
span.recordException(new Exception("Error Message"));
span.recordException(new Exception("Error Message"),
Attributes.builder().put(AttributeKey.stringKey("status"), "failed").build());
詳細は OpenTelemetry 仕様 を参照してください。
トレースクライアントと Agent コンフィギュレーション
トレーシングクライアントと Datadog Agent の両方が、コンテキスト伝播のための追加構成オプションを提供します。また、ヘルスチェックに関連するトレースなど、計算されたメトリクスに含めたくないトレースについては、特定のリソースを Datadog へのトレース送信から除外することもできます。
ヘッダー抽出と挿入によるコンテキストの伝搬
分散型トレーシングのコンテキストの伝搬は、ヘッダーの挿入と抽出で構成できます。詳しくはトレースコンテキストの伝播をお読みください。
リソースのフィルター
トレースはそれぞれのリソース名に基づいて除外可能で、これによりヘルスチェックなどの外形監視トラフィックが Datadog にレポートされるトレースから削除されます。この設定およびその他のセキュリティ/微調整に関するコンフィギュレーションについてはセキュリティページまたは不要なリソースを無視するを参照してください。
その他の参考資料