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四半期に減少したが、年間を通じて増加する見込み

推薦する

zji: 香港の高防御サーバー 38% 割引、50G 防御、2*e5-2630L/32g メモリ/2*1T SSD/10M 帯域幅 (cn2+BGP)

zji 香港葵湾の(独立した物理マシン)高防御サーバーモデルは 38% 割引を提供しています。デュア...

#クリスマス# profitserver: シンガポール VPS、オーストラリア VPS、50% オフ プロモーション、無制限トラフィック

profitserver は現在、世界中の 15 のデータセンターで VPS および専用サーバー サ...

スマート名刺ミニプログラムは販売を可能にし、より便利にします

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています2017 ...

SaaS トラックと堀

国内のSaaSベンチャーキャピタル分野では、「トラック」と「堀」が2つのホットワードです。しかし、海...

extravm: 米国製高周波サーバー (5.3GHz)、複数のモデル、月額 149 ドル、i9-10900K/32GDDR4/1TNVMe/4IP/1Gbps 帯域幅

extravm は、メインの DDoS 対策 VPS サービスに加えて、ハイエンド、高性能、高周波数...

教育求人ウェブサイトがトラフィックがあるのに収益性がない理由の分析例

著者は数年間、教育登録業界で働いており、10 以上の教育登録 Web サイトを管理しています。昨日、...

高収益の製品を作るには、製品とサービスに重点を置く必要があります

私は2週間以上このことについて考え、正式で合法的かつ収益性の高いプロジェクトを確立しようと努めてきま...

Diandian.comは、独立したドメイン名の贈与活動を開始します。1年間の更新後、所有権を取得できます。

Admin5によると、3月26日、国内の有名な独立系マイクロブログサイトDiandian.comが無...

2021 年のクラウド コンピューティングの 8 つのトレンド

時代と企業は共に呼吸し、企業と個人は同じ運命を共にする。昨日3月16日、Qingyunは株式コード6...

#著作権なし: hostsolutions-29 ユーロ/X3353/320g ハードドライブ/100M 無制限/ルーマニア

2009 年にルーマニアで登録された (CUI: RO30747114) 海外の著作権フリー ホステ...

クラウドコンピューティングは企業のイノベーションの重要な原動力となっている

新たな情報技術革命により、従来のインターネットを覆す波が巻き起こっています。クラウド コンピューティ...

9大グループ購入サイトの新状況は満杯、滴滴出行と58団は遅れをとる可能性

2年間の熾烈な競争を経て、共同購入業界の競争は重要な時期を迎えています。今年最初の8か月間の主要共同...

SEO の観点から、ウェブサイトのスナップショットがないこととランキング向上との間に密接な関係があることを説明します。

今日は2011年12月31日、2011年の最終日です!そこで今日は、1か月前に発見した問題についての...

2000年代以降のカーニバル、QQは「見知らぬ人とのソーシャルネットワーキング」に賭ける

旧来のソーシャルソフトウェアであるQQはWeChatに追い抜かれ、勢いを失ったように見えたが、200...

2021 年のクラウド コンピューティングのトップ 10 トレンド

クラウド コンピューティング テクノロジーは、コロナウイルスのパンデミックの間、世界経済、サプライ ...