すべてのプロダクト
Search
ドキュメントセンター

Simple Log Service:OpenTelemetry SDK for Androidを使用して、AndroidアプリからSimple Log Serviceにトレースデータをインポートする

最終更新日:Mar 14, 2025

このトピックでは、OpenTelemetry SDK for Javaを使用してAndroidアプリからSimple Log Serviceにトレースデータをインポートする方法について説明します。

前提条件

トレースインスタンスが作成されます。 詳細については、「トレースインスタンスの作成」をご参照ください。

ステップ1: SDKの統合

アプリまたはモジュールのbuild.gradleファイルに次の設定を追加します。

// The bill of materials (BOM) list that is used to synchronize dependency versions. 
implementation(platform("io.opentelemetry:opentelemetry-bom:1.22.0"))
// Call an API operation.
implementation("io.opentelemetry:opentelemetry-api")
implementation("io.opentelemetry:opentelemetry-context")
// API extensions
implementation("io.opentelemetry:opentelemetry-extension-kotlin")
// SDK
implementation('io.opentelemetry:opentelemetry-sdk')
implementation('io.opentelemetry:opentelemetry-sdk-logs')
// semantic conventions
implementation("io.opentelemetry:opentelemetry-semconv")
// Exporters
// Create an official gRPC exporter.
implementation("io.opentelemetry:opentelemetry-exporter-otlp")

詳細については、「OpenTelemetry Java SDKリリース」をご参照ください。

ステップ2: 権限の設定

トレースデータを報告するには、AndroidManifest.xmlファイルに次のアクセス許可ステートメントを追加して、ネットワークアクセス許可を申請する必要があります。

<uses-permission android:name="android.permission.INTERNET" />

ステップ3: SDKの初期化

ApplicationクラスのonCreateメソッドを呼び出してSDKを初期化することを推奨します。

// Initialize the exporter. The exporter is used to export trace data to a Log Service Logstore. 
OtlpGrpcSpanExporter grpcSpanExporter = OtlpGrpcSpanExporter.builder()
  .setEndpoint("https://${endpoint}") 
  .addHeader("x-sls-otel-project", "${project}")
  .addHeader("x-sls-otel-instance-id", "${instanceId}")
  .addHeader("x-sls-otel-ak-id", "${access-key-id}")
  .addHeader("x-sls-otel-ak-secret", "${access-key-secret}")
  .build();

// Initialize the tracer provider. The tracer provider is used to expose main API operations, preprocess spans, and configure custom clocks. 
// The custom rule that is used to generate TraceIds and SpanIds, and custom samplers. You can configure the settings based on your business scenario. 
SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
  .addSpanProcessor(BatchSpanProcessor.builder(grpcSpanExporter).build())
  .setResource(Resource.create(Attributes.builder()
                               .put(ResourceAttributes.SERVICE_NAME, "${service}")
                               .put(ResourceAttributes.SERVICE_NAMESPACE, "${service.namespace}")
                               .put(ResourceAttributes.SERVICE_VERSION, "${version}")
                               .put(ResourceAttributes.HOST_NAME, "${host}")
                               .put(ResourceAttributes.DEPLOYMENT_ENVIRONMENT, "${environment}")
                               .build()
                              )
              )
  .build();

// Initialize the OpenTelemetry SDK. 
OpenTelemetrySdk telemetrySdk = OpenTelemetrySdk.builder()
  .setTracerProvider(tracerProvider)
  .build(); // If you call the build() method to generate an instance, you must check whether to define the OpenTelemetry SDK as a global variable based on your business scenario. 

// You can also define a global variable named OpenTelemetrySdk. 
// OpenTelemetrySdk telemetrySdk = OpenTelemetrySdk.builder()
//    .setTracerProvider(tracerProvider)
//    .buildAndRegisterGlobal(); // You can call the GlobalOpenTelemetry.get() or GlobalOpenTelemetry.getTracer() method to access the instance.

変数

説明

${endpoint}

Simple Log Serviceプロジェクトのエンドポイント。 形式: ${region-endpoint}: ポート

  • ${region-endpoint}: プロジェクトが存在するリージョンのSimple Log Serviceエンドポイント。 Simple Log Serviceには、内部エンドポイントまたはパブリックエンドポイントを使用してアクセスできます。 内部エンドポイントは、クラシックネットワークまたは仮想プライベートクラウド (VPC) 経由でアクセスできます。 インターネット経由でパブリックエンドポイントにアクセスできます。 詳細については、「エンドポイント」をご参照ください。

  • Port: ポート番号。 値は10010に設定されており、変更できません。

