Sentry + OTLP で .NET の MongoDB クエリをトレースする

Article by: (読了時間:6分)

 

あなたの .NET アプリが MongoDB とやり取りしているなら、遭遇しうるパフォーマンスの問題を効果的にデバッグできるようDB のパフォーマンスを計測できるようにしたいと、まず間違いなく考えるはずです。

そのためには、どのデータベースコマンドが実行されていたのか、どれくらいの時間がかかったのか、そしてそれが一度きりの小さな異常なのか、それともより大きなパターンの一部なのかを知る必要があります。理想を言えば、そのトレースから、関連するエラーやリプレイへと、手作業でつなぎ合わせることなく移動できるようにもしたいところです。

この記事では、まさにそれを実現する方法を次のものを使って紹介します。

  • MongoDB に組み込まれた OpenTelemetry インストルメンテーション
  • .NET SDK での Sentry の OTLP 取り込みサポート
  • エンドツーエンドの流れを示す、小さなサンプルアプリ

 

一通り終える頃には MongoDB のスパンとクエリデータを Sentry 上で確認し、次のように掘り下げられるようになります。

 

なぜこのアプローチなのか

Sentry ユーザーのために MongoDB のインストルメンテーションを実現する方法は基本的に2つ考えられます。

1つは、独自の ActivityListener とカスタムのマッピングロジックを備えた専用の Sentry.MongoDB インテグレーションを構築して保守する方法です。これでも機能はしますが、その一方で保守すべきカスタムコードが増え、テレメトリモデル間の変換が増え、説明すべき特殊なインテグレーションがもう1つ増える、ということでもあります。

私たちが選んだのはもう1つの方法である OpenTelemetry を活用し、OTLP 経由で Sentry にスパンを送る方法です。MongoDB はすでに OpenTelemetry 互換の Activity データを出力しており、Sentry も今では OTLP トレースを直接受け取ることができます。そのため、ライブラリごとに専用のブリッジを構築する代わりに、既存の OpenTelemetry パイプラインを使えるのです。

sentry-dotnetSentry.OpenTelemetry.Exporter が存在するのは、まさにこのためです。Sentry 固有のコンテキスト伝播を維持しつつ、OpenTelemetry のエクスポート処理を Sentry の OTLP エンドポイントへとつなぎます。

 

おさらい ─ .NET の MongoDB と Activity

.NET では、OpenTelemetry のトレーシングは System.Diagnostics.Activity の上に構築されています。

  • インストルメント済みのライブラリは、処理の開始時と終了時に activity を作成します。
  • OpenTelemetry SDK のコンポーネントが、それらの activity をリッスンし、処理し、エクスポートします。

 

最近の MongoDB ドライバーのリリースでは、インストルメンテーションを有効にすると、MongoDB の操作が追加設定なしでこのテレメトリを出力できるようになっています。つまり、クエリ、コマンド、トランザクション関連の操作を、自分でリスナーを書くことなく、既存の OpenTelemetry のセットアップに流し込めるということです。

 

前提条件

大まかに言うと、必要なものは次のとおりです。

  • OpenTelemetry インストルメンテーションに対応した MongoDB.Driver を使う .NET アプリ
  • トレーシング用の OpenTelemetry SDK パッケージ
  • アプリに組み込んだ Sentry.OpenTelemetry.Exporter
  • Sentry の DSN

 

sentry-dotnet のサンプルに沿って進めている場合は、そこで定義されているパッケージのバージョンをそのまま使うことをおすすめします。それらはすでに組み合わせて検証済みだからです。

参考

 

 

組み込む

セットアップ自体は、とてもシンプルです。

  1. エラー用に、いつもどおり Sentry を初期化する。
  2. Sentry 組み込みのトレーシングインストルメンテーションがスパンを重複させないよう、OTLP モードを有効にする。
  3. OpenTelemetry のトレーシングを設定する。
  4. MongoDB のインストルメンテーションを追加する。
  5. AddSentryOtlp(...) を使って、トレースを Sentry にエクスポートする。

 

簡略化した形は、次のようになります。

核心となる考え方はシンプルです。スパンの生成とエクスポートは OpenTelemetry が担い、一方で Sentry は引き続き、クラッシュレポート、エンドツーエンドのオブザーバビリティの関連付け、そして UI での探索を担います。

注:UseOtlp() を使わないと、OpenTelemetry と Sentry 組み込みのトレーシングフックの両方が重複するテレメトリを生成しようとして、スパンが重複してしまうことがあります。

 

有用な MongoDB クエリデータを取得する

スパンを取得できるのは、当たり前の前提です。面白いのは、それらのスパンに付随するコンテキストのほうです。

MongoDB のインストルメンテーションでは、そこにコマンドやクエリの詳細が含まれるため、次のようなことを判断できます。

  • どのコレクションが関係していたか
  • どの操作タイプが遅いのか
  • これは繰り返し現れるクエリパターンなのか、それとも一度きりのスパイクなのか

 

