•12 min read

OpenTelemetryによる分散トレーシング

OpenTelemetryによる分散トレーシング

現代のソフトウェアアーキテクチャがマイクロサービスやサーバーレスパラダイムへと移行するにつれて、システムの監視、モニタリング、デバッグの複雑さは飛躍的に増大しています。単一のユーザーリクエストが数十のマイクロサービス、データベース、外部APIを横断する場合、従来のロギングメトリクスを使用して障害の原因やパフォーマンスのボトルネックを特定することはほぼ不可能です。ここで分散トレーシング(distributed tracing)が役立ち、OpenTelemetryはオブザーバビリティ(observability)のための決定的なオープンソース標準として登場しました。

この詳細な解説では、OpenTelemetryのアーキテクチャ基盤を探り、分散トレーシングが根本的なレベルでどのように機能するかを理解し、アプリケーションのインスツルメンテーション、コンテキストの伝播、分析のためのテレメトリーデータのエクスポート方法を検討します。

Audio Briefing
0:00 / 0:00

トレースの構造

OpenTelemetryを理解するには、まず分散トレースの基本的な構成要素であるトレースとスパンを理解する必要があります。

トレースは、分散システム内を移動するリクエストの全行程を表します。これは、スパンの有向非巡回グラフ(DAG)です。

スパンは、トレースの基本的な構成要素です。データベースクエリ、HTTPリクエスト、関数呼び出しなど、トレース内の単一の操作を表します。すべてのスパンには、一連の構造化データが含まれています。

  • 操作名: 操作の人間が読める説明(例: GET /users/:id)。
  • 開始時刻と終了時刻: 操作の正確な期間を示すタイムスタンプ。
  • スパンID: スパン自体の一意の識別子。
  • トレースID: トレース内のすべてのスパンで共有される、トレース全体の一意の識別子。
  • 親スパンID: この操作をトリガーしたスパンのID。これにより、トレーシングシステムは階層と因果関係(DAG)を構築できます。スパンに親がない場合、それはルートスパンと見なされます。
  • 属性: 追加のコンテキストを提供するキーと値のペア(例: http.status_code、db.statement、user.id)。
  • イベント: スパンのライフスパン内で特定の出来事を記録するのに役立つ、タイムスタンプ付きのログまたはアノテーション。
  • ステータス: 成功または失敗のインジケーター(例: OKまたはERROR)。

これらのスパンをトレースIDと親子関係に基づいて組み立てることで、オブザーバビリティプラットフォームは完全な実行パスを視覚化し、レイテンシー、ボトルネック、エラーを特定できます。

Advertisement

OpenTelemetryのアーキテクチャ

OpenTelemetry(OTelと略されることが多い)はバックエンドシステムではありません。テレメトリーデータ(トレース、メトリクス、ログ)の生成、収集、エクスポートのために設計された、ベンダーニュートラルなAPI、SDK、およびツールセットです。コアアーキテクチャは、いくつかの主要なコンポーネントで構成されています。

1. API (Application Programming Interface)

APIは、コードをインスツルメントするために使用される言語に依存しないインターフェースを提供します。スパン、メトリクス、ログを生成するために必要な抽象データ型と操作を定義します。APIが実装から分離されているため、ライブラリの作成者は、エンドユーザーに特定のインプリメンテーションを強制することなく、OpenTelemetryのインスツルメンテーションをコードに追加できます。

2. SDK (Software Development Kit)

SDKは、APIの言語固有の実装です。APIによって生成されたテレメトリーデータを処理、サンプリング、エクスポートするための具体的なロジックを提供します。SDKは、次のような概念を処理します。

  • サンプリング: オーバーヘッドとストレージコストを削減するために、どのトレースをキャプチャしてエクスポートするかを決定します(例: ヘッドベースサンプリング、テールベースサンプリング)。
  • プロセッサー: エクスポートする前にスパンを変換またはフィルタリングします(例: ネットワーク効率を向上させるためにスパンをバッチ処理する)。
  • エクスポーター: 処理されたデータを指定されたバックエンドまたはコレクターに送信します(例: OTLPエクスポーター、Jaegerエクスポーター、Prometheusエクスポーター)。

3. OpenTelemetry Collector

OpenTelemetry Collectorは、テレメトリーデータを受信、処理、エクスポートできる、非常に汎用性の高いベンダーニュートラルなプロキシです。アプリケーションはデータをバックエンドに直接エクスポートできますが、Collectorを使用することが推奨されるアーキテクチャパターンです。Collectorは、多様な環境でテレメトリーを処理する統一された方法を提供し、アプリケーションをオブザーバビリティバックエンドから分離します。

Collectorはパイプラインアーキテクチャを使用して動作します。

  • レシーバー: さまざまな形式(例: OTLP、Jaeger、Zipkin、Prometheus)でテレメトリーデータを受け入れます。
  • プロセッサー: 転送中のデータを変更、フィルタリング、またはエンリッチします。一般的なユースケースには、バッチ処理、個人識別情報(PII)の削除、環境属性の追加(例: kubernetes.cluster.name)などがあります。
  • エクスポーター: 処理されたデータを1つ以上のオブザーバビリティバックエンド(例: DataDog、Honeycomb、AWS X-Ray、Elasticsearch)に送信します。

Collectorをサイドカーまたは中央ゲートウェイとしてデプロイすることで、組織はアプリケーションコードを変更することなく、簡単な設定変更でオブザーバビリティベンダーを切り替えたり、データを複数の宛先に送信したりできます。

コンテキスト伝播: 分散トレーシングの接着剤