cn-hangzhou.log.aliyuncs.com:10010

${project}

Simple Log Serviceプロジェクトの名前。

test-project

${instance}

トレースインスタンスのID。 詳細については、「トレースインスタンスの作成」をご参照ください。

テストトレース

${access-key-id}

Alibaba CloudアカウントのAccessKey ID。

Simple Log Serviceプロジェクトに対する書き込み権限のみを持つRAMユーザーのAccessKeyペアを使用することを推奨します。 AccessKey ペアは、AccessKey ID と AccessKey Secret で構成されます。 指定したプロジェクトの書き込み権限をRAMユーザーに付与する方法の詳細については、「カスタムポリシーを使用してRAMユーザーに権限を付与する」をご参照ください。 AccessKeyペアの取得方法については、「AccessKeyペア」をご参照ください。

なし

${access-key-secret}

Alibaba CloudアカウントのAccessKeyシークレット。

Simple Log Serviceプロジェクトに対する書き込み権限のみを持つRAMユーザーのAccessKeyペアを使用することを推奨します。

なし

${service.nameスペース}

サービスが属する名前空間。

order

${service}

サービスの名前です。 ビジネスシナリオに基づいて値を指定します。

payment

${version}

サービスのバージョンです。 va.b.c形式でバージョンを指定することを推奨します。

v0.1.2

${host}

ホスト名。

localhost

${environment}

デプロイ環境。 例: テスト環境または本番環境。 ビジネスシナリオに基づいて値を指定します。

ステップ4: SDKの使用

トレーサーの作成

ビジネスシナリオに基づいてトレーサーを作成することを推奨します。 トレーサーを作成するときは、インストルメンテーションスコープ名を指定する必要があります。 異なるトレースデータはスコープによって区別されます。

Tracer tracer = telemetrySdk.getTracer("otel application", "1.0.0");

ルートスパンの作成

スパンは、トランザクションにおける動作を示す。 各スパンは、操作名、開始タイムスタンプおよび終了タイムスタンプ、属性、イベント、およびコンテキストをカプセル化します。

final Span span = tracer.spanBuilder("root span").startSpan();
// do stuff
// ...
span.end();

ネストされたスパンの作成

ネストされた操作をスパンに関連付ける場合は、OpenTelemetryを使用して、オンプレミスプロセスおよびリモートプロセス間の操作スレッドを追跡できます。 この例では、methodBはmethodAによって呼び出されます。 スパンをネストするには、次の方法を使用します。

void methodA() {
  Span parentSpan = tracer.spanBuilder("operation A").startSpan();
  methodB(parentSpan);
  parentSpan.end();
}
void methodB(Span parentSpan) {
  Span childSpan = tracer.spanBuilder("operation B")
    .setParent(parentSpan)
    .startSpan();
  // do stuff
  childSpan.end();
}

OpenTelemetry APIは、親スパンを伝播するために使用される自動化されたメソッドも提供します。

void methodA() {
  Span parentSpan = tracer.spanBuilder("operation A").startSpan();
  try (Scope scope = parentSpan.makeCurrent()) {
    methodB();
  } finally {
    parentSpan.end();
  }
}

void methodB() {
  Span childSpan = tracer.spanBuilder("operation B").startSpan();
  // do stuff
  childSpan.end();
}

属性を持つスパンの作成

実行結果やその他の関連するビジネス情報などの属性を指定することで、スパン内の特定の操作のコンテキストを指定できます。

Span span = tracer.spanBuilder("GET /resource/catalog").setSpanKind(Span.Kind.CLIENT).startSpan();
span.setAttribute("http.method", "GET");
span.setAttribute("http.url", url.toString());

イベントを含むスパンの作成

複数のイベントを使用してスパンに注釈を付けることができます。

span.addEvent("start");
// do stuff
// ...
span.addEvent("end");

// A span can also carry attributes. 
Attributes eventAttributes = Attributes.of(
  "key1", AttributeValue.stringAttributeValue("value1"),
  "key2", AttributeValue.longAttributeValue(111L)
);
span.addEvent("End Computation", eventAttributes);

