Sentry Monitoring - フルスタック開発者向けの分散トレース

Sentry Monitoring - フルスタック開発者向けの分散トレース

[[427214]]

フルスタック開発者向けの分散トレースに関するシリーズのパート 1 へようこそ。このシリーズでは、分散トレースの詳細と、フルスタック アプリケーションの監視というますます複雑化する要件に分散トレースがどのように役立つかを学びます。

Web の初期の頃は、Web アプリケーションの作成は簡単でした。開発者は、PHP などの言語を使用してサーバー上で HTML を生成し、MySQL などの単一のリレーショナル データベースと通信し、ほとんどのインタラクティブ性は静的 HTML フォーム コンポーネントによって実現されていました。デバッグツールは原始的ですが、コードの実行フローを理解するのは簡単です。

今日の最新の Web スタックでは、それは何の意味もありません。フルスタック開発者は、ブラウザで実行される JavaScript を記述し、複数のデータベース テクノロジと相互運用し、さまざまなサーバー アーキテクチャ (サーバーレスなど) にサーバー側コードをデプロイする必要があります。適切なツールがなければ、ブラウザでのユーザー操作がサーバー スタックの奥深くにある 500 サーバー エラーとどのように相関しているかを理解することはほぼ不可能です。分散トレースの登場です。

2021 年の Web スタックのボトルネックについて説明してみました。

分散トレースは、複数のサービスにわたって発生する操作とリクエストをリンクする監視手法です。これにより、開発者は、エンドツーエンドのリクエストが 1 つのサービスから別のサービスに移動するパスを「追跡」できるようになり、システム全体に悪影響を与えている単一のサービスのバグやパフォーマンスのボトルネックを正確に特定できるようになります。

この投稿では、分散トレースの概念についてさらに詳しく学び、コード内のエンドツーエンドのトレースの例を確認し、トレース メタデータを使用してログ記録および監視ツールに貴重なコンテキストを追加する方法について説明します。完了すると、分散トレースの基礎を理解できるだけでなく、トレース技術を適用してフルスタック Web アプリケーションをより効果的にデバッグする方法も理解できるようになります。

しかし、まず最初に、分散トレースとは何かを考えてみましょう。

分散トレースの基礎

分散トレースは、複数のサービスの接続された操作を記録する方法です。通常、これらの操作は、あるサービスから別のサービスへのリクエストによって開始されます。ここで、「リクエスト」は、実際の HTTP リクエスト、またはタスク キューやその他の非同期手段を介して呼び出される作業です。

トレースには 2 つの基本コンポーネントが含まれます。

  • スパンは、サービス上で発生する操作または「作業」を表します。スパンは、HTTP 要求に応答する Web サーバーのアクションなど、広範な操作を記述することも、単一の関数の呼び出しを記述することもできます。
  • トレースは、接続された 1 つ以上のスパンのエンドツーエンドの経路を記述します。トレースが複数のサービスで実行されるスパン(「作業」)を接続する場合、そのトレースは分散トレースとみなされます。

仮想的な分散トレースの例を見てみましょう。

上の図は、トレースがサービス (ブラウザー上で実行されている React アプリケーション) から開始され、API Web サーバーへの呼び出し、さらにはバックグラウンド タスク ワーカーへの呼び出しへと継続される様子を示しています。この図のスパンは各サービスで実行される作業であり、各スパンはブラウザ アプリケーションによって開始された初期作業まで「遡って」追跡できます。最後に、これらの操作は異なるサービスで発生するため、このトレースは分散されていると見なされます。

広範な操作 (たとえば、HTTP 要求に応答する Web サーバーの完全なライフサイクル) を記述する範囲は、トランザクション範囲、または単にトランザクションと呼ばれることもあります。トランザクションとスパンの詳細については、このシリーズのパート 2 で説明します。

トレースとスパンの識別子

これまで、トレースのコンポーネントを特定してきましたが、これらのコンポーネントがどのようにリンクされているかについてはまだ説明していません。

まず、各トレースはトレース識別子によって一意に識別されます。これは、ルートスパンにランダムに生成された一意の値 (UUID など) を作成することによって行われます。これは、トレース全体を開始する最初の操作です。上記の例では、ルート スパンがブラウザ アプリケーションに表示されます。