このサンプルではクエリコマンドのコンテキストを出力し、それを Sentry のトレース詳細や Queries の画面で見られるように、MongoDB と OpenTelemetry を設定しています。

 

クエリデータ内の PII はどうするか?

クエリのペイロードには、ユーザー識別子、メールアドレス、トークン、その他の機密フィールドが含まれることがあり、それらを Sentry に保存することに抵抗がある(あるいは法的に認められていない)場合もあります。

Sentry が OTLP 経由で MongoDB のスパンを受け取ると、Relay はそのクエリをパラメーター化したコピーを生成し、DB の属性を正規化し、クエリの値をすべてスクラブします(それらを ? に置き換えます)。このパラメーター化された文字列が、Queries モジュールでクエリをグループ化して表示する際に使われます。

ただし、Relay は元の db.query.text を削除したり上書きしたりすることは決してありません。そのため、{ "name": "Alice Smith" } のような実際の値を含む生のコマンドは、保存されたスパン上にそのまま保持され、スパンや代表例(exemplar)の詳細ビューに表示されます。つまり、集計された Queries ビューでは値は安全ですが、生の PII は依然として保存され、スパン単位で閲覧可能なままだということです。

このデータをスクラブするための選択肢は、3つあります。

クエリテキストをそもそも取得しない

これが最もシンプルで、最も確実です。ただし、その分、非常に有用になりうるコンテキストの一部を取り逃すことにはなります。

OTEL スパンプロセッサーでクライアント側でマスクする

.NET 向けの OTEL SDK では、BaseProcessor<Activity> を継承したクラスを登録でき、これを使って Activity.OnEnd フック経由で PII をマスクできます。これは Sentry の MongoDB サンプルで示している手法です。

上記のスクラバーは contributor フィールドの値をすべて [Filtered] というテキストに置き換えます。これにより、Sentry に送信・保存されるのは、PII を一切含まないマスク済みのバージョンになります。

サーバー側の高度なデータスクラビング

高度なデータスクラビングのルールは、db.query.text を対象にできます。

デフォルトのルールは、既知の機密パターン(パスワード、トークン、カード番号)しか捕捉しません。任意のフィールドの値をパラメーター化してくれるわけではないため、一般的な PII に対しては、明示的なルールやセレクターを追加することになります。

 

トレースを Sentry のエラーやリプレイと関連付ける

OTLP インテグレーションで重要なポイントの1つが、伝播コンテキストのブリッジングです。

トレースが OpenTelemetry の Activity によって生成される場合でも、Issue、トランザクション、そして下流のサービスが正しく揃うように、Sentry は適切なトレースヘッダー(sentry-tracebaggage)を注入し、読み取る必要があります。そのサポートはエクスポーターのインテグレーションに組み込まれているため、アプリケーションのコードに追加の配線をしなくても、トレーシングとエラーを横断した関連付けが得られます。

実際には次のことを意味します。

  • 遅い MongoDB のスパンから、同じトレース内の関連するエラーやログへとジャンプできます。
  • サービスの境界を越えても、一貫した分散トレーシングのコンテキストを保てます。

 

 

Sentry でデータを見る

サンプルを実行して MongoDB のアクティビティを発生させると、いくつかの場所でデータを探索できます。

  • Explore → Traces:エンドツーエンドのトランザクションのタイムラインを見る
  • Span samples:個々の MongoDB 操作を調べる
  • Trace samples:スパンがリクエストのライフサイクルの中にどう収まっているかを示すウォーターフォールを見る
  • Queries:スパンレベルの挙動を検索・グループ化する

 

ここでこそ、OTLP というルートが本領を発揮します。あなたが目にしているのは、独自のサイドチャネル的なインテグレーションではありません。Sentry のオブザーバビリティのワークフロー全体と自然に馴染む、第一級のトレースデータなのです。

 

おわりに

MongoDB はすでに適切なシグナルを出力しています。OpenTelemetry はそれらの処理方法をすでに心得ており、そして今や Sentry は、それらのトレースを OTLP 経由でネイティブに取り込みます。

もう1つ専用の SDK インテグレーションを保守する代わりに、オープンな標準を使い、セットアップをシンプルに保ちながら、それでいて Sentry の関連付けとデータ安全性の仕組みを維持できます。

さらに詳しく知るには

 

いつものように、質問、フィードバック、あるいはこの先どこへ進めるべきかというアイデアも大歓迎です。sentry-dotnet の discussions で、お気軽にディスカッションを始めてください。

 

 

Original Page: MongoDB Query Tracing in .NET with Sentry + OTLP

 

 




IchizokuはSentryと提携し、日本でSentry製品の導入支援、テクニカルサポート、ベストプラクティスの共有を行なっています。Ichizokuが提供するSentryの日本語サイトについてはこちらをご覧ください。またご導入についての相談は「お問い合わせ」からお気軽にお問い合わせください。

 

シェアする

Recent Posts

;