リンク付きスパンの作成

リンクを使用して、1つのスパンを1つ以上のスパンに関連付けることができます。

Link link1 = LinkData.create(parentSpan1.getContext());
Link link2 = LinkData.create(parentSpan2.getContext());
Span child = tracer.spanBuilder("child_with_link")
    .addLink(link1)
    .addLink(link2)
    .addLink(parentSpan3.getContext())
    .startSpan();

リモートプロセスからコンテキストを読み取る方法については、「コンテキストの伝播」をご参照ください。

スパンのステータス値の指定

StatusCode.UNSETStatusCode.OK、およびStatusCode.ERRORのいずれかのステータス値をスパンにアタッチできます。 UNSETはデフォルトのステータスを示します。 OKは、操作が完了したことを示します。 ERRORは、操作にエラーが含まれていることを示します。

Span span = tracer.spanBuilder("operation name").startSpan();

try (Scope scope = span.makeCurrent()) {
  // do stuff
} catch (Throwable t) {
  span.setStatus(StatusCode.ERROR, "Something bad happened!");
  throw t;
} finally {
  span.end(); // After you call the end() method, you cannot specify a status value for the span. 
}

例外をスパンに記録する

例外がキャプチャされた後、関連するスパンに例外を追加することを推奨します。 また、スパンのステータスを同時に更新することをお勧めします。

Span span = tracer.spanBuilder("operation name").startSpan();
try (Scope scope = span.makeCurrent()) {
  // do stuff
} catch (Throwable throwable) {
  span.setStatus(StatusCode.ERROR, "Something bad happened!");
  span.recordException(throwable)
} finally {
  span.end();
}

コンテキストの伝播

OpenTelemetryは、コンテキストを伝播するテキストベースのメソッドを提供します。 次の例は、HttpURLConnectionを使用してHTTPリクエストを開始する方法を示しています。

// Inject the context in the HTTP headers by using the HttpURLConnection Header setter.
TextMapSetter<HttpURLConnection> setter =
  new TextMapSetter<HttpURLConnection>() {
    @Override
    public void set(HttpURLConnection carrier, String key, String value) {
      // Insert the context as Header
      carrier.setRequestProperty(key, value);
    }
};

URL url = new URL("http://127.0.0.1:8088/resource/catalog");
Span httpSpan = tracer.spanBuilder("GET /resource/catalog").setSpanKind(SpanKind.CLIENT).startSpan();
try (Scope scope = httpSpan.makeCurrent()) {
  // Inject attributes to record the details of the HTTP request. 
  httpSpan.setAttribute(SemanticAttributes.HTTP_METHOD, "GET");
  httpSpan.setAttribute(SemanticAttributes.HTTP_URL, url.toString());
  HttpURLConnection transportLayer = (HttpURLConnection) url.openConnection();
  // Inject the current context into the HTTP request. 
  telemetrySdk.getPropagators().getTextMapPropagator().inject(Context.current(), transportLayer, setter);
  // do stuff
} finally {
  httpSpan.end();
}

OpenTelemetry SDKは、W3CトレースコンテキストHTTPヘッダーを使用したコンテキスト伝播をサポートしています。 詳細については、「W3CTraceContextPropagatorクラス」をご参照ください。

OpenTelemetry SDKの詳細については、「OpenTelemetryドキュメント」をご参照ください。

よくある質問

OpenTelemetry SDK for JavaがJava 8 + API機能を使用している場合、デバイスに次のエラーメッセージが表示されることがあります。

FATAL EXCEPTION: main
Process: xx.xx.xx.xx, PID: 2810
java.lang.NoClassDefFoundError: io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder$$ExternalSyntheticLambda0
	at io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder.<init>(OtlpGrpcSpanExporterBuilder.java:38)
	at io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter.builder(OtlpGrpcSpanExporter.java:39)

上記の問題を解決するには、AndroidアプリがAPIレベル26以前を実行するデバイスをサポートしている場合、coreLibraryDesugaringEnabledをオンにします。 詳細については、「core library desugaring」をご参照ください。

coreLibraryDesugaringEnabledをオンにすると、AndroidアプリはAPIレベル21以降を実行するデバイスをサポートできます。

説明

OpenTelemetry SDK for Javaは、21未満のAPIレベルを実行するデバイスをサポートしていません。