このチュートリアルの目的は、OpenTelemetry のスパン リンクに関する実用的でわかりやすいガイドを提供することです。
開発者、特に複雑な非同期システムを扱う開発者が、スパン リンクとは何か、トレースにおける従来の親子関係との違い、およびトレースの相関関係を改善するためにスパン リンクがなぜ価値があるのかを理解できるようにすることを目的としています。
このガイドを終えると、スパン リンクを効果的に使用して分散システム内の対話を追跡し、可観測性とデバッグの向上につながるために必要なスキルを習得できるようになります。
以前は、アプリケーションは通常モノリシックでした。つまり、すべてのプロセスや機能が 1 つのサーバー上で単一のユニットとして実行されます。そのようなアプリケーションの監視は簡単でした。
例: 何か問題が発生した場合、そのサーバーからのログを調べて問題を特定できます。しかし、マイクロサービスの台頭により、このシンプルさが変わりました。
現代のアプリケーションは、多くの場合、連携して動作する数十、場合によっては数百の小規模な独立したサービスで構成されています。たとえば、モバイル アプリを使用して注文する場合、ユーザー認証の処理、支払い処理、在庫管理、確認メールの送信を行う別のサービスが存在する場合があります。
これらのサービスは常に同じサーバー上にあるわけではなく、インターネット経由で通信することもできるため、アプリケーションと対話するときに何が起こったかを追跡するのがさらに複雑になります。
ここで分散トレーシングが登場します。分散トレーシングは、複雑なアプリケーション内のさまざまなサービスを通過する単一のリクエストを追跡する方法と考えてください。複雑なシステムを通過するリクエストの移動を追跡します。
最新のアプリケーションでは、リクエストは多くの場合、それぞれが異なるマシン上で実行されている複数のサービスを経由します。分散トレーシングはこの過程を視覚化するのに役立ち、ボトルネックやエラーを特定しやすくなります。
これは、プロセスの各ステップ間の点を結ぶ探偵の地図のようなもので、各部分にどれくらい時間がかかり、どこで問題が発生したかを示します。トレースを見ると、リクエストがさまざまなサービスをどのように移動したかをタイムラインで確認できるため、速度の低下、エラー、障害を特定しやすくなります。
コード リポジトリ
このチュートリアルのコード リポジトリは次のとおりです:
[https://github.com/Noibisjunior/Span-Links-in-OpenTelemetry]
OpenTelemetry は、この種の可視性を実現する上で重要な役割を果たします。これは、開発者がアプリケーションからログ、メトリクス、トレースなどのデータを収集できるようにするオープンソースの可観測性フレームワークです。サービス内で何が起こっているかに関する詳細な情報を取得するためのツールセットとして機能します。
最新の可観測性の世界では、OpenTelemetry は分散アプリケーションのパフォーマンスと健全性を理解するのに役立ちます。これは、さまざまなサービスからデータを収集し、それを SigNoz などのツールに送信するブリッジのように機能し、そこで何が起こっているかを視覚化できます。このため、OpenTelemetry はボトルネックの特定、エラーの追跡、アプリケーションのスムーズな実行の確保に非常に役立ちます。
分散トレースで OpenTelemetry を使用すると、アプリケーションの動作の全体像を把握できるため、問題の診断が容易になり、ユーザー エクスペリエンスが向上します。
ソフトウェア、特に分散システムが複雑になるにつれて、その内部の仕組みを理解することが困難な作業になります。そこで OpenTelemetry のスパンが登場し、課題を簡単に解決できます。
スパンは、OpenTelemetry のトレース システムにおける基本的な作業単位です。これは、アプリケーション内で発生する単一の操作またはイベントです。
操作中に何が起こったか、所要時間、成功したか失敗したかなどの関連詳細が記録されます。
たとえば、アプリケーションがユーザー リクエストを処理すると想像してください。
スパンの主要な属性:
スパンは個別に便利ですが、連携してトレースを形成すると効果的です。
トレースは、システム内を流れるリクエストまたは操作の過程全体を表すスパンのコレクションです。
ユーザーリクエストの例に戻りましょう:
リクエストがシステムに入力されるとトレースが開始され、ルート スパンが作成されます。リクエストがデータベース クエリをトリガーすると、データベース インタラクション スパンがルート スパンにリンクされ、同じプロセスの一部であることが示されます。
他のサービスを呼び出すための追加のスパンがトレースに追加されます。このトレースを見ると、リクエストがシステムのさまざまな部分をどのように通過したかの全体像がわかります。これは、何が起こったかだけでなく、アプリケーションのさまざまな部分がどのように接続されているかを理解するのに役立ちます。
問題の特定: スパンは、問題が発生している箇所を拡大するのに役立ちます。リクエストが遅い場合、スパンは、遅延の原因がデータベース クエリなのか、ネットワーク呼び出しなのか、それともプロセスの他の部分なのかを知ることができます。どのスパンに予想よりも時間がかかっているかがわかるため、ボトルネックを見つけやすくなります。
コンテキストの構築: 各スパンには、開始時間、終了時間、カスタム ラベル (属性) などのコンテキスト情報が含まれています。このデータは、リクエストに含まれる特定のユーザー ID や実行されたクエリなど、システムで特定の瞬間に何が起こっていたのかについての洞察を提供します。
関係の作成: スパンは相互に関係を持ち、多くの場合、親子構造になります。ルート スパンが親であり、後続のスパンがその子です。この構造は、イベントが発生した順序と、イベントが相互にどのように依存しているかを確認するのに役立ちます。これは、アプリ内の操作の家系図を見るようなものです。
分散システムのデバッグ: マイクロサービス (異なるサービスがリクエストの異なる部分を処理する) を使用するアプリケーションの場合、スパンは特に重要です。これらは、サービスが異なるサーバーまたは異なるデータセンターで実行されている場合でも、サービス間を移動するリクエストを追跡するのに役立ちます。これは、サービス間の複雑な相互作用を理解するための鍵となります。
スパンリンクとは何ですか?
複数のサービスが連携してユーザー リクエストを処理する分散システムの世界では、トレースは探偵の地図のようなもので、リクエストがこれらのサービスを通過するときにたどるパスを示します。この旅の各アクティビティはスパンと呼ばれ、完全な旅はトレースと呼ばれます。
伝統的に、スパンは親子関係を使用して接続されます。これらを家系図のように想像してください。親スパンはプロセス (別のサービスにリクエストを行うなど) を開始し、子スパンは結果として発生するアクティビティ (リクエストを処理するサービスなど) を表します。これはリクエストのフローを表す簡単な方法です。
しかし、2 つのスパンが関連していても、その親子階層に完全に適合しない場合はどうなるのでしょうか?ここでスパンリンクが登場します。
スパン リンク を使用すると、関連はあっても直接の親子関係がない 2 つのスパンを接続できます。これは、分散システムにおける 2 つのアクティビティ間の「参照」または「ショートカット」のようなものです。
たとえば、電子メールの送信やデータベースへの書き込みなど、複数の独立したプロセスをトリガーするリクエストを行うユーザーがいるとします。これらのプロセスはお互いの子アクティビティではありません。それらは並行して起こります。スパン リンクを使用すると、電子メール送信スパンとデータベース書き込みスパンが、親子概念では直接接続されていない場合でも、同じ最初のユーザー リクエストに関連していることを示すことができます。
親子関係: これは単純な一連の出来事です。ユーザーがリクエスト (親) を送信すると、データベース (子) 内のレコードの作成がトリガーされます。子スパンは親スパンがなければ存在しないため、それが直接的な結果となります。
スパン リンク: これらは、何らかのコンテキストで関連しているアクティビティの間に点線を引くことに似ていますが、アクションの直接の連鎖には従いません。これらは、「一方が他方を直接引き起こさなかったとしても、これらのことは関連している」と言う方法を提供します。スパン リンクは、厳密には階層的ではないものの、相互作用する並行アクティビティやイベントを表すのに最適です。
複雑な非同期システムにおけるスパン リンクの重要性
スパン リンクは、イベントの流れが必ずしも明確な親子パスに従うわけではない、複雑な非同期システムで特に価値があります。実際にどのように使用できるかを示すいくつかのシナリオを次に示します。
非同期ワークフロー:
バックグラウンド ジョブ (レポートの生成など) から始まるユーザー リクエストを想像してください。最初のリクエストは終了しますが、レポートの生成はバックグラウンドで続行されます。
スパン リンクの実装により、直接の親子パターンに従っていない場合でも、最初のリクエスト スパンをバックグラウンド ジョブ スパンに関連付けることができます。
マイクロサービス通信:
マイクロサービス アーキテクチャでは、多くの場合、サービスは厳密には階層的ではない方法で相互に通信します。
たとえば、ユーザーのアクションにより複数のサービスがトリガーされ、データの異なる部分が同時に処理される可能性があります。スパン リンクを使用すると、より広範なワークフローの一部として、これらの独立した関連スパンを追跡できます。
バッチ処理: バッチ内の各項目が独自のスパンを生成するデータのバッチを処理している場合、スパン リンクを使用してこれらのスパンを元のバッチ プロセスに接続できます。
これにより、バッチのライフサイクル全体を追跡し、個々のアイテムがメイン プロセスにどのように関係しているかを理解することが容易になります。
コードと可観測性システムの間のブリッジとして機能し、アプリケーションがどのように実行されているかに関する詳細な情報を収集できるようにします。
OpenTelemetry を、アプリケーションの操作のスナップショットをキャプチャする「カメラ」として想像してください。 SDK をアプリに統合すると、舞台裏で何が起こっているかを記録するためにこのカメラを配置することになります。
アプリケーションのプログラミング言語 (Python、Java、JavaScript など) で SDK をインストールする必要があります。
(2) SigNoz のセットアップ: SigNoz は、OpenTelemetry で収集したデータを視覚化し、分析できるオープンソースの可観測性ツールです。
SigNoz は、OpenTelemetry セットアップによってキャプチャされた映像を表示する「コントロール ルーム」と考えてください。ここで、アプリケーション内のトレースとメトリクスを明確に把握できます。
SigNoz インスタンスをセットアップする必要があります。これには、通常は Docker または Kubernetes を使用してローカル マシンまたはサーバーにデプロイする必要があります。
SigNoz は、生データをグラフやチャートなどの視覚化に変換するのに役立ち、アプリケーション内で何が起こっているかを理解しやすくします。
トレース:
簡単に言えば、トレースは、ユーザーまたはリクエストがアプリケーションと対話するときに何が起こるかを示す「ストーリー」のようなものです。最初のリクエストから、関係する可能性のあるすべてのサービスやデータベースに至るまで、その対話の結果として発生するすべてのアクションをキャプチャします。
ユーザーが Web サイト上のボタンをクリックしているところを想像してください。トレースは、次に起こることのすべてのステップを記録します。
スパン:
スパンは、トレースのストーリー内の「章」です。各スパンは、トレースの一部として実行される特定の操作またはタスクを表します。
たとえば、トレースがユーザー リクエストのプロセス全体をキャプチャする場合、スパンはデータベースへのクエリや外部 API の呼び出しなどの 1 つのステップを表す可能性があります。
各スパンには開始時間と終了時間があり、各ステップにかかった時間の正確な詳細がわかります。これにより、速度低下やエラーを特定しやすくなります。
OpenTelemetry を使用したコードのインストルメント:
インストルメンテーションは、可観測性データを収集するためにアプリケーションにコードを追加するプロセスです。コードに OpenTelemetry を組み込むことにより、通常、トレースとスパンを作成する場所に数行のコードを追加する必要があります。
たとえば、データベース クエリをインストルメント化して所要時間を確認したり、ユーザー ログイン プロセスをインストルメント化してパフォーマンスを追跡したりできます。
OpenTelemetry SDK は、コードに直接統合できるライブラリと関数を提供することで、これを容易にします。これは、トラッカーをマシンの部品に取り付けて、それらがどのように連携するかを監視するようなものだと考えてください。
Python の基本的な例を見てみましょう。 OpenTelemetry SDK を使用して 2 つのスパンを作成し、それらをリンクします。
from opentelemetry import trace from opentelemetry.trace import Link from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter # Set up the tracer provider and span exporter trace.set_tracer_provider(TracerProvider()) tracer = trace.get_tracer(__name__) span_processor = SimpleSpanProcessor(ConsoleSpanExporter()) trace.get_tracer_provider().add_span_processor(span_processor) # Create the first span, simulating some work being done with tracer.start_as_current_span("span_one") as span_one: span_one.add_event("Processing order") order_id = "12345" # Imagine this as an order ID we're processing # Create a second span with a link to the first span with tracer.start_as_current_span("span_two", links=[Link(span_one.get_span_context())]) as span_two: span_two.add_event("Updating order status") # Simulate some additional work here print("Order ID: {order_id} has been updated.") print("Tracing complete")
上記の Python コード スニペットの説明
トレーサープロバイダーをセットアップします:
上記のコード スニペットは、スパンの作成を管理するトレーサー プロバイダーで始まります。
これは、OpenTelemetry がスパンの処理方法を知るために不可欠です。また、SimpleSpanProcessor と ConsoleSpanExporter を構成して、スパン データをコンソールに出力します。これは、作成されているスパンのタイプとそれらがどのようにリンクされているかを確認するのに役立ちます
.
(2) 最初のスパン (span_one) を作成します:
tracer.start_as_current_span メソッドを使用して、span_one という名前のスパンを作成します。これは、注文の処理など、あらゆるアクションを表すことができます。
このスパン内に、その特定の時点で何が起こっているかを示すイベント処理順序を追加します。
次のスパンで使用される注文 ID (order_id = "12345") もシミュレートします。
(3) リンクを使用して 2 番目のスパンを作成します (span_two):
ここでは、注文ステータスの更新など、別の関連するアクションを表すために、span_two という別のスパンを開始しました。
links パラメータに注目してください。Link(span_one.get_span_context()) を使用して、span_two と span_one の間にリンクを作成します。
これにより、OpenTelemetry に「これらのアクションは親子ではありませんが、関連している」ことがわかります。
span_two 内に、注文ステータスの更新という別のイベントを追加し、データベース内の注文ステータスの更新などのいくつかの作業をシミュレートしました。
(4) 出力:
このコードを実行すると、両方のスパンとそれらの間のリンクを示す ConsoleSpanExporter からの出力がコンソールに表示されます。これは、トレース内でこれら 2 つのスパンが互いにどのように関係しているかを視覚化するのに役立ちます。
(1) スパンコンテキストが欠落しています:
エラー: OpenTelemetry ではリンクを作成するために有効な Span コンテキストが必要であるため、span_one.get_span_context() を呼び出さずにリンクを作成しようとすると、エラーが発生します。
解決策: リンクを作成するときは、必ずスパン コンテキストを渡していることを確認してください。アクティブなスパンの .get_span_context() メソッドを使用します。
(2) 未開始または終了したスパンのリンク:
エラー: 開始されていない、またはすでに終了しているスパンへのリンクを作成しようとすると、リンクが認識されないという問題が発生する可能性があります。
解決策: リンクを作成するときに、リンク先のスパンがアクティブであることを確認してください。すでに終了しているスパンを含むリンクを作成すると、トレースの表示方法で予期しない動作が発生する可能性があります。
(3) パフォーマンスに関する考慮事項:
パフォーマンスの問題: リンクするスパンが多すぎると、トレース データのオーバーヘッドが増加し、高トラフィック システムでのパフォーマンスの低下につながる可能性があります。
解決策: リンクを選択的に使用します。リンク スパンは、視覚化または分析する必要がある意味のある関係がある場合にのみ行われます。高トラフィック環境の場合、OpenTelemetry のサンプリング オプションを使用して、キャプチャされるトレース データの量を減らすことができます。
分散システムを操作する場合、システムのさまざまな部分がどのように通信するかを理解することが重要です。 OpenTelemetry のスパン リンクは、直接の親子関係がない可能性のあるトレースを接続する上で重要な役割を果たし、リクエストがサービスをどのように流れるかをより明確に示します。
スパン リンクの視覚化が重要な理由
アプリケーションに、支払いが成功したときに通知サービスをトリガーする支払いサービスがあると想像してください。これらのサービスは相互作用しますが、直接の親子関係を共有しない場合があります。
スパン リンクを使用すると、これらのインタラクションを関連付けることができ、支払いによって通知がトリガーされたことを示すことができます。これらのリンクを視覚化すると、独立したサービスがリアルタイムでどのように相関しているかを全体像を把握するのに役立ちます。
これらのスパン リンクを視覚化するように SigNoz を設定することで、アプリケーションの動作についてより深い洞察を得ることができます。
スパン リンクをキャプチャして表示するように SigNoz を設定する方法は次のとおりです
ステップ 1: SigNoz が適切にインストールされていることを確認します
ステップ 2: スパン リンクを含めるように OpenTelemetry SDK を構成する
次のステップは、OpenTelemetry SDK がスパン リンク データを SigNoz に送信するように設定されていることを確認することです。アプリケーションのコードでは、トレース ロジックの一部としてスパン リンクを追加する必要があります。
これは Python プログラミング言語のコード スニペットです:
from opentelemetry import trace from opentelemetry.trace import Link from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter # Set up the tracer provider and span exporter trace.set_tracer_provider(TracerProvider()) tracer = trace.get_tracer(__name__) span_processor = SimpleSpanProcessor(ConsoleSpanExporter()) trace.get_tracer_provider().add_span_processor(span_processor) # Create the first span, simulating some work being done with tracer.start_as_current_span("span_one") as span_one: span_one.add_event("Processing order") order_id = "12345" # Imagine this as an order ID we're processing # Create a second span with a link to the first span with tracer.start_as_current_span("span_two", links=[Link(span_one.get_span_context())]) as span_two: span_two.add_event("Updating order status") # Simulate some additional work here print("Order ID: {order_id} has been updated.") print("Tracing complete")
上記の Python コード スニペットの説明
まず、アプリケーションでトレースを処理し、スパン プロセッサをセットアップするように TracerProvider を構成しました。
OTLPSpanExporter は、OTLP プロトコルを使用して SigNoz のバックエンドにスパンを送信するために使用されます。
SigNoz をローカルで実行していない場合は、http://localhost:4317 を適切な SigNoz エンドポイントに置き換えます。
2 番目に、スパンとリンクの作成:
parent_span が最初に作成され、初期操作 (ユーザーリクエストなど) を表します。get_span_context() を使用してparent_span のコンテキストを抽出します。これにより、別のスパンをそれにリンクできます。
次に、linked_span が作成され、parent_span のコンテキストを参照するリンクが追加されます。これは、linked_span がparent_span の直接の子ではないものの、parent_span に関連していることを意味します。
最後に、SigNoz にデータを送信します:
スパン データは BatchSpanProcessor を使用して処理され、これによりスパン データが確実に SigNoz に効率的に送信されます。
trace.get_tracer_provider().shutdown() は最後に呼び出され、プログラムが終了する前に残りのスパンが確実にフラッシュされ、エクスポートされます。
ステップ 3: データ追跡用の SigNoz 構成を更新する
from opentelemetry import trace from opentelemetry.trace import SpanKind, Link from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter # Set up the tracer provider and add a span processor trace.set_tracer_provider(TracerProvider()) tracer = trace.get_tracer(__name__) # Configure the exporter to send spans to SigNoz using the OTLP exporter otlp_exporter = OTLPSpanExporter(endpoint="http://localhost:4317", insecure=True) span_processor = BatchSpanProcessor(otlp_exporter) trace.get_tracer_provider().add_span_processor(span_processor) # Create two spans, linking the second span to the context of the first with tracer.start_as_current_span("parent_span") as parent_span: # Simulate some logic for the parent_span print("Parent span is active") # Get the context of the parent span parent_context = parent_span.get_span_context() # Create a linked span and add a link to the parent span's context with tracer.start_as_current_span( "linked_span", links=[Link(parent_context)] ) as linked_span: # Simulate some logic for the linked_span print("Linked span is active") # Ensure all spans are flushed before exiting the application trace.get_tracer_provider().shutdown()
ステップ 4: SigNoz でスパン リンクを視覚化する
アプリケーションがスパン リンクを含むトレース データを SigNoz に送信すると、次の方法でこれらのリンクを視覚化できます。
ステップ 5: 見やすくするためにビューを調整します
完璧な視覚化を実現するには、次の点に注意する必要があります:
次のステップ
このチュートリアルでは、スパン リンクを使用して分散システム内のインタラクションを追跡する方法を学びました
次のチュートリアルでは、スパン リンクを使用するためのベスト プラクティスと高度な使用例を学びます
以上がOpenTelemetry と Signoz を使用したスパン リンクによるトレース分析をマスターする (実践ガイド)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。