クライアントサイドのトレースでパフォーマンスをモニタリングする

Firestore リクエストをエンドツーエンドでモニタリングしてデバッグするには、クライアント ライブラリでトレースを有効にします。クライアントサイドのトレースでは、アプリケーションで発生したパフォーマンスに関するシグナルと、問題のデバッグに役立つ分析情報を提供できます。

クライアントサイドのトレースでは、クライアントからの RPC の実行によって収集され、次の情報を提供します。

  • クライアントが RPC リクエストを送信した時点やクライアントが RPC レスポンスを受信した時点のタイムスタンプを含むスパンで、ネットワークとクライアント システムによって発生したレイテンシが含まれます。
  • クライアントとその構成に関する情報を表示する属性(Key-Value ペア)
  • スパンのキーイベントに関連付けられたログ
  • クライアントでクラッシュが発生した場合のスタック トレース

OpenTelemetry

クライアント ライブラリのトレースは、OpenTelemetry API を使用して計測されます。OpenTelemetry は、業界標準のオープンソース化されたオブザーバビリティ フレームワークです。OpenTelemetry には、計測 API や SDK、コレクタ、バックエンド固有のエクスポータ、サンプリング制御やスパンの上限などの柔軟な構成オプションなど、幅広いツールが用意されています。

エクスポータとコレクタを使用してトレースをエクスポートする

構成の一環として、トレースをオブザーバビリティ バックエンドにエクスポートできます。ほとんどのオブザーバビリティ サービス プロバイダは、Cloud Trace など、使用できるエクスポータを用意しています。

OpenTelemetry では、エクスポータに加えて、Collector を設定することをおすすめします。Collector により、サービスがデータを迅速にオフロードできるようになります。また、Collector が再試行、バッチ処理、暗号化などの追加処理を行うことができます。Collector はアプリケーションとともに実行されます。Collector は OTLP メッセージを受信して処理し、オブザーバビリティ バックエンドにエクスポートします。

制限事項

クライアントサイド トレースには次の制限があります。

  • トレーススパンは、Java と Node.js のクライアント ライブラリで使用できます。
  • クライアント ライブラリは、リアルタイム リスナーのトレース スパンを生成しません。

課金

クライアントサイド トレースを行うと、Firestore の使用量に加えて費用が発生する場合があります。

トレースの収集や OpenTelemetry フレームワークの使用に対して料金は発生しません。

トレーススパンのオブザーバビリティ バックエンドへの取り込みに料金が発生する可能性があります。たとえば、バックエンドとして Cloud Trace を使用する場合は、Cloud Trace の料金に沿って課金されます。別のオブザーバビリティ サービス プロバイダを使用している場合は、その課金モデルと関連費用を確認します。

課金について把握するには、トラフィックに基づいて小さなトレース サンプリング比率(RPC の一部をトレース)から始めます。

始める前に

始める前に:

  • アプリがオブザーバビリティ バックエンドにトレースを書き込むサービス アカウントに、必要な Identity and Access Management ロールが設定されていることを確認します。

    トレース オペレーション IAM ロール
    トレースを読み取る roles/cloudtrace.user
    トレースに書き込む roles/cloudtrace.agent
    読み取り/書き込みトレース roles/cloudtrace.admin
  • このプロジェクトで Trace API が有効になっていることを確認します。

クライアント側トレースを構成する

このセクションでは、クライアントサイド トレースの構成例を示します。コレクタにエクスポートすることも、オブザーバビリティ バックエンドに直接エクスポートすることもできます。クライアントサイド トレースを構成するには、次のオプションもあります。

OpenTelemetry API を使用してトレースをコレクタにエクスポートする

次のコードは、10% のサンプリング率でスパンを OpenTelemetry Collector にエクスポートするようにクライアント ライブラリを構成します。

Java(管理)

Resource resource = Resource
  .getDefault().merge(Resource.builder().put(SERVICE_NAME, "My App").build());

OtlpGrpcSpanExporter otlpGrpcSpanExporter =
  OtlpGrpcSpanExporter
  .builder()
  .setEndpoint("http://localhost:4317") // Replace with your OTLP endpoint
  .build();

// Using a batch span processor
// You can also use other `BatchSpanProcessorBuilder` methods
// to further customize.
BatchSpanProcessor otlpGrpcSpanProcessor =
  BatchSpanProcessor.builder(otlpGrpcSpanExporter).build();

