Claude CodeにDash0プラグインを入れてセッションをトレースする
Dash0プラグインはClaude Codeのフックからプロンプト・ツール呼び出し・サブエージェント・トークン使用量をOTelトレースで送ります。導入、設定、プライバシー既定値、組織配布まで。
Dash0プラグインは、Claude Codeのフックで拾ったセッションの動きをOpenTelemetryのトレースとしてDash0へ送るプラグインです。1回のプロンプトが1本のトレースになり、その下にツール呼び出しやサブエージェントがスパンとして並びます。
どのターンで何トークン使ったか、どこで詰まったか、MCPサーバーのどれが呼ばれたかを、普段のアプリのトレースと同じ画面で追えます。ここでは導入から接続確認、設定の置き場所、組織への配布、つまずきやすい点までを順に説明します。
何がトレースとして送られるか
プラグインの実体は、フックのたびに起動する短命のGoバイナリです。常駐するデーモンではありません。セッションの状態はディスクに持ち、OTLP JSONをHTTPで送ります。
Claude Code用のhooks.jsonには、SessionStartやUserPromptSubmit、PreToolUse、PostToolUse、SubagentStart、PreCompactなど24種類のイベントが登録されています。フックの仕組みそのものはClaude Code Hooks完全ガイドにまとめています。
スパンは3種類です。
| スパン名 | 何を表すか |
|---|---|
chat <モデル名> | 何を表すか1回のプロンプトに対するターン全体 |
invoke_agent <エージェント種別> | 何を表すかサブエージェントの実行 |
execute_tool <ツール名> | 何を表すかツール1回の呼び出し |
親子関係はこうなります。ターンの開始(プロンプト送信)でトレースIDが採番され、ツールとサブエージェントのスパンはそのターンの chat スパンにぶら下がります。サブエージェントの中で呼ばれたツールは、そのサブエージェントを起動した execute_tool Agent スパンの下に入るため、深さがつぶれません。
スパンの種別は常に Internal です。ステータスは通常 Unset で、StopFailure や PostToolUseFailure のときだけ Error になり、exception.message が付きます。失敗したツール呼び出しだけを検索したいときは、このステータスで絞れます。
スパンに載る主な属性
トークン
gen_ai.usage.input_tokensとoutput_tokensに加え、キャッシュ読み取りとキャッシュ書き込み(5分・1時間の別つき)、推論トークンも載ります。ツール
gen_ai.tool.nameにツール名が入ります。MCPツールはmcp__<サーバー>__の接頭辞が外れ、サーバー名はdash0.gen_ai.tool.mcp_serverに分かれます。Bashはgitやnpmといったコマンドの系統がdash0.gen_ai.tool.bash.command_familyに入ります。コードと成果物
Edit・Write系は追加行数・削除行数、PRやIssue、コミットのURL・SHAが属性になります。
リポジトリと人
リポジトリURL、ブランチ、コミットSHA、
user.nameが付きます。チーム名を設定するとdash0.team.nameも付きます。
セッションIDは gen_ai.conversation.id に入るので、複数ターンにまたがるセッション単位の集計もできます。
入れる前に決める3つの設定
導入前に、送る範囲を決めておくと後で困りません。READMEのプライバシー既定値は次のとおりです。
| 設定 | 既定 | 効果 |
|---|---|---|
OMIT_IO | 既定true | 効果プロンプト本文、応答、ツールの入出力をスパンから外す |
OMIT_USER_INFO | 既定false | 効果true にすると user.name はSHA-256ハッシュ、user.email は省略、作業ディレクトリは伏せる |
OMIT_IDENTITY_FALLBACK | 既定false | 効果true にすると、gitのユーザー名が無いときにOSアカウント名で代用しない |
OMIT_IO が true のままだと、プロンプトの中身は見えません。見えるのはツール名、トークン数、所要時間、モデル名、セッションの構造、エラーの有無、リポジトリとブランチです。これらは設定にかかわらず常に収集されます。
つまり既定では「何を頼んだか」ではなく「何がどれだけ起きたか」の観測になります。プロンプトの中身まで残したい場合は OMIT_IO を false にしますが、プロンプトにコードや社内情報が含まれる環境では、送信先の保持期間とアクセス権を先に確かめてください。Claude Code標準のOTel出力でも同じ判断が要ります。詳しくはClaudeのOpenTelemetryでプロンプトと応答を送るかで扱っています。
ユーザー名は、gitの user.name が無ければOSのアカウント名(表示名、なければユーザー名)で補われます。どちらから取ったかは dash0.gen_ai.user.identity.source が git か os で示します。CIや root、runner のような共有アカウントではこの補完は行われず、名前なしで報告されます。
インストールから接続確認まで
必要なのはClaude Code CLIと、macOS・Linux・Windowsのいずれか(amd64またはarm64)です。macOSとLinuxでは bash、curl か wget、sha256sum か shasum が要ります。初回起動時にフック用のバイナリをGitHubから取得し、チェックサムを検証してから実行するためです。Windowsでは、フックがGit Bash経由で動くのでGit for Windowsが必要です。
導入の流れ
- 1
プラグインを入れる
公式マーケットプレイスからの導入が推奨です。
- 2
認証トークンとOTLPエンドポイントを用意する
Dash0の設定画面でingest専用のトークンを作り、OTLP via HTTPのエンドポイントURLを控えます。
- 3
プラグインに値を設定する
/pluginからdash0のConfigureを開くか、設定ファイルに書きます。 - 4
リロードして接続を確かめる
/reload-pluginsか再起動のあと、セッション開始時のメッセージを見ます。
インストールは1行です。
/plugin install dash0@claude-plugins-officialDash0側のマーケットプレイスから入れる経路もあります。この場合のプラグイン名は dash0-agent-plugin になります。
/plugin marketplace add dash0hq/claude-marketplace
/plugin install dash0-agent-plugin@dash0公式マーケットプレイスでの登録名は dash0、Dash0のマーケットプレイスでは dash0-agent-plugin です。中身は同じプラグインなので、両方を有効にするとフックが二重に走り、スパンが2回送られます。どちらか一方だけにしてください。
トークンは、Auth Tokens設定ページで作ります。権限は送信先のデータセットへの書き込み(ingest)だけに絞るのが、READMEの推奨です。万一漏れても、書き込みはできても読み出しはできない状態にできます。
設定後に新しいセッションを開くと、次のメッセージが出ます(READMEに載っている表示)。
dash0: connected (v0.1.22)資格情報が無い場合は dash0: telemetry is not active となり、URLは設定済みで接続に失敗した場合は dash0: connectivity check failed と出ます。後者は認証トークンの誤りが典型です。
接続できたら、Claudeにまず1つ依頼を出してから、Dash0でその service.name を探します。サービス名の既定は claude-code で、AGENT_NAME で変えられます。セッションのURLを手元で開きたいときは、プラグインのコマンド /open-session が現在のセッションの詳細URLを表示して開きます。
設定の置き場所と優先順位
設定の書き場所は複数あり、優先順位が決まっています。同じ値が複数にあるときは上が勝ちます。
- 管理設定(managed settings)の
pluginConfigs - ユーザー設定
~/.claude/settings.jsonのpluginConfigs(/pluginのConfigureが書く先) - プロジェクトの
.claude/dash0-agent-plugin.local.md - ユーザーの
~/.claude/dash0-agent-plugin.local.md DASH0_*環境変数
ユーザー設定の書き方は次のとおりです。キーは、実際にインストールした名前と一致させます。
{
"pluginConfigs": {
"dash0@claude-plugins-official": {
"options": {
"OTLP_URL": "https://ingress.<region>.aws.dash0.com",
"DATASET": "default",
"TEAM_NAME": "your-team"
}
}
}
}認証トークンをここに書くと平文で残ります。/plugin のConfigureから入れればOSのキーチェーンに保存されるので、トークンはそちらで入れ、上の例のように AUTH_TOKEN は書かない形がおすすめです。
設定ファイル方式なら、~/.claude/dash0-agent-plugin.local.md にフロントマターで書きます。/dash0-configure スキルを呼べば、対話で同じファイルを作ってくれます。
---
otlp_url: "https://ingress.<region>.aws.dash0.com"
dataset: "default"
team_name: "your-team"
---環境変数は DASH0_OTLP_URL、DASH0_DATASET、DASH0_TEAM_NAME などが使えます。ただし認証トークンだけは DASH0_AUTH_TOKEN という環境変数を読みません。ツールが起動するシェルの環境に漏れるのを避けるためです。
組織全体に配る
Team・Enterpriseプランでは、管理者が全員に配れます。手順は2段です。
まず、claude.aiの組織プラグイン管理で、Dash0を「Required」または「Installed by default」にします。これで各メンバーのマシンにプラグインが取得されます。管理設定は有効化と設定を担うだけで、取得はしません。ここを飛ばすと、enabledPlugins に名前があっても実体が無いので、何も送られません。
次に、管理設定に次のJSONを入れます。
{
"extraKnownMarketplaces": {
"dash0": {
"source": { "source": "github", "repo": "dash0hq/claude-marketplace" },
"autoUpdate": true
}
},
"enabledPlugins": { "dash0-agent-plugin@dash0": true },
"pluginConfigs": {
"dash0-agent-plugin@dash0": {
"options": {
"OTLP_URL": "https://ingress.<region>.aws.dash0.com",
"AUTH_TOKEN": "auth_...",
"DATASET": "default"
}
}
}
}管理設定の AUTH_TOKEN は各マシンの ~/.claude/remote-settings.json に平文で残ります。READMEは、ingest専用かつ1データセット限定のトークンを使い、ローテーションは管理設定の値を変えて一括で行う運用を挙げています。平文を許さない方針なら、macOSではキーチェーンのサービス名を AUTH_TOKEN_KEYCHAIN_SERVICE で指す方法と、各自が /plugin のConfigureで入れる方法があります。
チーム別の集計をしたい場合、TEAM_NAME は管理設定に入れないでください。管理設定の値は上書きできないため、全員が同じチームとして記録されます。各自が DASH0_TEAM_NAME 環境変数か ~/.claude/dash0-agent-plugin.local.md の team_name で設定します。
配布後の確認は、/status のSetting sourcesに Enterprise managed settings が出ること、claude plugin list にDash0が1つだけ enabled・Scope: managed で出ること、セッションのバナーが dash0: connected になることです。
各マシンにはGitHubとDash0のOTLP受信口への、HTTPSでの外向き通信が必要です。コンテナイメージでは CLAUDE_CODE_PLUGIN_SEED_DIR でマーケットプレイスとプラグインのキャッシュを事前に焼いておけば、実行時のダウンロードが要りません。複数プラグインの読み込みについてはCLAUDE_CODE_PLUGIN_DIRSの記事が関連します。
トレースで何が分かるか
導入したら、まず次の見方を試すと違いが分かります。
- ターンごとのトークンとモデル:
chatスパンのgen_ai.usage.*を、モデル名とgen_ai.request.reasoning.level(low〜xhigh)で分けると、思考の深さが費用にどう効いたか追えます - 詰まった箇所: ステータスが
Errorのスパンを絞り、前後のツール呼び出しを時系列で眺めると、同じツールの失敗が繰り返されている箇所が見つかります - MCPの使われ方:
dash0.gen_ai.tool.mcp_serverで集計すると、どのMCPサーバーがどれだけ呼ばれているかが出ます - Bashの内訳:
command_familyでgit、npmなどの比率を出せます - スキル: スキルの呼び出しは
dash0.gen_ai.tool.skill.nameに、プラグイン名つきの形で載ります
セッションの請求の形は dash0.gen_ai.billing_mode に入り、subscription・api・metered_external・unknown のいずれかです。サブスクリプションとAPI課金が混在するチームで、金額の見積もりを分けたいときの手がかりになります。
Claude Code標準のOTel出力とどう分けるか
Claude Code自身にもOpenTelemetryの出力があります。メトリクスとログは CLAUDE_CODE_ENABLE_TELEMETRY=1 と OTEL_EXPORTER_OTLP_ENDPOINT で有効にします。トレースはベータ扱いで、CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1 も要り、OTEL_TRACES_EXPORTER で出力先を選びます。標準側の見方はプラグインの導入と利用をOpenTelemetryで測る記事で取り上げています。
違いは出し手です。標準出力はClaude Code本体が発する信号で、Dash0プラグインはフックで拾った情報とセッションの記録(トランスクリプト)から、プラグインのバイナリがスパンを組み立てて送ります。そのためトークン数はトランスクリプトから復元した値になります。
数字が合わないと感じたときは、/audit-usage が使えます。ローカルのトランスクリプトからセッションのモデル別トークン数と、あるべきスパン数を再構成し、/usage やDash0上のスパンと突き合わせられます。欠けたテレメトリがあれば「差」として見えます。
両者を併用する場合は、同じバックエンドに送るとメトリクスやスパンの意味が重なるので、データセットかサービス名で分けておくと混ざりません。マーケットプレイスの説明では、送信先はDash0以外のOpenTelemetry互換バックエンドでもよいとされています。ただしREADMEの設定項目はDash0のURLと認証を前提に書かれているため、他のバックエンドへ送る場合の設定は、事前に手元で試してください。
つまずきやすい点
落とし穴
プロジェクトの settings.json に pluginConfigs を書いても無視される
v2.1.207以降、pluginConfigs を読むのはユーザー設定、--settings フラグ、管理設定の3か所だけです。リポジトリの .claude/settings.json や settings.local.json に書いた値は、警告なしに無視されます。プラグインは読み込まれ設定済みに見えますが、何も送りません。リポジトリにコミットできるのは enabledPlugins までです。トークンやURLは各自のユーザー設定に入れてもらいます。
落とし穴
プロジェクトとユーザーの .local.md は混ざらない
プロジェクトに .claude/dash0-agent-plugin.local.md があると、ユーザー側のファイルは丸ごと無視されます。プロジェクト側に team_name が無ければ、ユーザー側のチーム名も消えます。enabled: false はプロジェクト単位でプラグインを止める書き方にもなるので、消す前に中身を見てください。
落とし穴
worktreeや複数クローンで2つ目のチェックアウトに読み込まれない
プロジェクトスコープのインストールはリポジトリの絶対パスに紐づきます。gitのworktreeや複数のクローンを使うと、2つ目の場所でプラグインが読み込まれません。ユーザースコープで入れ直します。
claude plugin install dash0@claude-plugins-official --scope userCIなどSSH鍵が無い環境では、プラグインの取得がSSH経由で失敗します。次のようにHTTPSへ切り替えてから入れます。
git config --global url."https://github.com/".insteadOf "git@github.com:"
claude plugin install dash0@claude-plugins-official --scope userスパンが届かないときは、セッション開始時の dash0: で始まるメッセージを手がかりにします。メッセージが何も出ないなら、/reload-plugins か再起動です。フックが毎回404で失敗する場合は、非対応のOS・CPUでバイナリを取りに行っています。uname -s -m で、Darwin・Linux・Windows(Git Bash)と x86_64・arm64・aarch64 のいずれかか確かめます。
フックが送る中身を見たいときは、デバッグモードが使えます。
DASH0_DEBUG=true DASH0_DEBUG_FILE=/tmp/dash0-debug.log claudeログには [dash0:trace] と [dash0:log] の接頭辞が付くので、grepで切り分けられます。ファイルにはプロンプトが入る可能性があるため、共有する前に中身を見ておいてください。
導入判断のめやす
トークンの内訳やMCPの使われ方をチームで追いたいなら、Dash0を既に使っている環境がいちばん早く価値が出ます。トレース画面にアプリ側のスパンと並べて見られるからです。OMIT_IO を true のままにすれば、プロンプトの本文を外に出さずに運用できます。
一方、Claude Code標準のOTel出力で足りる範囲(使用量のメトリクスやイベントログ)なら、プラグインを足す理由は薄くなります。ターン単位のトレース構造とサブエージェントの親子関係が欲しいかどうかが分かれ目です。