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

推薦する

zgovps: ドイツの高速 VPS (as4809+9929)/高性能 VPS (Ryzen 9 7950X3D)、四半期あたり 17 ドルから

zgovps (zgocloud) のドイツ VPS は現在在庫があり、販売中です。デフォルトは、C...

グラスルーツはWeChatの成長から学び、自社ブランドの成長ルールを理解する

インターネット経由で音声メッセージ、ビデオ、画像、テキストをすばやく送信でき、複数人でのグループチャ...

北京3Dが正式に運用開始、QingCloudパブリッククラウドサービスの機能がアップグレード

エンタープライズクラスのフルスタッククラウドICTサービスプロバイダーであるQingCloudは、北...

hostvenom: スライストランスコーディングサーバーなどの高負荷タスクに適しています。月額 149 ドル、i9-9900K/64gDDR4/1T NVMe

多くの人は、ビデオ サーバー、スライス サーバー、トランスコーディング サーバー、およびあらゆる高負...

テンセントは依然としてテンセントだが、ゲーム市場はもはや同じ市場ではない

時が経つにつれ、シャンダは姿を消した。2009年に中国のオンラインゲームのトップの座から退いたシャン...

ウェブサイトを構築するには、これらの企業から学ぶ必要があります

どの業界にもリーダーやロールモデルが存在します。Web構築業界にも業績の良い企業はありますが、その業...

#blackfriday# hawkhost - サイト全体/仮想ホスト/VPS/香港\シンガポール\米国で 30% オフ

Hawkhost の毎年恒例のブラックフライデー セールが始まりました。サイト上のすべての製品 (仮...

10年続くレストランの閉店を追跡 Fantong.com

Fantong.comは消滅しました。 O2Oの普及により、飲食サービスサイトは絶好調のはずだったが...

Weiboマーケティングの基礎について簡単に解説

現在、Weiboは最も人気のあるオンラインマーケティングプラットフォームとなり、大手企業もWeibo...

5 分間の技術講演 | Xinchuang クラウド デスクトップについてどれくらいご存知ですか?

パート01 Xinchuang Cloud Desktopとは何ですか?クラウド デスクトップは、伝...

細部に注意を払うことで、ウェブサイトは優れた「ユーザーエクスペリエンス」を実現します。

ユーザー エクスペリエンスは、間違いなく昨今のホットな言葉です。最近の A5 の記事を例に挙げると、...

広告界の品質に影響を与える要因と解決策の分析

Baidu 入札キーワードの品質に影響を与えるさまざまな理由をまとめました。参考までに、広告界におけ...

スマートシティ計画の次の段階におけるエッジコンピューティングの重要性

[[423575]]過去 10 年間で、多くの都市が大規模な (そして高額な)「スマート シティ」イ...

ウェブマスターの苦い最適化の旅は、語り尽くせないほどです。

私は大学卒業後すぐに SEO 業界に入り、2 年間この業界で働いてきました。最初は SEO 初心者で...

HostwindsのシアトルVPSの簡単なレビューでHostwindsの仕組みを確認

Hostwindsは、当初は米国中部の都市ダラスを拠点として開発されました。その後、西海岸のシアトル...