// Export to a collector that is expecting OTLP using gRPC.
OpenTelemetrySdk otel = OpenTelemetrySdk.builder()
        .setTracerProvider(
          SdkTracerProvider.builder()
            .setResource(resource)
            .addSpanProcessor(otlpGrpcSpanProcessor)
            .setSampler(Sampler.traceIdRatioBased(0.1))
            .build())
          .build();

Firestore firestore = FirestoreOptions
  .newBuilder()
  .setOpenTelemetryOptions(
    FirestoreOpenTelemetryOptions.newBuilder()
      .setTracingEnabled(true)
      .setOpenTelemetry(otel)
      .build())
  .build().getService();

    
Node.js(管理)

import { trace } from "@opentelemetry/api";
import {GrpcInstrumentation} from '@opentelemetry/instrumentation-grpc';

import pkg1 from "@opentelemetry/sdk-trace-node";
import pkg2 from "@opentelemetry/instrumentation";
import pkg3 from "@opentelemetry/exporter-trace-otlp-grpc";

const { NodeTracerProvider, BatchSpanProcessor, TraceIdRatioBasedSampler } = pkg1;
const { registerInstrumentations } = pkg2;
const { OTLPTraceExporter } =  pkg3;

const provider = new NodeTracerProvider(
  // Provide your chosen NodeTracerConfig such as sampler and span limit
  {
    sampler: new TraceIdRatioBasedSampler(0.1),
  }
);
provider.addSpanProcessor(new BatchSpanProcessor(new OTLPTraceExporter()));
provider.register();

// If you'd like to see gRPC spans (recommended), enable GrpcInstrumentation
registerInstrumentations({
  instrumentations: [
    new GrpcInstrumentation(
      // (optional): you can add GrpcInstrumentationConfig here
    ),
  ],
});


const settings: Settings = {
  projectId: 'my-project-id',
  preferRest: false,
  openTelemetry: {
    tracerProvider: trace.getTracerProvider()
  }
};

// Initialize Firestore
const firestore = new Firestore(settings);
// Add app code here

// Make sure to shut down your TracerProvider to flush any traces left in memory.
process.on('SIGINT', async () => {
  await provider
        .shutdown()
        .catch(error => console.error('Error terminating NodeTracerProvider:', error));
});
    

OpenTelemetry API を使用してオブザーバビリティ バックエンドに直接エクスポートする

オブザーバビリティ サービス プロバイダが OTLP 取り込みをサポートしている場合は、その OpenTelemetry エクスポータを使用して、トレースをバックエンドに直接エクスポートできます。次のコードは、トレース サンプリング率が 10% で、トレーススパンを Cloud Trace に直接エクスポートするようにクライアント ライブラリを構成します。

Java(管理)

// TraceExporter needed for this use case
import com.google.cloud.opentelemetry.trace.TraceExporter;

Resource resource = Resource
  .getDefault().merge(Resource.builder().put(SERVICE_NAME, "My App").build());
SpanExporter gcpTraceExporter = TraceExporter.createWithDefaultConfiguration();

// Using a batch span processor
// You can also use other `BatchSpanProcessorBuilder` methods
// to further customize.
SpanProcessor gcpBatchSpanProcessor =
  BatchSpanProcessor.builder(gcpTraceExporter).build();

// Export directly to Cloud Trace with 10% trace sampling ratio
OpenTelemetrySdk otel = OpenTelemetrySdk.builder()
        .setTracerProvider(SdkTracerProvider.builder()
            .setResource(resource)
            .addSpanProcessor(gcpBatchSpanProcessor)
            .setSampler(Sampler.traceIdRatioBased(0.1))
            .build())
        .build();

Firestore firestore = FirestoreOptions
  .newBuilder()
  .setOpenTelemetryOptions(
    FirestoreOpenTelemetryOptions.newBuilder()
      .setTracingEnabled(true)
      .setOpenTelemetry(otel)
      .build())
  .build().getService();

    
Node.js(管理)

import { trace } from "@opentelemetry/api";
import {GrpcInstrumentation} from '@opentelemetry/instrumentation-grpc';
import { TraceExporter } from "@google-cloud/opentelemetry-cloud-trace-exporter";

import pkg1 from "@opentelemetry/sdk-trace-node";
import pkg2 from "@opentelemetry/instrumentation";

