/note/tech

Sentry 互換の GlitchTip を AI 開発のハーネスにする

要約:

■ 1. 背景と課題意識

  • エージェント開発による大規模化:
    • コーディングエージェントのおかげで大規模なシステムの構築が容易になった
    • 趣味で Claude Code や Codex を使い、多数のサブシステムを持つアプリケーションを開発している
    • 構成はバックエンドとフロントエンドからなる
    • システムは一人で目を配れる規模を超えつつある
    • 変更のたびに画面やログを確かめて回るのは非現実的になった
  • 静的検査による品質ベースライン:
    • 型検査、lint、テストがエージェント開発における品質のベースラインとして機能している
    • エージェントはこれらを自分で実行し、作業のミスを発見できる
  • 実行時エラーの見落とし:
    • 実行時エラーは静的解析では発見しにくい
    • 例として、ブラウザ console のエラーやバックエンドのスタックトレースを見落とすおそれがある
    • エラーの発生箇所は散らばっており、当たりをつけてログを tail する必要がある
  • 解決の方針:
    • エラーを集約してエージェントが読めるよう整備すれば、実行時エラーの有無もベースラインにできる
    • Sentry 互換のエラートラッカー GlitchTip を開発ワークフローに組み込み、エージェントのハーネスに仕立てた

■ 2. GlitchTip の特徴

  • 既存の Sentry 計装の流用:
    • 本番アプリに Sentry を導入していれば、エラーを構造化して送信する計装は済んでいる
    • GlitchTip は Sentry SDK 互換であり、DSN の向き先を変えるだけでローカルに集約できる
    • Go では github.com/getsentry/sentry-go がそのまま使える
  • REST API の存在:
    • エラーの一覧からスタックトレースまで API で取得できる
    • Sentry 互換の API である点もエージェントにとって扱いやすい
  • 軽量な構成:
    • 本家 Sentry の Self-hosted 版は多数のコンテナで構成され、開発マシンに常駐させるには重すぎる
    • GlitchTip は本体のほか PostgreSQL と Redis 程度で動作する
    • インストールガイドに Docker Compose の構成例がある

■ 3. DSN の固定

  • DSN が変わる問題:
    • Sentry 系の DSN は {scheme}://{public_key}@{host}/{project_id} という形式である
    • DSN は初期化時に生成されるため、環境を作り直すたびに変わる
    • エージェントが迷わないよう固定しておきたい
  • 初期化スクリプトによる固定:
    • DSN を Docker Compose 側の環境変数として定義する
    • 初期化スクリプトが GlitchTip 側の DSN をその値でオーバライドする
    • 組織とプロジェクトの作成も初期化スクリプトに任せる
    • GlitchTip 本体は初期化コンテナの正常終了後に起動させる
    • アプリ側の SENTRY_DSN にも同じ値を渡す
  • 疎通確認:
    • 起動後、各サービスから実際にエラーを1件ずつ送り、GlitchTip に届くことを確かめる
    • ローカル開発では SampleRate など送信を止める設定が入っており、エラーが捨てられていることがある

■ 4. エラーを要約するスクリプト

  • スクリプトの役割:
    • 集約したエラーをエージェントに見てもらう仕組みとして、PR 作成前に実行するスクリプトを用意した
    • 前回実行時(チェックポイント)以降に発生した未解決のエラーだけを GlitchTip の API から取得して表示する
    • 出力はエラーのタイトル、初回発生時刻、件数、パーマリンクからなる
  • チェックポイントの記録先:
    • .git 配下に記録する
    • 自然と Git 管理外になる
    • Worktree を使う場合もツリーごとの記録になる
  • チェックポイントの巻き戻し:
    • エラートラッカーはイベントを非同期に取り込むため、現在時刻をそのまま記録すると境界のエラーを取りこぼしうる
    • 取り込み遅延を見込んで現在時刻から数秒程度巻き戻して記録する
    • 境界のイベントが重複して出力されることはある
    • 取りこぼしと重複なら、重複に倒す方が堅牢である
  • 終了コードの扱い:
    • エラーを検出しても終了コードは 0 のままにする
    • ESLint の warning と同じ位置づけで、検出は機械的に行う
    • 対応するかどうかはエージェントに内容を見て裁量的に判断させる
  • ノイズの除外:
    • ネットワークエラーなど対応不要な一時的エラーも発生する
    • スクリプトに除外リストを持たず、GlitchTip 上で Resolve 扱いにする
    • Unresolved の Issue だけをクエリすればノイズは消える
    • 同じエラーが再発すれば新しい Issue として立つため、検出性は低下しない

■ 5. ハーネスとしての完成

  • エージェントへの指示:
    • CLAUDE.md(AGENTS.md)の完了条件に「実行時エラーの不存在」セクションを追加する
    • PR 作成前にスクリプトを実行し、作業中に新規エラーが発生していないことを確認させる
    • エラーを発見した場合は修正を試みさせる
    • エラーを Resolve 扱いにする場合はユーザーの許可を得させる
  • 導入の効果:
    • エージェントは PR 作成前にスクリプトを実行するようになる
    • 新規エラーがあれば API でスタックトレースを引いて原因を調べ、修正する
    • lint やテストと同じレベルに、実行時エラーの不存在というベースラインが1つ増えた
  • 実効性の強化:
    • より実効性を持たせるなら、gh pr create を対象にした Hooks を追加するのがよい

■ 6. まとめ

  • 導入のハードルの低さ:
    • Sentry による計装が済んでいれば、DSN を GlitchTip に向けるだけでよい
    • それだけでローカル開発用に実行時エラーを集約できる
  • 品質ベースラインの担保:
    • 差分を出力するスクリプトを用意し、PR 提出前の完了条件とすることで品質のベースラインを担保できる
  • エラートラッカーの新たな用途:
    • エラートラッカーは本番運用のためのツールだと考えていた
    • エージェントと協働する時代では、ローカル開発でのエラーの追跡と集約にも非常に有用である