トレーシングとは、分散システムを通るリクエストの流れを観測する手法であり、各処理ステップがタイムスタンプ付きの個別イベントとして記録されます。OpenTelemetry、2025によると、トレースはエントリーポイントから最終レスポンスまでのリクエストの完全なパスを結合し、すべてのマイクロサービスと外部呼び出しを通過します。これにより、開発者は複雑なモバイルバックエンドアーキテクチャにおけるボトルネック、遅延、障害を特定できます。
重要なポイント
トレーシングは、各受信リクエストをシステムのすべてのサービスとコンポーネントを通じて追跡する分散観測手法です。集約値を表示するメトリクス(平均応答時間、エラー数)とは異なり、トレーシングは単一の特定リクエストの完全なコンテキストを保存します。
各処理ステップ(データベース呼び出し、別のマイクロサービスへのHTTPリクエスト、バックグラウンドタスクの実行)は、タイムスタンプ、ステータス、属性を持つ個別のユニットとして記録されます。Google Dapper(2010年のオリジナル論文)によると、トレーシングにより分散システム内の遅延を単一呼び出しの精度で特定できます。
トレーシングは、バックエンドが数十のマイクロサービスで構成されるモバイルアプリケーションにとって特に重要です。アカウントへのログインなどのユーザーアクションは、APIゲートウェイ、認証サービス、データベース、プッシュサービスを通過する可能性があります。トレーシングがなければ、どのコンポーネントが応答を遅くしているかを特定することはほぼ不可能です。
トレーシングの基本単位はスパンです。各スパンは1つの論理操作(HTTPリクエスト、SQLクエリ、gRPC呼び出し、JSONシリアライゼーション)を表します。スパンには、一意の識別子、親識別子、操作名、開始時間、期間、ステータス、および一連の属性が含まれます。
同じルートリクエストに関連するすべてのスパンはトレースにグループ化されます。ルートスパンはエントリーポイント(モバイルクライアントからAPIへのHTTPリクエスト)を表します。子スパンはツリーを形成し、各スパンはparent_span_idフィールドを通じて親を参照します。
トレースの期間は、すべてのスパンの一意の時間セグメントの期間の合計に等しくなります。2つの子スパンが並行して実行される場合、それらの時間は合計されません。これは、並行するマイクロサービス呼び出しによって引き起こされる遅延を正しく分析するために重要です。
各スパンには属性(メタ情報を含むキーと値のペア:リクエストURL、ユーザーID、APIバージョン、ホスト名)を含めることができます。属性はトレースのフィルタリングとグループ化に使用されます。属性に加えて、スパンはイベント(「キャッシュミス」や「接続再試行」などのテキスト説明付きのタイムスタンプ)をサポートします。
分散トレーシングは、異なるプロセスや異なるマシンで作成されるスパンをリンクする問題を解決します。このメカニズムはコンテキスト伝搬に基づいています。サービスAがサービスBを呼び出すとき、現在のトレースIDと親スパンIDを含むヘッダーが送信リクエストに追加されます。
標準のコンテキスト伝搬プロトコルは、W3C Trace Context(traceparentおよびtracestateヘッダー)とZipkin B3(X-B3-TraceId、X-B3-SpanIdヘッダー)です。W3C Trace Contextは2021年にW3Cコンソーシアムによって標準として採用され、すべての主要なテレメトリプロバイダーによってサポートされています。
リクエストを受信すると、サービスBはヘッダーからtrace_idを抽出し、そのtrace_idで子スパンを作成します。これにより、リクエストが完了した後、異なるサービスのすべてのスパンがコレクター側で1つのトレースに結合されます。これには、各サービスが同じトレーシングライブラリでインストルメント化されている必要があります。
モバイル開発では、コンテキスト伝搬はバックエンドだけでなくクライアント・サーバー間の相互作用もカバーします。モバイルアプリケーションは各APIリクエストのヘッダーにtrace_idを送信でき、クライアントアクションをサーバー側の処理にリンクできます。iOSおよびAndroid向けのOpenTelemetry SDKは、HTTPクライアントを通じたトレースコンテキストの自動生成と伝搬をサポートしています。
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.context.Context
class TracingInterceptor : Interceptor {
private val tracer: Tracer = OpenTelemetry.getTracer("mobile-app")
override fun intercept(chain: Interceptor.Chain): Response {
val span = tracer.spanBuilder("HTTP POST /api/login")
.setParent(Context.current())
.startSpan()
return chain.proceed(chain.request())
.also { span.end() }
}
}
提示されたKotlinインターセプターは、サーバーへの各HTTPリクエストに対してスパンを作成します。親コンテキストはContext.current()を介して呼び出し元コードから伝搬され、クライアント側のトレーシングをサーバー側のトレーシングにリンクできます。
OpenTelemetryはトレースデータ収集のデファクトスタンダードです。スパンを生成するための統一API、一般的なライブラリの自動インストルメンテーション、およびさまざまなバックエンド(Jaeger、Zipkin、Grafana Tempo、Datadog、New Relic)へのデータエクスポートのための柔軟なメカニズムを提供します。
OpenTelemetryは一般的なフレームワーク(Spring Boot、Ktor、Flask、Express、gRPC)の自動スパン作成をサポートしています。開発者はプロジェクトに依存関係を追加するだけで、ライブラリが自動的に受信および送信リクエストをインターセプトします。Javaの自動インストルメンテーションは、ソースコードを変更せずにバイトコードを動的に変更するjavaagentを使用します。
モバイルプラットフォーム向けに、OpenTelemetryはSwift SDKとKotlin SDKを提供しています。これらはネットワークリクエスト(URLSession、OkHttp)、データベース操作(CoreData、Room)、バックグラウンドタスクのスパンを自動的に作成します。開発者はビジネスロジック用のカスタムスパンを追加できます。
収集されたスパンはOTLP(OpenTelemetry Protocol)を介してコレクターに送信されます。コレクターはデータをバッファリング、フィルタリング、および1つ以上のストレージシステムに転送できます。OpenTelemetryのドキュメントによると、gRPCエクスポートを使用した場合のスパン生成からダッシュボード表示までの標準的なレイテンシは2~5秒です。
import OpenTelemetryApi
import OpenTelemetrySdk
import URLSessionInstrumentation
let instrumentation = URLSessionInstrumentation()
instrumentation.enable()
let tracer = OpenTelemetry.instance.tracerFactory
.get("mobile-monitoring")
let span = tracer.spanBuilder("fetch-user-profile")
.setAttribute(key: "user.id", value: userId)
.startSpan()
span.end()
Swiftコードはネットワーキングレイヤーの自動インストルメンテーションをアクティブにし、ユーザープロファイル取得操作のカスタムスパンを作成します。user.id属性により、後で特定のユーザーでトレースをフィルタリングできます。
高負荷システムでは、すべてのリクエストをトレースすることは不可能です。ストレージとネットワークに許容できない負荷がかかります。サンプリングは、トレースの一部のみを保存することでこの問題を解決します。戦略の選択は、データの完全性とインフラストラクチャコストに直接影響します。
トレースを保存する決定は、その作成時(ルートスパン)に行われます。最もシンプルで一般的なアプローチ:リクエストの一定割合(例:5%)を保存し、残りは破棄します。欠点は、まれなエラーが確実にキャプチャされるとは限らないことです。OpenTelemetryのProbability samplerは0.0から1.0までの確率設定をサポートしています。
決定はトレースのすべてのスパンが完了するまで延期されます。アナライザーがトレースにエラー、時間超過、または興味深い属性が含まれているかを評価し、その場合にのみ保存します。このアプローチではコレクター内のすべてのスパンをバッファリングする必要があり、メモリ消費が増加します。Grafana Labsによると、テールベースサンプリングは、まれだが重大なエラーが発生するシステムにおいて、「有用なデータあたりのコスト」の点で40~60%効率的です。
| 戦略 | メリット | デメリット |
|---|---|---|
| 固定確率 | シンプルさ、予測可能な負荷 | まれなイベントを見逃す |
| レート制限 | 保証されたデータ量 | 不均一なカバレッジ |
| テールベース | すべてのエラーをキャプチャ | 高いメモリ消費 |
| アダプティブ | コストとカバレッジのバランス | 複雑な設定 |
ロギングは重要度レベル(info、warn、error)を持つ個別のイベントを記録しますが、それらを単一のリクエストのコンテキストにリンクしません。一方トレーシングは、エンドツーエンドのリクエストに属する操作の構造化されたツリーを作成します。実際には、これら2つのアプローチは相互排他的ではなく、相互補完的です。
ログは特定のエラーの詳細な分析に効果的です。開発者は正確なメッセージ、スタックトレース、変数値を確認できます。トレーシングは「なぜリクエストに5秒かかるのか」という質問に答えます。どのマイクロサービスまたは呼び出しが最も時間を消費したかを示します。Honeycomb(2024)によると、トレーシングとロギングを組み合わせて使用するチームは、インシデントの根本原因を2.3倍速く発見します。
最新のアプローチであるオブザーバビリティは、トレーシング、メトリクス、ログを1つのシステムに統合します。OpenTelemetryはこれら3つのシグナル間の相関をサポートしています。各スパンは関連ログへのリンクを含めることができ、メトリクスは特定のトレースにドリルダウンするためにtrace_idでタグ付けできます。
よくある質問
モニタリングはシステムの集約メトリクス(平均応答時間、1分あたりのエラー数、CPU負荷)を表示します。トレーシングはすべてのコンポーネントを通る単一の特定リクエストのパスを表示します。モニタリングは「何が起きているか」に答え、トレーシングは「なぜ起きているか」に答えます。
本番システムでは、ヘッドベースサンプリングで1~5%のリクエストで十分です。システムがめったにエラーを生成しない場合は、すべてのエラートレースのキャプチャに焦点を当てたテールベースサンプリングをお勧めします。ステージング環境では、制限なく100%のリクエストをトレースしても問題ありません。
主なツールは次のとおりです。Jaeger(Uberによるソリューション、オープンソース)、Grafana Tempo(スケーラブルなトレースストレージ)、Datadog APM、New Relic Distributed Tracing、AWS X-Ray、Honeycomb。これらはすべて、データ取り込みにOpenTelemetry標準をサポートしています。
はい。ローカルトレーシングは単一プロセス内で機能します。iOSおよびAndroid向けのOpenTelemetry SDKは、データベース読み取り、画像処理、ネットワークリクエストなどのローカル操作のスパンを作成します。これらのトレースは分散されていませんが、クライアント側のパフォーマンス診断に役立ちます。
最新のトレーシングライブラリは、ヘッドベースサンプリングで1%未満のオーバーヘッドを追加します。OpenTelemetryはメインスレッドをブロックしない非同期データエクスポートを使用します。モバイルデバイスの場合は、スパン作成の頻度を制限し、アダプティブサンプリング戦略を使用することをお勧めします。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。