const { NodeTracerProvider, BatchSpanProcessor, TraceIdRatioBasedSampler } = pkg1;
const { registerInstrumentations } = pkg2;

const provider = new NodeTracerProvider(
  // Provide your chosen NodeTracerConfig such as sampler and span limits
  {
    sampler: new TraceIdRatioBasedSampler(0.1),
  }
);
provider.addSpanProcessor(new BatchSpanProcessor(new TraceExporter()));
provider.register();

// If you'd like to see gRPC spans (recommended), enable GrpcInstrumentation
registerInstrumentations({
  instrumentations: [
    new GrpcInstrumentation(
      // (optional): you can add GrpcInstrumentationConfig here
    ),
  ],
});


const settings: Settings = {
  projectId: 'my-project-id',
  preferRest: false,
  openTelemetry: {
    tracerProvider: trace.getTracerProvider()
  }
};

// Initialize Firestore
const firestore = new Firestore(settings);
// ...

// Make sure to shut down your TracerProvider to flush any traces left in memory.
process.on('SIGINT', async () => {
  await provider
        .shutdown()
        .catch(error => console.error('Error terminating NodeTracerProvider:', error));
});
    

ゼロコード インストルメンテーション

コードを変更せずにトレースを構成するには、次の手順を行います。

Java(管理)
自動エージェントを使用すると、コードを変更せずにトレースを構成できます。環境変数 FIRESTORE_ENABLE_TRACING=ON を設定する必要があります。また、エージェントの構成で説明されているように、他の構成設定も設定する必要があります。次の例をご覧ください。

自動エージェントを使用してコレクタにエクスポートする

OTLP gRPC レシーバーを有効にして OpenTelemetry Collector を実行します。エージェントのエクスポーターを otlp に設定し、エージェントがデータをエクスポートするエンドポイントを指定します。次の例では、サンプリング率を 10% に設定し、localhost ポート 4317 でリッスンする Collector にトレースを送信します。


FIRESTORE_ENABLE_TRACING=ON                            \
java                                                   \
-javaagent:path/to/opentelemetry-javaagent.jar         \
-Dotel.traces.exporter=otlp                            \
-Dotel.exporter.otlp.endpoint="http://localhost:4317"  \
-Dotel.traces.sampler=traceidratio                     \
-Dotel.traces.sampler.arg=0.1                          \
-Dotel.service.name="My App"                           \
-jar myapp.jar

自動エージェントを使用してオブザーバビリティ バックエンドに直接エクスポートする

環境変数 FIRESTORE_ENABLE_TRACING=ON の設定に加えて、特定のバックエンド用の OpenTelemetry Java エージェント拡張機能を追加する必要があります。次の例では、Trace エクスポータ拡張機能と 10% のトレース サンプリング率を使用します。


FIRESTORE_ENABLE_TRACING=ON                                                \
java                                                                       \
-javaagent:path/to/opentelemetry-javaagent.jar                             \
-Dotel.javaagent.extensions=/path/to/exporter-auto-0.26.0-alpha-shaded.jar \
-Dotel.traces.exporter=google_cloud_trace                                  \
-Dotel.traces.sampler=traceidratio                                         \
-Dotel.traces.sampler.arg=0.1                                              \

    
Node.js(管理)

ゼロコード計測を設定するには、JavaScript 計測に関する OpenTelemetry の手順に沿って操作します。次のコード スニペット例では、計測を有効にして、トレースを OpenTelemetry コレクタに送信します。


npm install @opentelemetry/api
npm install @opentelemetry/auto-instrumentations-node


env \
FIRESTORE_ENABLE_TRACING=ON \
OTEL_TRACES_EXPORTER=otlp \
OTEL_NODE_ENABLED_INSTRUMENTATIONS="http,grpc" \
OTEL_NODE_RESOURCE_DETECTORS="none" \
node --require @opentelemetry/auto-instrumentations-node/register my_app.js

    

トレースの例

次の例は、Cloud Trace でトレース情報がどのように表示されるかを示しています。使用可能な属性と値の詳細については、トレース スパンの属性とイベントをご覧ください。

トレース スパンの例

Cloud Trace で表示されたトレーススパン

イベントログの例

Cloud Trace から見たトレース スパン イベントログ

属性値の例

Cloud Trace から見たトレーススパンの属性値

スタック トレースと例外イベントの例

Cloud Trace で表示されたスタック トレース

Cloud Trace で表示された例外イベント

次のステップ