深夜2時にアラートで叩き起こされて、半分眠ったままログを眺めた経験はないでしょうか。私はあります。何度もあります。チームがいる会社員ならオンコールローテーションが組めるのですが、個人開発でアプリやSaaSを運営していると、結局「自分が起きるしかない」という現実が突きつけられます。
そんなときに私が頼り始めたのが、Claude をデバッグの相棒として明確に設計し直すことでした。「とりあえずログを貼って聞く」のではなく、ログ要約・原因仮説の生成・最小再現コードの作成という3つの仕事を、専用のプロンプトと前処理パイプラインで分担させる。すると、以前なら30分以上かかっていた一次調査が、長くて10分、運が良ければ3分で終わるようになりました。
ここではその設計を「相棒として使うためのアーキテクチャ」として体系化してお伝えします。すぐコピーして使えるプロンプトと、本番ログを安全に渡すための前処理コード、そして実際にうまくいかなかったパターンも含めて、現場感のある形でまとめました。
なぜ「Claudeにデバッグを任せる」が個人開発者に効くのか
正直に言うと、最初は「Claude に長いログを貼って聞く」程度のことしかしていませんでした。それでもそれなりに役には立ったのですが、スタックトレースが長くなると Claude も読み飛ばしますし、毎回「これはエラーログです」「Node.jsです」と説明し直すのも面倒でした。
転機になったのは、デバッグという作業を細かく分解してみたことです。本番でアラートが鳴ったとき、人間が頭の中でやっている作業はざっくり以下の3つです。
- 凝視フェーズ: 大量のログから関係ありそうな行を探し、時系列でつなぐ
- 仮説フェーズ: 「これが原因かも」というアタリをいくつか立て、優先順位をつける
- 検証フェーズ: 仮説を検証する最小再現コードを書き、ローカルで実行する
このうち凝視フェーズは、人間の集中力が一番奪われる箇所です。深夜眠い頭でログを舐めるように読むのは、認知的に最も辛い。一方で、構造化された出力さえもらえれば、仮説と検証は経験のある開発者なら早い。だから「凝視フェーズを Claude に任せる」のが最大のレバレッジになります。
私が好きなのは、Claude を「ジュニアエンジニアの相棒」と見なす考え方です。判断の最終責任は自分にありますが、面倒な前処理と一次仮説の整理は任せる。これだけで、深夜の対応が「絶望」から「会話」に変わります。
デバッグ相棒に渡すべき「3つのコンテキスト」
Claude に意味のあるアウトプットを返してもらうには、最初に渡す情報の質を上げるのが一番効きます。私は「3層コンテキスト」と呼んでいます。
- アプリの設計コンテキスト: 使っているフレームワーク、主要なライブラリのバージョン、デプロイ環境(私の場合は Cloudflare Workers / Next.js / Stripe など)
- 直近の変更コンテキスト: 最後にデプロイした PR のサマリー、過去24時間のリリース履歴、最近触ったファイルパスのリスト
- 症状コンテキスト: 実際に起きているエラーログ、スタックトレース、影響範囲(誰が・どの機能で・いつから)
このうち1番目と2番目は、毎回貼り直すのが面倒なので、テンプレート化して Claude Projects のプロジェクト指示やシステムプロンプトに固定しておくのがコツです。3番目だけ毎回変える運用にすると、起動コストが劇的に下がります。
Claude のコンテキスト管理 で書いた通り、コンテキストは多ければ良いというものではなく、目的に対して関連度の高い情報を絞り込むのが鍵です。デバッグの場合、無関係なログを200行混ぜると Claude の注意がそちらに引っ張られて精度が落ちます。
ログ要約プロンプトの設計
最初の道具は、ログ要約専用のプロンプトです。生のログをそのまま投げるのではなく、Claude に「読みやすく構造化して、次のアクションに繋げやすい形にしてもらう」のが目的になります。
何を解決するコードか — エラーログを「タイムライン形式の症状サマリー」に変換し、次の仮説生成プロンプトにそのまま渡せる中間表現を作ります。
# log_summarizer.py
import anthropic
import json
client = anthropic.Anthropic()
LOG_SUMMARY_SYSTEM = """あなたは本番運用のシニアSREです。
ログを読み、以下のJSON形式で構造化サマリーを返してください。
出力形式(厳守):
{
"incident_window": "発生時刻のISO8601範囲",
"primary_error": "最も頻度の高い、または最初に出たエラーの1行説明",
"error_chain": [{"timestamp": "...", "service": "...", "message": "..."}, ...],
"affected_users": "影響範囲の推定(unknownでも可)",
"deduped_count": {"error_signature": 件数},
"first_questions": ["人間が次に確認すべき質問を最大3つ"]
}
ルール:
- スタックトレースは最初の3フレームだけ抜粋
- PII(メール・トークン・氏名)が見えたら[REDACTED]に置換
- 確信が持てないフィールドは "unknown" を入れる(空文字列禁止)
"""
def summarize_logs(raw_logs: str) -> dict:
"""生ログを構造化サマリーに変換"""
try:
msg = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=2000,
system=LOG_SUMMARY_SYSTEM,
messages=[{"role": "user", "content": raw_logs}],
)
# Claudeはたまにコードフェンスで囲むので除去
text = msg.content[0].text.strip()
if text.startswith("```"):
text = text.split("```")[1]
if text.startswith("json"):
text = text[4:]
return json.loads(text)
except json.JSONDecodeError as e:
# 失敗時は素の文字列を返してフォールバック
return {"_raw": msg.content[0].text, "_parse_error": str(e)}
except anthropic.APIError as e:
return {"_api_error": str(e)}
# 期待する出力例
# {
# "incident_window": "2026-04-29T02:14:00Z/2026-04-29T02:18:00Z",
# "primary_error": "Stripe webhook signature verification failed",
# "error_chain": [...],
# "affected_users": "estimated 12 paid users",
# "deduped_count": {"InvalidSignature": 47, "TimeoutError": 3},
# "first_questions": [
# "STRIPE_WEBHOOK_SECRET が直近のデプロイで変更されたか",
# "リクエストの timestamp ヘッダが現在時刻から大きくズレていないか",
# "Cloudflare 側で本文の改変が起きていないか"
# ]
# }
なぜ JSON で返させるかというと、後続のプロンプトに機械的に渡せるからです。自然文のまま受け取ると、毎回フォーマットが揺れて自動連携が壊れます。first_questions を 3 個に制限しているのは、人間が一度に処理できる仮説の数を意識しているからです。10個出されても結局上から3つしか追いません。
スタックトレースを最初の3フレームに絞るのは、長すぎるコンテキストが Claude の精度を下げるのを防ぐためです。本当にスタックの奥が問題のときは、後段の検証フェーズで追加で渡します。
原因仮説の生成と検証 — Hypothesis-Driven プロンプト
要約サマリーが手に入ったら、次は仮説生成です。ここで重要なのは「リストを並べて終わり」ではなく、「各仮説に対する確認方法」までセットで返してもらうことです。
何を解決するコードか — 構造化サマリーを入力に、優先度付きの仮説リストと、それぞれを確認するためのコマンドや確認手順を生成します。
# hypothesis_generator.py
import anthropic
import json
client = anthropic.Anthropic()
HYPOTHESIS_SYSTEM = """あなたは本番障害の一次対応に強いシニアエンジニアです。
構造化されたインシデントサマリーを入力に、原因仮説を出してください。
出力形式(JSON):
{
"hypotheses": [
{
"id": "h1",
"summary": "1行の仮説",
"likelihood": "high|medium|low",
"evidence_in_logs": ["サマリー内のどの記述が根拠か"],
"verification": {
"type": "command|query|manual",
"action": "実行すべきコマンドまたは確認手順",
"expected_if_true": "この仮説が正しければ何が見えるか"
},
"rollback_safe": true
}
],
"recommended_first": "h1",
"do_not_jump_to": "ただちに本番DBを触る・ロールバックを連打する等の禁忌があれば明記"
}
ルール:
- 仮説は最大4つまで
- 各仮説は独立に検証可能であること
- 検証コマンドはreadOnlyを優先(本番DBに書き込まない)
- データ削除や migration を含む対応は rollback_safe: false にする
"""
def generate_hypotheses(summary: dict, app_context: str) -> dict:
user_msg = f"""# アプリのコンテキスト
{app_context}
# インシデントサマリー
{json.dumps(summary, ensure_ascii=False, indent=2)}
このインシデントの一次対応として、確認すべき仮説をJSONで返してください。
"""
msg = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=2500,
system=HYPOTHESIS_SYSTEM,
messages=[{"role": "user", "content": user_msg}],
)
text = msg.content[0].text.strip()
if text.startswith("```"):
text = text.split("```")[1]
if text.startswith("json"):
text = text[4:]
return json.loads(text)
このプロンプトの肝は verification.type を command|query|manual に分けたことです。Claude は油断すると「DBを直接書き換えてください」のような危険な指示を平気で出してきます。型を区切ることで、人間が「これは command だから自動実行できる」「これは manual だから自分で確認」と判別しやすくなります。
do_not_jump_to というフィールドを設けたのも、深夜の眠い頭で「とりあえずロールバック」をやって被害を広げるのを防ぐためです。私は実際にこれで一度救われました。Claude が「DB の migration を含むコミットなので、ロールバックすると整合性が壊れる可能性があります」と教えてくれたのです。
再現用最小コードの自動生成 — repro-script プロンプト
仮説の中で一つ怪しいものが絞れたら、最小再現コードを Claude に書かせます。これがあると、ローカルで仮説を検証できるので、本番をいじらずに済みます。
何を解決するコードか — 仮説1つを入力に、ローカルで実行できる最小スクリプトと、想定される実行結果を生成します。
# repro_generator.py
import anthropic
client = anthropic.Anthropic()
REPRO_SYSTEM = """あなたは本番障害の再現コードを書く専門家です。
仮説を入力に、ローカルで実行可能な最小再現スクリプトを生成してください。
出力形式:
1. ## 前提
実行に必要な環境変数・依存パッケージ
2. ## 再現コード
```python (またはshellなど) のコードフェンス
3. ## 想定される出力
仮説が正しい場合・正しくない場合のそれぞれ
4. ## 安全性
このスクリプトが本番に影響しない理由(または影響する場合の警告)
ルール:
- 本番DBに書き込まない(read-onlyまたはローカルの再現環境を使う)
- 外部APIを叩く場合は、最小回数(1〜3回)に絞る
- 必要ならMockサーバーを立てる手順も含める
"""
def generate_repro(hypothesis: dict, tech_stack: str) -> str:
user_msg = f"""# 技術スタック
{tech_stack}
# 検証したい仮説
{hypothesis}
ローカルで再現できる最小スクリプトを書いてください。
"""
msg = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=3000,
system=REPRO_SYSTEM,
messages=[{"role": "user", "content": user_msg}],
)
return msg.content[0].text
私が個人開発で使うときは、ここで生成されたスクリプトを scripts/repro/ 配下にそのまま保存しておきます。同じ症状が再発したときに「前にこういうので調べたな」と参照できますし、似たような障害のテストケースを書く下地にもなります。
ちなみに、コード生成の精度をさらに上げたい場合は、技術スタック情報を Claude Projects のナレッジベース に固定しておくと、毎回貼り直さずに済みます。
本番ログを安全に渡すためのマスキングと前処理
ここまで「Claude に渡す」と書いてきましたが、本番ログにはユーザーのメールアドレス、認証トークン、PII が混ざっています。これをそのまま外部APIに送るのは、規約的にもプライバシー的にも避けるべきです。
何を解決するコードか — ログを Claude に渡す前にマスキングする、軽量な前処理パイプラインを実装します。
# log_sanitizer.py
import re
from typing import Pattern
# パターンは追加しやすい構造にする
SENSITIVE_PATTERNS: list[tuple[Pattern[str], str]] = [
# メールアドレス
(re.compile(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}"), "[EMAIL]"),
# JWT (3セグメント、各セグメントbase64url)
(re.compile(r"eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+"), "[JWT]"),
# Stripe sk_live / sk_test
(re.compile(r"sk_(live|test)_[A-Za-z0-9]{16,}"), "[STRIPE_KEY]"),
# GitHub PAT
(re.compile(r"ghp_[A-Za-z0-9]{20,}"), "[GH_PAT]"),
# Anthropic API Key
(re.compile(r"sk-ant-[A-Za-z0-9_-]{20,}"), "[ANTHROPIC_KEY]"),
# クレジットカード番号らしき16桁
(re.compile(r"\b(?:\d[ -]*?){13,19}\b"), "[CC_NUMBER]"),
# IPv4
(re.compile(r"\b(?:\d{1,3}\.){3}\d{1,3}\b"), "[IP]"),
]
def sanitize_log(log: str, max_lines: int = 300) -> str:
"""ログをマスキングし、行数制限する"""
redacted = log
for pattern, replacement in SENSITIVE_PATTERNS:
redacted = pattern.sub(replacement, redacted)
# 長すぎるログは前後を残して中央を省略
lines = redacted.splitlines()
if len(lines) > max_lines:
head = lines[: max_lines // 2]
tail = lines[-max_lines // 2 :]
skipped = len(lines) - len(head) - len(tail)
return "\n".join(head + [f"... ({skipped} lines skipped) ..."] + tail)
return redacted
# 簡単なテスト
if __name__ == "__main__":
sample = """
[2026-04-29T02:14:00Z] ERROR user=alice@example.com token=eyJhbGciOiJIUzI1NiJ9.payload.sig
[2026-04-29T02:14:01Z] Stripe key sk_live_AbCdEf1234567890abcdef leaked!
""".strip()
print(sanitize_log(sample))
# 期待出力:
# [2026-04-29T02:14:00Z] ERROR user=[EMAIL] token=[JWT]
# [2026-04-29T02:14:01Z] Stripe key [STRIPE_KEY] leaked!
ポイントは、マスキングを「ログを書く時」と「Claude に渡す時」の二重で行うことです。ログ自体にも PII が残らない設計が理想ですが、現実には Stripe の Webhook ログなどで意図せずトークンが残ることがあります。Claude に渡す直前にもう一度この関数を通すことで、二重防御になります。
行数制限を 300 行にしているのは、私の経験則です。これより多いと Claude がログの後半を読み飛ばす確率が上がります。本当に必要なら、要約フェーズで一度コンプレッションしてから次に進ませるのが得策です。
よくある落とし穴と回避パターン
ここからは、私が実際に運用していて遭遇した「やってしまいがちなパターン」と回避策をまとめます。
1. 「とにかく全ログを貼る」をやらない
最初の頃、私は本番ログを丸ごと10万行貼って Claude に投げていました。結果、トークン代が跳ね上がったのに、回答は「色々起きていますね」レベルの粒度。やめましょう。要約フェーズを必ず挟み、生ログは「サマリーを補強する材料」として後段に渡すのが正解です。
2. 仮説を検証せず鵜呑みにしない
Claude の仮説は「ジュニアエンジニアが30秒で考えた1次案」と見なすのが安全です。確かに筋は通っていますが、自分のコードベースの細かい事情までは知りません。verification.action を必ず実行してから判断する癖をつけてください。
3. 「自動修正コミット」までエージェントに任せない
Claude Code でコミットまで任せる運用 は確かに強力ですが、本番障害対応の最初の30分で自動コミットさせるのはお勧めしません。原因が確定する前にコードに手を入れると、後で「あのコミットで状況が変わってしまった」というメタ障害が起きます。診断と修正は明確に分けましょう。
4. ロールバックを安易に勧めさせない
do_not_jump_to フィールドを設けた理由がここです。Claude は過去のログから「直近のデプロイ後に発生」を推定すると、すぐ「ロールバックしては」と提案してきます。しかし、DB マイグレーションが含まれているデプロイは安易にロールバックできません。仮説プロンプトの中で「rollback の安全性」を明示的に判定させると、このリスクを下げられます。
5. ログのコンテキスト境界を曖昧にしない
複数のサービスのログを混ぜて貼るときは、必ずヘッダーで区切ってください。
=== Service: stripe-webhook-worker ===
[2026-04-29T02:14:00Z] ...
=== Service: nextjs-app ===
[2026-04-29T02:14:01Z] ...
これがないと、Claude は「どのログがどのサービスのものか」を文脈から推測することになり、誤った因果関係を作り出します。境界を明示することが、推論の質を上げる最低コストの対策です。
実際のSaaSで運用する自動連携パターン
最後に、私が個人で運用している小さな SaaS で、この相棒システムをどう自動化しているかを共有します。
仕組みはシンプルです。Sentry や Cloudflare Logpush から重要なエラーが来たら、Cloudflare Workers のキューに入れて、定期的にバッチでまとめて要約・仮説生成までやらせ、結果を Slack の専用チャンネルに投げます。
擬似コード(Workers の Queue ハンドラ)はこんな具合です。
// queue_handler.ts
export default {
async queue(batch: MessageBatch<ErrorEvent>, env: Env) {
const grouped = groupByService(batch.messages);
for (const [service, events] of grouped) {
const rawLogs = events.map(e => e.body).join("\n");
const sanitized = sanitizeLog(rawLogs); // log_sanitizerのTS版
const summary = await summarizeLogs(env.ANTHROPIC_API_KEY, sanitized);
// 仮説までやるのはhigh重要度のみ(コスト管理)
const isHigh = events.some(e => e.body.includes("CRITICAL"));
const hypotheses = isHigh
? await generateHypotheses(env.ANTHROPIC_API_KEY, summary, APP_CTX)
: null;
await postToSlack(env.SLACK_WEBHOOK, formatReport(service, summary, hypotheses));
}
},
};
ここで使っている Prompt Caching はコスト面で必須です。LOG_SUMMARY_SYSTEM のような長めのシステムプロンプトをキャッシュしておくと、リクエスト1回あたり数千トークン分のコストが下がります。
isHigh で仮説生成を分岐しているのは、全エラーで仮説まで作るとコストが膨らむからです。私の運用では、Slack 通知を見て「これは深掘りしたい」となったら手動で仮説プロンプトを叩く運用にしています。完全自動化は気持ちいいですが、無視されがちなアラートに対しても課金が発生するので、人間のトリガーを残しておくのが現実的です。
実例 — Stripe Webhook タイムアウトの夜
具体的なエピソードを一つ。数ヶ月前、私が運営している小さな SaaS で、日曜の朝4時頃から Stripe からの Webhook 配信が次々に拒否される現象が起きました。Sentry を見ると、InvalidSignature エラーが約4分の間に50件ほどクラスタリングしていて、それ以外の手がかりはほとんどありませんでした。
このパイプラインがなければ、私はおそらく20分以上、眠い目でログを舐めるように読んでいたと思います。実際にやったことは、生ログのバッチをサニタイザに通し、要約プロンプトを叩き、返ってきた JSON の first_questions を読むだけ。中身はこんな感じでした。
- 「直近のデプロイで
STRIPE_WEBHOOK_SECRET が変更されていないか」
- 「リクエストの timestamp ヘッダがサーバ時刻からズレていないか」
- 「Stripe と Worker の間で Body が書き換えられていないか」
3つのうち1つ目はデプロイ履歴を一瞬で確認して除外、2つ目もメトリクスでズレていないことを確認できました。仮説プロンプトは「Cloudflare 側でのボディ変換」を medium で挙げていて、根拠として「直近の Worker ルート変更」を引いていました。これに沿って curl で再現コマンドを叩いたら、想定外の JSON 再シリアライズが起きていることが特定でき、ページから PR まで12分で到達しました。
Claude が問題を解いたわけではありません。問題を解いたのは私です。ただ、Claude が「凝視フェーズの20分」を「3つの質問を読む90秒」に圧縮してくれた。この圧縮こそが、相棒を持つことの実用的な価値だと感じています。
モデル選択とコストの本音
つい実用的モデルをデフォルトにしたくなりますが、キューが連続発火するシステムではコストが地味に効いてきます。私はティア構成にしています。
- 要約フェーズ:
claude-sonnet-4-6 がスイートスポット。Haiku 系だと JSON フィールドを落とすことがあり、Opus は構造化抽出にはオーバースペックです。Prompt Caching と組み合わせれば、1リクエストあたりのコストは大きく抑えられます
- 仮説生成フェーズ: 同じ Sonnet。要求される推論は「丁寧なジュニアエンジニア」レベルで、研究級の精度は不要です
- 再現コード生成フェーズ: ここも Sonnet。スタックの特殊な部分で詰まるなら、まずモデルを上げるより、関連モジュールをそのまま貼って与えることを試してください
- ポストモーテム執筆: ここだけは Opus に切り替えることがあります。チャンネルにシェアする報告書は、文章の質が後で効いてくるからです
実装上の重要な学びは「コストを必ず観測すること」です。私は KV のシンプルなカウンタにインシデントごとのトークン使用量を記録し、日次キャップを設定しています。これがなかったら、誤設定したキューがメッセージを延々リトライして一晩で数千ドルを溶かしていた事故が、2回ほど発生していました。可観測性が足りないと、相棒は突然キレた家計簿になります。
エージェントに任せてはいけない領域の線引き
何ヶ月かこのセットアップで運用していますが、エージェントに自動でやらせる範囲については保守的なままです。プレッシャー下で線引きが崩れないよう、文書化しています。
- ログを読んで要約させる: 完全に委譲してOK
- 仮説と検証手順を出させる: 完全に委譲してOK
- read-only な検証コマンドの自動実行: コマンドの allowlist に入っているもの限定、かつサンドボックス内に限る
- 本番状態を触る操作: 絶対に自動化しありません。DB 書き込み、Feature Flag のトグル、トラフィック切替は深夜3時でも自分の手で
- 公開ステータスページへの投稿: 絶対に自動化しありません。顧客向けの言葉は、トーン1つで信頼が変わります
- PR のクローズ・マージ: diff を必ず自分で読む。Claude に PR を起こさせるのは構いませんが、Merge ボタンは人間に残しておきます
注意したいのは「成功体験後の機能拡張誘惑」です。一度うまくいくと、つい「次は自動で適用させよう」と思ってしまう。少なくとも10件以上のインシデントで安定運用が確認できるまで、その欲求は抑えるのが安全です。1回の自動誤動作(誤った migration ロールバックなど)の代償は、毎回数分節約する価値より遥かに大きいものです。
プロンプトを陳腐化させない運用の習慣
ここで紹介したプロンプトは、今この瞬間のスナップショットでしかありません。最初から完璧だったわけではなく、何度も書き直してきました。私はプロンプトを小さな専用リポジトリで管理し、CHANGELOG を付けています。これで「先週は動いていたのに」という回帰が起きたとき、すぐ巻き戻せます。
おすすめの習慣は「ポストモーテム時にプロンプトもレビューする」ことです。インシデント後に「要約は適切な first_questions を出したか」「仮説生成は low 仮説を高く評価しすぎなかったか」「再現スクリプトは触ってはいけないものに触っていないか」を自問します。問題があれば、そのインシデントのサニタイズ済みログを使って小さなテストケースを書き、プロンプトの改修案をそれで検証します。テストケースはリポジトリにそのまま残します。
もう一つは、システムプロンプトの末尾にバージョン情報を埋めること。# v3, last edited 2026-04-20 のような一行があるだけで、「あれ、最近何か変えたっけ」を一瞬で確認できます。
最後に、サイト固有の知見を遠慮なく書き込むこと。汎用ベストプラクティスだけでは精度は頭打ちになります。Stripe を多用する自分のアプリの要約プロンプトには、はっきり「InvalidSignature は件数が少なくてもトップ優先度として扱う」と書き込んでいます。売上に直結するからです。ビジネスへのチューニングは、どのモデルアップグレードよりも効果が出ます。
「未来の自分」と荷を分かち合う
最後に少しだけ感傷的な話をさせてください。私がこのパイプラインを組んだ最も深い理由は、「Claude が速いから」でも「トークンが安いから」でもありません。一人での障害対応がもたらす独特の孤独感を和らげるため、というのが一番大きいのです。
あなたは疲れていて、顧客は怒っていて、フィードバックループは自分の独り言だけ。そんな状況で、よく設計された相棒は時間以上のものを返してくれます。要約が JSON で返ってきた瞬間、「少なくとも誰か(あるいは何か)が一緒にこの問題を見てくれた」という証拠が生まれます。仮説プロンプトは「パニックする前に、何が起きうるかリストアップしよう」という小さな儀式になり、再現コードは「直感ではなく計画でキーボードに向かおう」という宣言になります。
ポケベルを一人で持ち歩いているなら、こうしたスキャフォールディングは個別のプロンプトより重要です。睡眠不足の脳がパニックモードに入っても、構造があれば「プロらしい振る舞い」を続けられる。一度作ってしまえば、特定の障害より長く生き残ります。生産性の数字以上に、これがあなたへの最大のプレゼントになるはずです。
次のアクション
長くなりましたが、この記事の内容は丸ごと実装する必要はありません。一番効くのは、まず log_sanitizer.py だけ作って、自分が普段 Claude に貼っているログを通してみることです。それだけで「うわ、こんなにトークンがマスキングされた」という気づきがあり、PII を渡してしまうリスクの肌感覚が変わります。
そこから先は、自分のサービスで実際にアラートが鳴ったタイミングで、ログ要約プロンプトを試してみる。そのときに「もっと早く一次仮説が欲しい」と感じたら、仮説プロンプトを足す。順番に積み上げていくのが、結果的に一番疲れない方法です。
私は今でも深夜のアラートが嫌いですが、Claude が一緒に画面の前にいてくれると、孤独感はだいぶ和らぎます。あなたが次にアラートで叩き起こされたとき、この記事のどこか1つでも役に立てば嬉しいです。
この記事の設計をさらに深めたい方には、SRE 視点の体系的な書籍として 入門 監視 ─ モダンなモニタリングのためのデザインパターン(Mike Julian 著) が、ログを見る視点を「症状」「原因」「ビジネス影響」のレイヤーで整理する考え方を与えてくれます。本記事のサマリープロンプトを設計し直すときの強力な参照軸になります。