分散トレーシングにおける最も複雑な課題の1つは、ネットワーク境界を越えてトレースの連続性を維持することです。サービスAがサービスBにHTTPリクエストを行うとき、サービスBは特定のトレースに参加していることをどのように知るのでしょうか?

その答えがコンテキスト伝播です。

コンテキスト伝播は、トレース識別子と状態が独立したサービス間で渡されるメカニズムです。これは、クライアント側で通信プロトコル(例: HTTPヘッダー、gRPCメタデータ、Kafkaメッセージヘッダー)のヘッダーにトレーシングメタデータを挿入し、サーバー側でそれを抽出することによって実現されます。

OpenTelemetryは、標準的な伝播形式、特にW3C Trace Context仕様をサポートしています。W3C Trace Contextは、2つの重要なHTTPヘッダーを標準化しています。

  • traceparent: トレースID、親スパンID、およびサンプリングフラグが含まれます。形式: 00-{trace-id}-{parent-span-id}-{trace-flags}。
  • tracestate: ベンダー固有のトレーシング情報を提供し、複数のトレーシングシステムがシームレスに相互運用できるようにします。

さらに、OpenTelemetryはBaggageをサポートしています。これは、任意のキーと値のペア(例: tenant_idまたはuser_role)をトレース全体に伝播するメカニズムです。単一のスパンに限定されるスパン属性とは異なり、Baggageアイテムはすべての後続サービスにダウンストリームに流れ、横断的なビジネスコンテキストへの深いオブザーバビリティを可能にします。

アプリケーションのインスツルメンテーション

インスツルメンテーションとは、テレメトリーを生成するためにOpenTelemetryをアプリケーションに統合するプロセスです。OpenTelemetryは、主に2つのアプローチを提供します。

自動インスツルメンテーション

多くの言語(Java、Python、Node.js、.NETなど)では、OpenTelemetryは自動インスツルメンテーションエージェントまたはライブラリを提供しています。これらのツールは、バイトコード操作、モンキーパッチ、またはランタイムフックを使用して、コード変更を必要とせずに、一般的なフレームワーク、HTTPクライアント、およびデータベースドライバーを自動的にインスツルメントします。これにより、エッジツーエッジのトレースを簡単にキャプチャでき、すぐに価値が得られます。

手動インスツルメンテーション

自動インスツルメンテーションは確かなベースラインを提供しますが、ビジネス固有の深いオブザーバビリティを得るには、手動インスツルメンテーションが必要です。これには、アプリケーションコード内でOpenTelemetry APIを直接使用して、カスタムスパンを作成し、ビジネスに関連する属性を追加し、特定のイベントを記録することが含まれます。

from opentelemetry import trace

# Acquire a tracer
tracer = trace.get_tracer(__name__)

def process_payment(order_id: str, amount: float):
    # Start a new span manually
    with tracer.start_as_current_span("process_payment") as span:
        # Add attributes to the span
        span.set_attribute("payment.order_id", order_id)
        span.set_attribute("payment.amount", amount)
        
        try:
            # Simulate processing logic
            result = invoke_payment_gateway(amount)
            span.set_attribute("payment.status", "success")
            span.add_event("Payment successfully processed by gateway.")
            return result
        except Exception as e:
            # Record the exception and mark the span as failed
            span.record_exception(e)
            span.set_status(trace.StatusCode.ERROR, "Payment processing failed")
            raise

広範なカバレッジのための自動インスツルメンテーションと、深いドメイン固有の洞察のための手動インスツルメンテーションを組み合わせることで、エンジニアリングチームは包括的なオブザーバビリティを実現できます。

Advertisement

OTLPプロトコルの力

OpenTelemetryの相互運用性の中心にあるのは、OpenTelemetry Protocol(OTLP)です。OTLPは、SDK、Collector、およびオブザーバビリティバックエンド間でテレメトリーデータを送信するために使用されるネイティブプロトコルです。高性能と効率のために設計されたOTLPは、トレース、メトリクス、ログの厳密なスキーマを定義し、シリアル化にはProtocol Buffers(protobuf)を使用したgRPCまたはHTTPトランスポートを利用します。

OTLPに標準化することで、ベンダーロックインを防ぎます。ベンダー固有のAPI、SDK、プロトコルを実装する代わりに、組織はOTLPに完全に標準化します。ベンダーロックインは、Collectorのエクスポーターの設定のみに限定され、アプリケーションコードが完全にベンダーニュートラルであることを保証します。

結論

OpenTelemetryによる分散トレーシングはもはや贅沢品ではなく、大規模な分散システムをレジリエントに運用するために絶対不可欠なものです。トレースとスパンのコアコンセプトを理解し、OpenTelemetry Collectorの柔軟性を活用し、W3C標準を使用した堅牢なコンテキスト伝播を確保し、自動および手動インスツルメンテーションを組み合わせることで、エンジニアリング組織はアーキテクチャの暗い部分を照らすことができます。プロジェクトが成熟し続け、メトリクスとロギングの堅牢なサポートを拡大するにつれて、OpenTelemetryはオブザーバビリティの普遍的なロゼッタストーンとなる態勢を整え、エンジニアが前例のない明瞭さと自信を持ってシステムを理解し、デバッグし、最適化できるようにします。

こちらもおすすめ

Share this article:

Stay Updated

Get the latest posts delivered straight to your inbox.

Free Developer Utilities

Free In-Browser Developer Tools

Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.

Explore Tools
Advertisement
開発者のための量子コンピューティング
tech

開発者のための量子コンピューティング

Qiskitで量子アルゴリズムを記述し、量子ゲートを理解し、古典的なハードウェアで回路をシミュレートする方法を解説する、開発者向けの量子コンピューティングガイド。

Read more