次に、各スパンを最初に一意に識別する必要があります。これは、スパンが操作を開始するときに一意のスパン識別子 (または span_id) を作成することによって行われます。この span_id の作成は、トレース内で発生する各スパン (または操作) に対して行われる必要があります。

仮想的な追跡の例をもう一度見てみましょう。上の画像では、トレース識別子がトレースを一意に識別し、そのトレース内の各スパンにも一意のスパン識別子があることがわかります。

ただし、trace_id と span_id を生成するだけでは不十分です。これらのサービスを実際に接続するには、アプリケーションが 1 つのサービスから別のサービスにリクエストを行うときに、トレース コンテキストと呼ばれるものを伝播する必要があります。

トレースコンテキスト

トレース コンテキストは通常​​、次の 2 つの値のみで構成されます。

  • トレース識別子 (または trace_id): ルート スパンで生成され、トレース全体を識別する一意の識別子。これは、前のセクションで紹介したトレース識別子と同じです。変更されずに各下流サービスに伝播されます。
  • 親識別子 (または parent_id): 現在の操作を生成した「親」スパンの span_id。

次の図は、1 つのサービスで開始されたリクエストがトレース コンテキストを下流の次のサービスに伝播する方法を示しています。 trace_id は同じままですが、parent_id はリクエスト間で変化し、最新の操作を開始した親スパンを指していることがわかります。

これら 2 つの値を使用すると、任意の操作に対して、元の (ルート) サービスが決定され、すべての親/祖先サービスが現在の操作につながった順序で再構築されます。

動作例 (コードデモ)

ソースコードの例:

  • https://github.com/getsentry/distributed-tracing-examples

これをよりよく理解するために、ブラウザ アプリケーションがトレース コンテキストによって接続された一連の分散操作の開始者となる基本的なトレース実装を実際に実装してみましょう。

まず、ブラウザ アプリケーションはフォーム (この場合は「ユーザーを招待」フォーム) を表示します。フォームには、フォームが送信されたときに起動される送信イベント ハンドラーがあります。このコミット ハンドラーをルート スパンとして考えてみましょう。つまり、ハンドラーが呼び出されると、trace_id と span_id が生成されます。

次に、フォームからユーザーが入力した値を収集する作業を行い、最後に /inviteUser API エンドポイントへのフェッチ要求を Web サーバーに送信します。このフェッチ要求の一部として、トレース コンテキストは、trace-id と parent-id (つまり、現在のスパンの span_id) という 2 つのカスタム HTTP ヘッダーとして渡されます。

  1. // ブラウザアプリ (JavaScript)
  2. uuidインポート  'UUID' ;
  3.  
  4. 定数traceId = uuid.v4();
  5. 定数spanId = uuid.v4();
  6.  
  7. console.log( 'inviteUser POSTリクエストを開始します' , `traceId: ${traceId}`);
  8.  
  9. フェッチ( '/api/v1/inviteUser?email=' + encodeURIComponent(email), {
  10. メソッド: 'POST'
  11. ヘッダー: {
  12. 'トレースID' : トレースID、
  13. '親ID' : spanId、
  14. }
  15. })。それから((データ) => {
  16. console.log( '成功しました!' );
  17. }).catch((エラー) => {
  18. console.log( '何か問題が発生しました' , `traceId: ${traceId}`);
  19. });

これらは説明目的で使用されている非標準の HTTP ヘッダーであることに注意してください。 W3C の traceparent 仕様の一部として、トレース HTTP ヘッダーを標準化する取り組みが活発に行われていますが、これはまだ「推奨」段階にあります。

  • https://www.w3.org/TR/trace-context/

受信側では、API Web サーバーがリクエストを処理し、HTTP リクエストからトレース メタデータを抽出します。次に、ユーザーに電子メールを送信するジョブをキューに登録し、ジョブの説明の「メタ」フィールドの一部として追跡コンテキストを添付します。最後に、メソッドが成功したことを示すステータス コード 200 の応答を返します。

サーバーは成功応答を返しますが、バックグラウンド タスク ワーカーが新しくキューに入れられたジョブを取得して実際に電子メールを送信するまで、実際の「作業」は完了しないことに注意してください。

