◉CLAUDE LABEN
●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/API & SDK
⬡ API & SDK/2026-06-01上級

Crashlyticsのクラッシュを根本原因ごとに束ねる — Claude APIで作るトリアージの設計メモ

Crashlyticsの「Issue」は同じ原因を別物として散らしてしまうことがあります。累計5,000万DLのアプリ運用で溜まったクラッシュを、Claude APIで根本原因ごとに束ね直して優先順位をつける設計を、動くコードと実測値とともに共有します。

Claude API128Crashlytics8クラッシュ解析個人開発130Python22アプリ開発8バッチ処理4

✦ プレミアム記事

アプリが増えるほど、Crashlyticsのダッシュボードは「読むもの」から「眺めるだけのもの」に変わっていきました。

2014年から個人でアプリを作り続けてきて、いまは累計5,000万ダウンロードほどになりました。本数が増え、OSのバージョンも端末も多様になると、Crashlyticsの「Issue(問題)」は数百単位で並びます。やっかいなのは、件数の多さそのものではありません。同じ根本原因が、別々のIssueとして散らばってしまうことでした。

たとえば、ある画像デコード処理の不具合は、呼び出し元のスレッドが違うだけで3つのIssueに分かれていました。逆に、シンボルが解決できていない難読化済みのトレースは、まったく別の原因がひとつのIssueに同居していることもありました。Crashlyticsのグルーピングはスタックトレースの先頭フレームに強く依存するため、こうした「分かれすぎ」と「混ざりすぎ」が同時に起きます。

毎朝この一覧を前に、どれから手をつけるべきかを判断する時間が、いつのまにか開発そのものより長くなっていました。そこでClaude APIを使い、クラッシュを「根本原因」という単位で束ね直し、優先順位を機械的に出す仕組みを組みました。以下では、その設計判断と動くコード、そして運用して分かった実測値を共有します。

なぜ「LLMで全部分類」ではうまくいかないのか

最初に試したのは、クラッシュのスタックトレースをそのままClaudeに渡して「これらをグループ分けして」と頼む素朴なやり方でした。これは二つの理由で破綻します。

ひとつはコストです。1日に数千件のクラッシュイベントが届く規模だと、毎件をLLMに通すのは費用的に現実的ではありません。もうひとつは安定性です。同じトレースでも、入力の並び順やわずかな文言差で、束ね方が日によって揺れてしまいます。クラスタが毎日違う形になると、「昨日対応した原因が今日も上位にいるのか」を追えなくなります。

開発現場で実際に使えるものにするには、決定論的に処理できる部分は決定論的に処理し、LLMは人間でも判断に迷う「境界」だけに使うという割り切りが要ります。私はこの設計を、宮大工だった祖父が「墨付けは機械、刻みは手」と道具を使い分けていた話と重ねて考えるようになりました。揺れてはいけない寸法は治具で固定し、判断が要る部分にだけ手をかける。クラッシュ解析も同じで、揺れてはいけない指紋は決定論で固定し、意味の判断だけをClaudeに委ねます。

そこで採ったのが次の三段構成です。

  1. 正規化と指紋化(決定論)— トレースから可変要素を削り、安定した指紋を作る
  2. 指紋による事前クラスタリング(決定論)— 同一指紋を機械的にまとめる
  3. Claudeによるラベル付けとクラスタ統合(LLM)— 指紋が違っても原因が同じものを束ね、根本原因名と優先度を付ける

スタックトレースを正規化して指紋にする

LLMに渡す前に、まずトレースを「同じ原因なら同じ文字列になる」形へ正規化します。メモリアドレス、行番号、ユーザーIDのような可変要素を取り除き、安定したフレーム列だけを残すのが狙いです。

import re
import hashlib
 
# 可変要素を消すための置換ルール
NOISE_PATTERNS = [
    (re.compile(r"0x[0-9a-fA-F]+"), "0xADDR"),      # メモリアドレス
    (re.compile(r":\d+\)"), ":N)"),                   # 行番号
    (re.compile(r"\b\d{4,}\b"), "NUM"),               # 長い数値ID
    (re.compile(r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"), "UUID"),
]
 
# アプリ自身のフレームだけ残す(OS/SDKのノイズを落とす)
APP_FRAME_HINT = re.compile(r"(MyWallpaperApp|com\.dolice\.)")
 
def normalize_frame(frame: str) -> str:
    for pattern, repl in NOISE_PATTERNS:
        frame = pattern.sub(repl, frame)
    return frame.strip()
 
def fingerprint(stacktrace: str, top_n: int = 5) -> str:
    """上位フレームのうちアプリ由来のものを正規化して指紋を作る"""
    frames = [normalize_frame(f) for f in stacktrace.splitlines() if f.strip()]
    app_frames = [f for f in frames if APP_FRAME_HINT.search(f)]
    # アプリフレームが取れなければ上位フレームで代替
    key_frames = (app_frames or frames)[:top_n]
    digest = hashlib.sha256("\n".join(key_frames).encode()).hexdigest()
    return digest[:16]

ここで効くのが「アプリ由来のフレームを優先して指紋にする」工夫です。UIKit や libsystem のような共通フレームを先頭から拾うと、原因の違うクラッシュが同じ指紋に潰れてしまいます。逆に、自分のアプリのフレームを軸にすると、原因の単位で素直に分かれてくれます。公式ドキュメントには書かれていませんが、私の経験ではこの一手で事前クラスタの精度が体感で大きく変わりました。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦スタックトレースを決定論的に正規化してから指紋化し、LLM呼び出しを「境界」に絞ってコストと安定性を両立させる三段構成
✦Claude APIの構造化出力(tool use)で根本原因ラベル付けとクラスタ統合を行う、実行可能なPython実装一式
✦影響ユーザー数とクラッシュフリー率の差分で優先度を採点する式、Batch APIとプロンプトキャッシュでコストを抑える運用ノウハウ
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

⬡ API & SDK2026-09-17
画像は20枚ずつ送っています — 21枚目から全画像に別の上限がかかると知った日
素材フォルダの62枚を一度に送ったら invalid_request_error で落ちました。容量ではなく枚数が原因です。視覚トークンを28pxのパッチで数え直し、枚数・寸法・ペイロードの3つの上限を同時に見てバッチを組むまでの記録です。
⬡ API & SDK2026-09-06
訳文は自然なのに、実行時に落ちる翻訳がありました
多言語アプリの文言を Claude API で訳したとき、意味は正しいのに書式指定子だけが壊れることがあります。重大度で分けた受け入れ検査と、壊れた行だけを訳し直す修復ループを実装と実測でまとめました。
⬡ API & SDK2026-05-15
壁紙アプリの一括カテゴリ分類を Claude Vision API で自動化した話 — 実運用で見えた精度と限界
個人開発の壁紙アプリで画像のカテゴリ分類をClaude Vision APIに任せた実体験の記録です。SonnetとHaikuのモデル選択、75枚の手動検証で確かめた分類精度、実運用で踏んだ落とし穴、途中で落ちても再開できるバッチ設計、そして実際にかかったコストの感覚まで正直に書きました。