Sentry:エラーのグルーピングで例外を対処可能な課題に変える仕組み

Published · AI Daily — AI-assisted deep research, methodology & disclosure

Sentryはオープンソースのエラー監視・性能追跡プラットフォームです。中核技術はグルーピングで、届いたイベントを「カスタム指紋、コンポーネントのハッシュ、フォールバック」の優先順位で課題に割り当てます。グルーピング設定には版があり、新旧の設定を併存させられます。リポジトリは8,000を超えるPythonファイルからなる大規模モノリスで、高スループットの取り込みとシンボル化は独立したRustコンポーネントが担います。ライセンスはFSL-1.1-Apache-2.0です。

背景と課題の所在

本番環境のコードが失敗したとき、開発者は四つの問いに答える必要があります。どの行で起きたのか。何人のユーザーが影響を受けたのか。どのリリースから始まったのか。どうすれば再現できるのか。通常のログは失敗をすべて記録しますが、似た記録を数千件まとめて対処できる一つの課題にすることは得意ではありません。Sentry はこの隔たりを埋めるためのオープンソースのエラー監視・性能追跡プラットフォームです。その役割は、生のイベントを対処可能な課題に変えることです。

難しいのはグルーピングです。同じ欠陥でも、端末、ロケール、入力によって、異なるメッセージ、変数の値、スタックのパスが生じます。生のテキストで重複を除くと、一つのバグが数百の課題に分かれてしまいます。例外の型だけでまとめると、無関係な障害が混ざります。Sentry は、この二つの極端の間で安定した境界を見つける必要があります。

リポジトリのスター数は約4.5万で、主言語は Python です。ライセンスファイル LICENSE.md には FSL-1.1-Apache-2.0、すなわち Functional Source License と記載されています。トピックに付いた fair-source のタグもこれと一致します。コードを読むこと、自前で運用すること、社内用途に改変することは認められています。一方、このコードで競合する商用ホスティングを提供することは認められていません。

コアアーキテクチャと技術原理

リポジトリは大規模な Python モノリスです。src/sentry 以下とリポジトリ全体を合わせると8,000を超える Python ファイルがあり、静的フロントエンドには約8,700の TSX ファイルがあります。Web 画面、公開 API、非同期ワーカー、グルーピングエンジン、取り込みの経路は、この一つのコードツリーに収まっています。 イベントの流れは三段階です。第一段階はイベントストリームです。src/sentry/eventstream/snuba.py の85行目にある SnubaProtocolEventStream が、挿入、統合、分離、削除のための共通プロトコルを定義します。src/sentry/eventstream/kafka/backend.py の63行目にある KafkaEventStream は、このプロトコルを継承して、メッセージを Kafka に送ります。呼び出し側を変えずに、転送方式を差し替えられる構造です。 第二段階はグルーピングです。src/sentry/grouping/variants.py では、BaseVariant(26行目)が基底型です。ComponentVariant(113行目)はグルーピングの構成要素からハッシュを計算します。CustomFingerprintVariant(191行目)は、利用者が指紋を直接指定する仕組みです。FallbackVariant(106行目)は、ほかの変種ではハッシュを作れないイベントを受け持ちます。構成要素は src/sentry/grouping/component.py にあり、エラー型、エラーメッセージ、ファイル名、関数名などを含みます(240行目から252行目)。各グルーピング設定には識別子があり、src/sentry/grouping/strategies/configurations.py の8行目のレジストリに登録されています。WINTER_2023_GROUPING_CONFIG や FALL_2025_GROUPING_CONFIG のような名前付きの設定は、src/sentry/conf/server.py にあります。版を持つ設定によって、古い設定を残したままアルゴリズムを進化させられます。