ある時点で、キュー ハンドラーはキューに入れられた電子メール ジョブの処理を開始します。ここでも、Web サーバーで以前抽出されたのと同じように、トレースと親識別子が抽出されます。

  1. // API ウェブサーバー
  2. const Queue = require( 'bull' );
  3. const emailQueue = 新しいキュー( 'email' );
  4. uuidが必要です
  5.  
  6. app.post( "/api/v1/inviteUser" , (req, res) => {
  7. 定数spanId = uuid.v4()、
  8. traceId = req.headers[ "トレースID" ],
  9. parentId = req.headers[ "親ID" ];
  10.  
  11. コンソール.log(
  12. 「ジョブを電子メールキューに追加しています
  13. `[トレースID: ${トレースID},`,
  14. `親ID: ${parentId},`,
  15. `スパンID: ${スパンID}]`
  16. );
  17.  
  18. emailQueue.add ({
  19. タイトル: 「弊社製品へようこそ
  20. 宛先: req.params.email,
  21. メタ: {
  22. トレースID: トレースID、
  23.  
  24. // 下流のスパンの parent_id はこのスパンのspan_idです
  25. 親ID: スパンID、
  26. },
  27. });
  28.  
  29. res.status(200).send( "ok" );
  30. });
  31.  
  32. // バックグラウンド タスク ワーカー
  33. emailQueue.process((ジョブ、完了) => {
  34. 定数spanId = uuid.v4();
  35. const {traceId,parentId} = job.data.meta;
  36.  
  37. コンソール.log(
  38. 「メールを送信しています」
  39. `[トレースID: ${トレースID},`,
  40. `親ID: ${parentId},`,
  41. `スパンID: ${スパンID}]`
  42. );
  43.  
  44. // 実際にメールを送信する
  45. // ...
  46.  
  47. 終わり();
  48. });

分散システムロギング

例の各段階で、console.log を使用してログ呼び出しが行われ、現在のトレース、スパン、および親の識別子も出力されていることに気付くでしょう。完全に同期された世界、つまりすべてのサービスが同じ集中ログ機能にログを記録できる世界では、次の各ログ ステートメントが順番に表示されます。

これらの操作中に異常または誤った動作が発生した場合、これらのログ ステートメントまたは追加のログ ステートメントを使用して原因を特定するのは比較的簡単です。しかし残念なことに、これらは分散型サービスであり、次のことを意味します。

Web サーバーは通常、多数の同時リクエストを処理します。 Web サーバーは、他のリクエストに起因する作業 (およびログ ステートメントの発行) を実行している可能性があります。

ネットワーク遅延は操作の順序に影響を与える可能性があります。アップストリーム サービスからのリクエストは、トリガーされた順序どおりに宛先に到着しない場合があります。

バックグラウンドワーカーにはキューに入れられたジョブがある場合があります。このトレースにキューイングされた正確なジョブに到達する前に、ワーカーは以前にキューイングされたジョブを完了しなければならない場合があります。

より現実的な例では、同時に複数の操作が実行されていることを反映して、ログ呼び出しは次のようになります。

メタデータを追跡しないと、どのアクションがどのアクションを呼び出すかのトポロジを理解することは不可能です。ただし、すべてのログ呼び出しでトレース メタ情報を発行すると、traceId でフィルター処理してトレース内のすべてのログ呼び出しをすばやくフィルター処理し、spanId と parentId の関係を調べることで正確な順序を再構築できます。

これが分散トレースの威力です。現在の操作 (スパン ID)、それを生成した親操作 (親 ID)、およびトレース識別子 (トレース ID) を記述するメタデータを添付することで、ログ記録とテレメトリ データを拡張し、分散サービスで発生したイベントの正確なシーケンスをよりよく理解できるようになります。

実際の分散トレース環境では

この記事では、やや不自然な例を使用してきました。真の分散トレース環境では、すべてのスパンとトレース識別子を手動で生成して渡すことはありません。また、トレース メタデータを自分で出力するために console.log (またはその他のログ記録) 呼び出しに依存することもありません。適切な追跡ライブラリを使用して、追跡データの検出と送信を処理します。

