error-tracking について
Sentry を導入する開発者向けの設定・運用スキルです。イベントのスクラブ、リリースとコミットの紐付け、認証障害への対応を扱います。
主な機能
- 01Sentry SDK と DSN の設定
- 02二層ルールによるイベントデータの除去
- 03リリースとコミットの紐付け
- 04認証障害と復旧方法の判別
- 05Sentry CLI と MCP の利用方法
活用シーン
- 01プロジェクトへの Sentry 初回導入
- 02イベント内の URL 認証情報の漏えい防止
- 03リリースのコミット紐付け設定
- 04認証情報失効によるサービス劣化の調査
MCP 対応
Sentry MCP は OAuth を使うため、共有 MCP ゲートウェイではなくエージェント自身の設定に登録する方法を説明します。セッション内での問題の閲覧とトリアージに利用できます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ssheleg/ sheleg-dev --skill error-trackingインストール後、Claude Code で/error-trackingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/releases.mdscrubbing.mdsetup.md詳細
error-tracking — 漏えいを防ぎ、スタックトレースにコミットを表示する Sentry の設定
Sentry の追加は SDK のセットアップを 4 行書くだけです。そのため、たいていは正しく設定されません。 以下の 4 つの失敗はすべて、このマシンで、このスキルを使わずに作業していたエージェントが、1 回のセッション中に実際に起こしたものです。
| 発生した失敗 | その影響 |
|---|---|
| 「DSN を取得する」ことを、アカウントが必要な人手による作業だと判断した | アカウントはすでに存在し、CLI も認証済みでした。理由もなくエラートラッキングがオフのままになりました |
EventScrubber が存在し、デフォルトで実行されることを知らずに before_send スクラバーを書いた | どの層が何を保護するのか説明できず、コードが冗長なのか重要な役割を担うのか判断できませんでした |
| MCP が OAuth を使うことを知らなかった | OAuth フローを完了できない共有ゲートウェイに設定していたでしょう |
| DSN を設定してそれで終わりにしようとした | すべての Issue がコミットのないリリースに紐づき、疑わしいコミットの特定が機能しません |
実際に漏えいするもの
Sentry の組み込みスクラバーが照合するのはキー名です。文字列の値の中までは確認しません。 メッセージ、例外値、パンくずリスト内に含まれる認証情報は、そのまま通過します。
2026-08-24 時点の sentry-sdk 2.19.2 で確認した結果:
from sentry_sdk.scrubber import EventScrubber
event = {"message": "could not connect to postgresql://u:SUPERSECRET@host/db"}
EventScrubber().scrub_event(event)
assert "SUPERSECRET" in str(event) # passes — it was NOT scrubbed
EventScrubber はデフォルトで有効で、拒否リストには 32 個のキー(password、
token、api_key、auth、secret、authorization、…)があります。dsn と
database_url は含まれていません。
そのため、すでにログにデータベース URL を記録しているサービス(よくある間違いです)は、 Sentry を追加した途端に同じパスワードを第三者に転送し始めます。ログの場合よりも被害範囲が広がります。
常に 2 つの層を使います:
from sentry_sdk.scrubber import DEFAULT_DENYLIST, EventScrubber
sentry_sdk.init(
dsn=..., environment=..., release=...,
event_scrubber=EventScrubber( # layer 1 — keys
denylist=DEFAULT_DENYLIST + ["dsn", "database_url", "auth_key"],
recursive=True,
),
before_send=scrub_values, # layer 2 — values
send_default_pii=False,
)
第 2 層では、URL 内の認証情報を正規表現で検出します。第 1 層だけでは依然として漏えいすることを確認するテストを書いてください。そのテストがいつか失敗するようになったら、Sentry が値のスクラブを始めたということなので、第 2 層が冗長になった可能性があります。そうした点はテストが失敗したときに学べばよく、最初からテストを省く理由にはなりません。2 つの層(正規表現とそのテスト)については references/scrubbing.md を参照してください。
DSN は認証トークンではありません
この 2 つは別のものであり、混同すると、見当違いの警戒と不用心の両方を招きます。
| DSN | 認証トークン | |
|---|---|---|
| 方向 | 書き込み専用の取り込み | 完全な API アクセス |
| 保存場所 | ビルド済みアーティファクト(クライアント側を含む) | CI のシークレット、開発者のキーチェーン |
| 漏えいした場合 | 誰かが不要なイベントを送信できます。レート制限をかけてローテーションしてください | 誰かが Issue を読んだり、組織を変更したりできます |
| 必要な操作 | エラーの報告 | プロジェクトの作成、Issue の閲覧、リリースの作成 |
リポジトリに DSN があるのは整理されていない状態です。リポジトリに認証トークンがあるのはインシデントです。 CLI も MCP も DSN の必要性をなくすものではありません。これらは Sentry を操作するものであり、アプリを計測するものではありません。不要になるのは、DSN を取得する手作業です。
人手を介さずにセットアップする
これらを手作業と決めつける前に、まず確認してください。すでに済んでいることがよくあります。
sentry auth status # already authenticated? (credentials in ~/.sentry)
sentry org list --json # which orgs this token can see
sentry project list --json # what already exists
既存のプロジェクトから、アプリが必要とする DSN を取得するには:
sentry project view <org>/<project> --json | python3 -c "import json,sys; print(json.load(sys.stdin)[0]['dsn'])"
Sentry を初めてプロジェクトに追加する場合は、references/setup.md を参照してください。インストール、認証、プロジェクトの作成、ホストの設定への DSN の組み込み、MCP の宣言まで、手順全体を説明しています。
認証の問題に見えて、実際はそうではない403
sentry project create は、次のエラーで失敗することがあります。
Your organization has disabled this feature for members.
その組織のオーナーであっても発生します。2026-08-24に確認しました。原因は組織ポリシー allowMemberProjectCreation: false です。このポリシーはユーザーのロールではなくトークンのスコープに基づいて評価されます。また、sentry auth が保存する OAuth デバイスフロートークンには project:admin と team:write は含まれますが、org:write も org:admin も含まれません。チームスコープのエンドポイント(POST /teams/{org}/{team}/projects/)も同じように失敗します。同じポリシーが適用されるためです。
バグだと決めつける前に確認してください。
sentry org view <org> --json | grep allowMemberProjectCreation
sentry api "/" --json # prints the token's actual scopes
解決方法は3つあります。試す価値が高い順に、まずウェブ UI でプロジェクトを一度作成する、組織の設定を変更する、または Internal Integration トークンを発行する方法です。プログラムによるプロジェクト作成に必要な組織レベルの API アクセスを許可するとSentryが明記しているのは、このトークンタイプだけです。Organization Tokens は CI 向けに推奨されていますが、組織レベルの操作はできません。また、個人用トークンは CI での使用が明確に推奨されていません。トレードオフをまとめた表は references/setup.md を参照してください。
sentry と呼ばれるツールは2種類あります
片方のコマンドはもう片方には存在せず、実行しても何も起きないため、混同するとデバッグに余計な手間がかかります。
sentry | sentry-cli | |
|---|---|---|
| 入手先 | cli.sentry.dev、brew install getsentry/tools/sentry | github.com/getsentry/sentry-cli |
| 特徴 | エージェント向け。issue explain、issue plan、gh api のような api | ビルド向け。ソースマップ、デバッグファイル |
| 認証 | sentry auth — OAuth デバイスフロー。~/.sentry/ に保存 | SENTRY_AUTH_TOKEN |
| 両方で可能 | release create / set-commits / finalize / deploy、project、org |
どちらでもリリースコマンドを実行できます。リポジトリごとにどちらかを選び、READMEに明記してください。そうしないと、2人がそれぞれ別の半分を設定することになります。
バージョンを信頼する前に、別の実行ファイルが優先されていないか確認してください。 どちらも異なるプレフィックスにインストールされます。通常、~/.local/bin は /opt/homebrew/bin より先に検索されるため、古いコピーが気づかれないまま使われます。
which -a sentry | while read p; do printf '%-34s %s\n' "$p" "$("$p" --version 2>&1 | head -1)"; done
ここでは、0.43.0があるにもかかわらず、0.38.0が優先されていました。認証情報はバイナリの隣ではなく ~/.sentry/ に保存されるため、古いコピーを削除してもログアウトされません。
MCPはOAuthを使うため、設定場所が決まります
https://mcp.sentry.dev/mcp に未認証リクエストを送ると、次の応答が返ります。
401 www-authenticate: Bearer realm="OAuth", …, resource_metadata="https://mcp.sentry.dev/.well-known/oauth-protected-resource/mcp"
resource_metadata を含むこの www-authenticate ヘッダーが、OAuthかどうかを判定する目印です。OAuthを使う上流は、自身のアドレスをリソースとして宣言します。そのため、ローカルゲートウェイを指定したクライアントは不一致を拒否し、フローが始まりません。OAuth MCP サーバーはエージェント自身の設定に追加し、共有MCPゲートウェイの背後には置かないでください。 接続先を決める前にcurlを実行してください。静的トークンを使う上流はゲートウェイに追加しますが、OAuthを使う上流は追加しません。
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp/<org>/<project>
このMCPは、セッション内での読み取りやトリアージに使います。あくまで作業を加速するためのもので、MCPでできることはすべてCLIでも実行できます。MCPがないマシンでも機能が失われることはありません。
リリース、またはスタックトレースに名前が出ない場合
Sentryのリリースが役に立つのは、そのバージョン文字列がSDKの release と完全に一致している場合だけです。異なっていると、コミットが紐付いていないリリースにイシューが関連付けられ、疑わしいコミットの特定も何も起きないまま失敗します。その結果、配線の問題ではなく「Sentryはあまり優秀ではない」と受け取られてしまいます。
バージョンの情報源を1つに決め、両方で使ってください。Herokuではslugのコミットを使います。
RELEASE = os.getenv("HEROKU_SLUG_COMMIT") or os.getenv("RELEASE")
VERSION="$(git rev-parse HEAD)" # the same value
sentry release create "<org>/$VERSION" --project <project> --finalize
sentry release set-commits "<org>/$VERSION" --auto
sentry release deploy "<org>/$VERSION" production
リリースの記録処理でデプロイを失敗扱いにしてはいけません。 本番環境に到達したデプロイは、リリース呼び出しが失敗したことを理由に失敗として報告してはいけません。各コマンドをガードして、ログを記録したうえで処理を続けてください。デプロイスクリプトの例は references/releases.md にあります。また、--auto に必要なリポジトリ連携についても説明しています。
起動しているプロセスが、正常に動作するサービスとは限りません
2026-08-24 に確認:ボットトークンがローテーションされ、10 分間、プラットフォームは dyno を up と報告し、ログにも問題はありませんでしたが、API はすべての呼び出しに 401 を返し、ユーザーにはサービスが提供されませんでした。システム内には、その違いを見分けられるものがありませんでした。
ヘルス状態は 3 つあります。「起動している」は 1 つの問いではないからです。 ライブネス — プロセスが存在し、ループが動作していること。レディネス — 今すぐ役割を果たせること(認証情報が機能していること)。認証情報が無効なライブプロセスはライブだが、準備未完了であり、ロードバランサーやスーパーバイザーが参照するのはライブネスではなくレディネスです。degraded_auth — 認証に失敗している状態で、次の 2 つのケースでは正反対の対応が必要です。
- 一時的(トークンのローテーション、ネットワークの一時的な問題、新しい接続で解決する
401):バックオフ付きの上限を設けた再試行を行います。また、次回の起動で新しい認証情報が読み込まれるため、再起動も妥当です。「ゼロ以外の終了コードで終了し、クラッシュループが見えるようにする」が正しいのはこのケースです。 - 終端状態/取り消し済み(セッションがサーバー側で無効化された):再起動しても、決して成功しないログインを繰り返すだけです。処理を停止し、準備未完了にし、アカウント名を明記してアラートを出し、新しい認証情報を待ちます — 再起動ループは決して起こしません。上限付きの再試行回数でこの 2 つを区別します。同じ認証エラーに対して再試行を使い切った場合は終端状態であり、「もっと頑張って再試行」ではありません。
復旧の契約 — どちらのスキルも従う、1 つの判断表です。 スーパーバイザーによる再起動は、ポリシーが recoverable の場合にのみ適用されます。どちらのスキルが先に検知したかにかかわらず、terminal イベントは決して再起動されません。
| イベント | ポリシー | スーパーバイザーの対応 | レディネス |
|---|---|---|---|
| 一時的な認証失敗(トークンのローテーション、ネットワークによる 401) | recoverable | 再起動/上限付きの再試行 | 準備未完了 → 成功時に準備完了 |
| 同じ認証エラーで再試行を使い切った | terminal | 停止、アラート、新しい認証情報を待つ | 再認証まで準備未完了 |
| 取り消し済み/無効化されたセッション(MTProto またはベアラー) | terminal | 停止、アラート、新しい認証情報を待つ | 再認証まで準備未完了 |
取り消し済みのセッションが該当する行は、どちらのパックでも同じです。そのため、同一のイベントに正反対の対応をすることはありません。error-tracking と telegram-userbots はこの 1 つの契約を明示しており、terminal ポリシーを再起動するスーパーバイザーこそ、この表が防ぐべきバグです。
Sentry が役立つのは、何かが例外を発生させた場合だけです。例外を発生させずに接続が機能しなくなっても、イベントはまったく生成されません。Cron モニター(sentry monitor)は、ジョブの実行が停止するケースをカバーします。
劣化時の対応
- **ホストの機能はさまざまです:**現在のクライアントのシェル、ネットワーク、パッケージのインストール権限、MCP およびスキルの呼び出しサポートを確認します。Claude 以外のホスト名から、それらが利用できないと推測してはいけません。前提条件がそろっている場合は CLI/SDK の方法を使います。制限付きコンテナーでは、利用できない手順を明示し、セットアップを実行したと偽らずに設定を準備します。スキルのみをインストールしても、プラグインコマンド、MCP サーバー、フックは登録されません。
sentryCLI がない場合:その旨を一度伝えたうえで、トークンを使って REST API を直接利用する(curl https://sentry.io/api/0/…)か、単発の作業にはウェブ UI を使います。不足しているバイナリを探して繰り返し試してはいけません。- MCP がない場合:機能は失われません —
sentry issue listでイシューを読み取れます。 - 認証されていない場合、またはスコープが不足している場合:対話型認証は人が行う手順です。正確なコマンドを一度だけ伝え、何がブロックされているかを明示し、それを必要としない作業はすべて続行します。
推測せず、検証する
sentry auth status # authenticated, and as whom
sentry api "/" --json # the token's real scopes
sentry project view <org>/<project> --json # the DSN, and that it exists
sentry release list <org>/<project> --limit 3 # releases arriving at all
python3 -c "import sentry_sdk; print(sentry_sdk.VERSION)"
このページの記述を信頼するのではなく、再測定する価値のある主張が 2 つあります。どちらもバージョンによって変わるためです。デフォルトの拒否リストの内容と、SDK が値のスクラブを開始しているかどうかです。それぞれのコマンドは references/scrubbing.md に記載されています。
トリガー
ここに誘導するその他のフレーズ:「エラートラッキングを設定」、「sentry mcp」、「エラーからシークレットをスクラブ」、「疑わしいコミット」、「Sentry が空なのはなぜ」、「Sentry のリリース」、「可観測性」。
0.16.2 の説明からここに移動:「リリーストラッキング」、「Sentry のシークレット」。