第三段階は、シンボル化と検索です。C、C++、Swift、Rust などのネイティブクラッシュは、生のメモリアドレスとして届きます。デバッグシンボルがあって初めて関数名に戻せます。src/sentry/lang/native/symbolicator.py の44行目にある SymbolicatorFunction 列挙型は、Python 側から独立した Symbolicator サービスを呼び出すための接点です。Symbolicator はこのリポジトリには含まれません。検索側では、src/sentry/conf/server.py の1749行目が Snuba のアドレスの既定値を http://127.0.0.1:1218 としています。Snuba は ClickHouse の上に載る問い合わせ層で、検索、傾向、性能統計を担います。 SDK に向き合う入口は、Relay という別の Rust コンポーネントです。プロトコルのペイロードを検証し、レート制限をかけ、機微な情報を取り除いてから、イベントを Python 側に渡します。その実装もこのリポジトリにはありません。 実行環境には Python 3.13 以降が必要です。これは pyproject.toml の requires-python = ">=3.13" で宣言されています。

実用性と検証結果

グルーピングは、最も丁寧に調べるべき機能です。新しいイベントが届くと、エンジンは優先順位の順に変種を試します。一致したカスタム指紋が優先されます。どれも当てはまらなければ、構成要素のハッシュが決め、フォールバックの変種が残りを受け持ちます。利用者が画面でグルーピング規則を変えると、この優先順位の連鎖が変わるため、既存の課題が分割されたり統合されたりすることがあります。 評価では三つの観点が重要です。 第一に、対応範囲の広さです。README には公式 SDK が21種挙げられています。JavaScript、Python、Go、Rust、Java と Kotlin、Swift、C#、C と C++、Dart、そして Unity や Godot などのゲームエンジンを含みます。チームは一つの SDK から始めて、後から増やせます。 第二に、運用の重さです。自前運用のリポジトリ getsentry/self-hosted には、docker-compose.yml、install.sh、clickhouse ディレクトリ、nginx.conf があります。この構成は、リレーショナルデータベース、メッセージキュー、列指向ストア、問い合わせサービス、リバースプロキシが同時に動く完全な配備を示しています。クラッシュ報告だけが必要なチームには重すぎるかもしれません。データを完全に管理したいチームは、この負担を受け入れます。

第三に、ライセンスの境界です。FSL-1.1-Apache-2.0 は社内利用、改変、自前運用を認めます。このコードを基にした競合商用サービスの提供は認めません。社内のプラットフォームチームの多くはこの制限に当たりません。ホスト型の製品を計画する企業は、当たります。 実務では、まずステージング環境のプロジェクトで一つのグルーピング規則を変え、変更前後の課題数を比べてください。問題がなければ、本番の規則を変更します。

業界への影響と今後の展望

Sentry は、業界がエラーをどう捉えるかに影響を与えてきました。グルーピングを、隠れたヒューリスティックではなく、版、識別子、テストを備えたエンジニアリングの対象として扱います。この考え方は、ほかの監視ツールが課題の集約を見せる方法にも影響を与えています。

ライセンスは、ほかのインフラ系プロジェクトも採ってきた妥協を示しています。ソースコードは公開され、読むことができます。社内利用は認められます。直接の再販は制限され、一定期間の後に Apache 2.0 になります。このモデルをオープンソースと呼べるかどうかについては、開発者の間で議論が続いています。

リポジトリからは三つの兆候が読み取れます。第一に、名前付きのグルーピング設定が増えており、アルゴリズムは版ごとに進化しています。第二に、処理量が重要な取り込みとシンボル化は、すでに Rust のコンポーネントで動いています。第三は筆者の見通しであり、このコードベースで確認された事実ではありません。観測データを一つのプラットフォームに集約するチームは、今後も増えると考えられます。

Sources

FAQ

Sentry のリポジトリはどのライセンスを使っていますか。

LICENSE.md には FSL-1.1-Apache-2.0 と記載されています。これは Functional Source License 1.1 で、将来は Apache 2.0 に移行すると定められています。コードの読解と改変は可能ですが、このコードで競合する商用ホスティングを提供することはできません。

Sentry は二つのエラーが同じ課題に属すると、どう判断しますか。

グルーピングエンジンは優先順位の順に変種を試します。一致したカスタム指紋が優先されます。それ以外は、エラー型、エラーメッセージ、ファイル名、関数名などの構成要素からハッシュを計算して判断します。どれも当てはまらなければフォールバックの変種が処理します。根拠は src/sentry/grouping/variants.py です。