オープンテレメトリー

OpenTelemetry は、実行中のソフトウェアからテレメトリ データを計測、生成、エクスポートするためのオープン ソース ツール、API、SDK のセットです。ブラウザの JavaScript や Node.js など、最も一般的なプログラミング言語の言語固有の実装を提供します。

  • オープンテレメトリ
  • https://github.com/open-telemetry/opentelemetry-js

セントリー

Sentry はこのテレメトリをさまざまな方法で使用します。たとえば、Sentry のパフォーマンス監視機能セットは、トレース データを使用して、トレース内の分散サービス操作のエンドツーエンドのレイテンシを示すウォーターフォール チャートを生成します。

Sentry は、トレース メタデータを使用してエラー監視機能を強化し、あるサービス (サーバー バックエンドなど) でトリガーされたエラーが別のサービス (フロントエンドなど) のエラーにどのように伝播するかを理解します。

<<:  JVM ガベージ コレクターの簡単な紹介

>>:  IDC: クラウドインフラ支出は第1四半期に減少したが、年間を通じて増加する見込み

推薦する

Vultr 無料 $5 (VPS-12 データセンター)

Vultr は本日、ウェブサイトの再設計を完了し、5 ドルのトライアル割引をリリースしました。割引は...

budgetvm: ロサンゼルス サーバー、月額 86 ドル、帯域幅 1Gbps、トラフィック無制限、e3-1230v3/16g メモリ/2T ハード ドライブ

Enzu傘下のブランドであるBudgetvmは、創業から12年近く経ち、主に米国で4つのデータセンタ...

ターゲット人口 2 億人、単一店舗の売上高 100 万で、ゲームのレベルアップは良いビジネスでしょうか?

2017年以来、 『Honor of Kings』は、スキンの1日売上が1億5000万、1日平均DA...

alpha1server: 35% オフ、100M 無制限トラフィック KVM シリーズ、$3.5/1g メモリ/20g SSD

alpha1server(このサイトでは2017年に初めて紹介されました。こちらをクリック)では、現...

キーワードでホームページにランクインするために必要なのはたった3つの重要なポイントだけです(I)

新しいサイトがランキングされるにはある程度の時間がかかることは、多くの人が知っています。一般的に、B...

マヤの予言が信頼できるなら、キーワードランキングはホームページにしっかりと定着するだろう

これから過ぎ去ろうとしている年は、残酷で寒い年だと思っています。6月、8月、11月の数字は、すべての...

12月のウェブサーバー市場:Apacheは3.08%下落、Microsoftは上昇

IDC Review Network (idcps.com) は 12 月 11 日に次のように報告...

Akamai: エッジコンピューティングのイノベーションに注力し、業界のデジタル変革をリード

世界的なデジタル化の波の台頭により、エッジコンピューティングは徐々に産業変革の新たなプラットフォーム...

ウェブサイトのキーワードがオンライン化後に変動する理由

ウェブサイト最適化の主な仕事は、キーワードを百度のホームページに表示させることですが、残念なことに、...

インフラストラクチャ・アズ・コードの 8 つのメリットとツールの選び方

主要なアプリケーションやサービスをクラウド プラットフォームでホストする企業が増えるにつれて、Inf...

5 分間の技術講演 |クラウドコンピュータビデオストリーミングフレームレートネゴシエーションメカニズム

図に示すように、クラウド コンピュータはネットワークに大きく依存します。ネットワークがなければクラウ...

ehvps-50% オフ/$4.5/KVM/2g メモリ/30g ハードディスク/2T トラフィック/He Fremont

ehvps は 2016 年に VPS 事業を開始しました。サーバーはカリフォルニア州フリーモントの...

機械学習はクラウドネイティブセキュリティの未来

コンテナとマイクロサービスはセキュリティ保護が困難です。機械学習が解決策になるかもしれません。 [[...

3分レビュー! 2021年10月のクラウドコンピューティング分野の重要な動向の概要

2020年以降、クラウドコンピューティングがトレンドになりました。ますます多くの資本と企業がクラウド...

SEO サービスの倫理規定

今日、インターネットマーケティングは商品を販売するための重要な手段となっています。インターネットを通...