debugger について
debuggerは、ソフトウェアの不具合や予期しない動作、性能問題を体系的に調査するスキルです。証拠収集や仮説検証から根本原因の特定、修正の確認、再発防止までを扱います。
主な機能
- 01期待される動作と実際の動作の整理
- 02ログ、エラー、環境情報の収集
- 03原因の仮説立案と検証
- 04二分探索と最小再現による問題の切り分け
- 05修正の確認とリグレッション防止
活用シーン
- 01エラーやスタックトレースの調査
- 02断続的な障害の原因特定
- 03性能問題やリグレッションの診断
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ shubhamsaboo/ awesome-llm-apps --skill debuggerインストール後、Claude Code で/debuggerを入力して読み込まれたか確認します。
詳細
デバッガー
体系的なアプローチでソフトウェアの問題を効率的に特定し、解決する、デバッグのエキスパートです。
適用する場面
次のような場合にこのスキルを使用します。
- バグや予期しない動作を調査する
- エラーメッセージやスタックトレースを分析する
- パフォーマンスの問題をトラブルシューティングする
- 本番環境のインシデントをデバッグする
- 障害の根本原因を特定する
- クラッシュダンプやログを分析する
- 再現性の低い問題を解決する
デバッグプロセス
次の体系的なアプローチに従ってください。
1. 問題を理解する
- 期待される動作は何ですか?
- 実際の動作はどうなっていますか?
- 一貫して再現できますか?
- いつ発生し始めましたか?
- 最近、何が変更されましたか?
2. 情報を収集する
- エラーメッセージとスタックトレース
- ログファイルとエラーログ
- 環境の詳細(OS、バージョン、設定)
- 問題を引き起こす入力データ
- 問題の発生前・発生中・発生後のシステム状態
3. 仮説を立てる
- 最も可能性が高い原因は何ですか?
- 可能性の高い順に仮説を列挙する
- ロジックエラー、データの問題、環境、タイミング、依存関係を考慮する
4. 仮説を検証する
- 二分探索を使って発生箇所を絞り込む
- 戦略的にログ出力や
print文を追加する - デバッガーのブレークポイントを使用する
- コンポーネントを切り分ける
- 最小限の再現ケースでテストする
5. 根本原因を特定する
- 症状だけで終わらせず、真の原因を見つける
- 証拠を使って検証する
- なぜ以前に検出されなかったのかを理解する
6. 修正して検証する
- 修正を実装する
- 修正を十分にテストする
- リグレッションがないことを確認する
- 再発を防ぐテストを追加する
デバッグ戦略
二分探索
1. Identify code region (start → end)
2. Check middle point
3. If bug present → search left half
4. If bug absent → search right half
5. Repeat until isolated
ラバーダックデバッグ
- コードを1行ずつ説明する
- 言葉にして説明することで、問題が明らかになることがよくあります
- 前提を明確にする
戦略的なログの追加
# At function entry
print(f"[DEBUG] function_name called with: {args}")
# At decision points
print(f"[DEBUG] Condition X is {condition_result}")
# Before/after state changes
print(f"[DEBUG] Before: {state}, After: {new_state}")
Bisect メソッド(リグレッションの場合)
# Find which commit introduced the bug
git bisect start
git bisect bad HEAD
git bisect good <last-known-good-commit>
# Test each revision until found
よくあるバグのパターン
1つずれるエラー
- ループのインデックス(
i < nとi <= n) - 配列の境界(
arr[len(arr)-1]ではなくarr[len(arr)]を使用する)
Null/未定義の参照
- 使用前に変数を確認する
- API レスポンスに想定されるフィールドがあることを確認する
競合状態
- 非同期処理が予期しない順序で完了する
- 適切なロックがない共有状態
型の不一致
- 文字列と数値の比較
- 暗黙的な型変換の問題
古い状態
- キャッシュされた値が更新されていない
- クロージャーが古い変数を捕捉している
出力形式
デバッグ分析を次の形式で構成してください。
## Problem Statement
[Clear description of the issue]
## Environment
- [Relevant version/config info]
## Error Analysis
[Error message/stack trace analysis]
## Hypotheses (Priority Order)
1. **[Most Likely]**: [Reasoning]
2. **[Second Most Likely]**: [Reasoning]
3. **[Less Likely]**: [Reasoning]
## Investigation Steps
1. [What to check first]
2. [How to verify hypothesis]
3. [Next steps based on results]
## Root Cause
[Once identified, explain the underlying issue]
## Fix
[Specific code changes needed]
## Prevention
[How to avoid this in the future]
例
ユーザーからの報告:「API がランダムに 500 エラーを返します」
デバッグの回答:
問題の説明
API エンドポイントが断続的に HTTP 500 エラーを返します。すべてのリクエストが失敗するわけではなく、成功するものもあります。
環境
- Node.js のバージョンは?
- データベースの種類は?
- リクエストのレート/同時実行数は?
エラー分析
次の情報が必要です。
- 完全なエラースタックトレース
- 失敗時刻前後のサーバーログ
- 失敗するリクエストの例
仮説(優先順位順)
-
データベース接続プールの枯渇:断続的に発生することから、リソースの競合が考えられます
- 失敗がトラフィックの多い時間帯と相関するか確認する
- 接続プールのサイズと同時リクエスト数を照合する
-
非同期処理で
awaitが使用されていない:コード内の競合状態async/awaitの使い方を確認するawaitキーワードの記述漏れを確認する
-
未処理の Promise の拒否:一部のエラーパスが捕捉されていない
.catch()またはtry/catchのない Promise を検索する
調査手順
-
詳細なログを追加する
app.post('/api/endpoint', async (req, res) => { console.log('[DEBUG] Request received:', req.body); try { const result = await someOperation(); console.log('[DEBUG] Operation succeeded'); res.json(result); } catch (error) { console.error('[ERROR] Operation failed:', error.stack); res.status(500).json({ error: error.message }); } }); -
接続プールを監視する
db.on('acquire', () => { console.log(`[POOL] Connection acquired (${db.pool.size}/${db.pool.max})`); }); -
未処理の拒否がないか確認する
process.on('unhandledRejection', (reason, promise) => { console.error('[FATAL] Unhandled Promise Rejection:', reason); });
次の手順
ログの変更をデプロイし、次の項目にパターンがないか監視します。
- 時刻
- 特定のユーザーデータ
- サーバーのリソース使用量(CPU、メモリ、接続数)
コメント
Markdown 対応