Claude CodeのOpenTelemetryでプラグインの導入と利用を測る
plugin_installed・plugin_loaded・skill_activatedの使い分けと、プラグイン名がthird-partyに潰れる条件、exporter不要のAnalytics APIとの選び方を扱います。
プラグインの利用を測る5つのシグナル
Claude Codeは、プラグインの導入と利用をOpenTelemetry(OTel)のイベントとして自分のバックエンドへ送れます。組織でClaude Codeを管理している人が、プラグインごとの導入数・有効セッション数・スキル起動数・API費用を横断で見るための仕組みです。
プラグインの作者に使用状況が自動で戻ってくることはありません。利用は各自のマシンに記録され、見られるのは組織の管理者か、本人に聞ける同僚だけです。管理者の立場なら、問いごとに見るイベントが決まっています。
| 知りたいこと | 見るもの | 粒度 |
|---|---|---|
| どのプラグインが、どこから入ったか | 見るものclaude_code.plugin_installed | 粒度インストール1回につき1件 |
| 何セッションで有効だったか | 見るものclaude_code.plugin_loaded | 粒度セッション開始時に、有効なプラグイン1つにつき1件 |
| どのスキルが動き、どのプラグインのものか | 見るものclaude_code.skill_activated の plugin.name・marketplace.name | 粒度スキル起動ごと |
| プラグインのフックが何を報告したか | 見るものclaude_code.hook_plugin_metrics | 粒度公式マーケットプレイスのプラグインのフックだけ |
| プラグインがいくら使わせたか | 見るものコストcounterの plugin.name・marketplace.name | 粒度有効なスキルかサブエージェントがプラグイン所属のとき |
Claude Codeを自分で使っているだけの人や、プラグイン作者として端末の外を見たい人は、この仕組みの対象外です。手元の端末で確かめる方法は、記事の後半にまとめています。
先にexporterを管理設定で入れる
イベントはexporterを設定して初めて出ます。全ユーザーに揃えて配るなら、managed settingsの env に書くのが公式の例です。
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector.example.com:4317",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer example-token"
}
}plugin_installed・plugin_loaded・skill_activated はevents(logs)側のシグナルなので、OTEL_LOGS_EXPORTER が要ります。コストcounterはmetrics側なので、費用までプラグイン別に見たいなら OTEL_METRICS_EXPORTER も有効にします。
リポジトリの .claude/settings.json に書いたexporter変数は無視されます。リポジトリ側からテレメトリの宛先を変えられない作りです。設定の置き場は、managed settingsか各開発者のシェルまたは ~/.claude/settings.json になります。
疎通の確認は、メトリクスなら claude_code.session.count、ログだけなら claude_code.user_prompt の到着で行えます。基本のセットアップはClaude CodeのOpenTelemetryで利用量とコストを可視化に手順があります。
plugin_installedとplugin_loadedは別の問いに答える
名前が似ていますが、数えているものが違います。
plugin_installed は、claude plugin install でもインタラクティブな /plugin UIでも、インストールが終わった時点で出ます。属性には次のものがあります。
install.trigger:cliかuimarketplace.is_official: 公式Anthropicマーケットプレイスなら"true"plugin.name・plugin.version・marketplace.name
plugin_loaded はセッションを開始するたび、その時点で有効なプラグイン1つにつき1件ずつ出ます。インストールの履歴ではなく、いま実際に効いている構成の棚卸しです。属性は plugin_installed よりかなり多く、運用判断に使えるものが揃っています。
| 属性 | 値・意味 |
|---|---|
plugin.scope | 値・意味official / community / org / user-local / default-bundle |
enabled_via | 値・意味default-enable / org-policy / admin-install / seed-mount / user-install |
has_hooks・has_mcp | 値・意味フックやMCPサーバーを提供するか |
skill_path_count・command_path_count・agent_path_count | 値・意味宣言しているディレクトリ数 |
plugin_id_hash | 値・意味プラグイン名とマーケットプレイスのハッシュ |
safe_mode | 値・意味--safe-mode 起動なら "true" |
enabled_via を見ると、利用者が自分で入れたプラグイン(user-install)と、組織が必須や自動インストールに設定したもの(admin-install)を切り分けられます。「導入数は多いのに自発的に入れた人が少ない」という偏りは、plugin_installed だけでは見えません。
safe_mode が "true" のセッションでは、plugin_loaded は設定上の在庫だけを報告し、コマンド・スキル・フック・MCPサーバーは実際には読み込まれません。有効セッション数を数えるときは、この値で除外するか分けておく必要があります。
セキュリティ監査の文脈で plugin_installed を使う例は、セキュリティ監査とOTELイベントの対応表にまとまっています。
自社外のプラグイン名はthird-partyに潰れる
最初に引っかかりやすいのが名前の扱いです。公式マーケットプレイスのプラグインは、プラグイン名もマーケットプレイス名もそのままバックエンドに届きます。それ以外は、組織が運営する社内マーケットプレイスのプラグインも含めて、既定では名前が伏せられるか省かれます。
OTEL_LOG_TOOL_DETAILS=1 を、テレメトリを出す端末に設定すると実名が出ます。イベントごとの違いは次のとおりです。
| イベント | 既定 | OTEL_LOG_TOOL_DETAILS=1 |
|---|---|---|
plugin_loaded | 既定plugin.name・marketplace.name が文字列 third-party | OTEL_LOG_TOOL_DETAILS=1実名 |
plugin_installed・skill_activated | 既定plugin.name・marketplace.name が省かれる。skill_activated の skill.name は custom_skill | OTEL_LOG_TOOL_DETAILS=1実名 |
| コストcounter | 既定plugin.name が third-party、marketplace.name は無し | OTEL_LOG_TOOL_DETAILS=1plugin.name は実名。marketplace.name は無いまま |
名前を伏せたままでも、plugin_loaded の plugin_id_hash は既定で付きます。実名は分からなくても、フリート全体で何種類のサードパーティ製プラグインが動いているかは数えられます。
{
"env": {
"OTEL_LOG_TOOL_DETAILS": "1"
}
}これは上の env ブロックに足す1行です。ただし、この変数はプラグイン名だけを開けるものではありません。Bashのコマンド、MCPサーバーとツールの名前、スキル名、ツールの入力引数まで各イベントとトレースに入ります。セッションそのものと同じ程度に機微な内容が含まれうるため、コレクターがその内容を持てる承認済みの環境で有効にします。
コストの帰属には版の注意もあります。v2.1.273より前は、OTEL_LOG_TOOL_DETAILS=1 を設定してもコスト・トークンのcounterと api_request などのイベントは伏せた値のままでした。古いクライアントが混ざるフリートでは、実名で出る端末と出ない端末が併存します。
skill_activatedとコストで「使われているか」を見る
plugin_loaded が多くても、プラグインが使われている証拠にはなりません。有効なだけで、スキルが一度も呼ばれていない可能性があるためです。使われたかどうかは skill_activated で見ます。
スキルがプラグイン所属なら、公式マーケットプレイスのものか OTEL_LOG_TOOL_DETAILS=1 のとき、plugin.name と marketplace.name が付きます。あわせて次の属性で起動の経路が分かります。
invocation_trigger:user-slash(ユーザーが/で呼んだ)、claude-proactive(Claudeが自分で呼んだ)、nested-skillskill.source:bundled・userSettings・projectSettings・pluginなど
plugin_loaded の件数に対する skill_activated の件数が極端に低いプラグインは、入れただけで使われていない候補になります。逆にコストの面では、claude_code.cost.usage に plugin.name が付くので、プラグイン別の費用の傾きが見えます。この属性は、有効なスキルかサブエージェントがプラグイン所属のリクエストだけに付きます。所属が無いリクエストでは属性自体が付きません。
コスト指標は概算です。請求の正確な値は、利用しているAPI提供元(Claude Console、Amazon Bedrock、Google Cloudなど)のデータで確かめます。
スキルの棚卸しを端末単位でやりたいときは、skill-doctorで未使用スキルを洗い出すのが近道です。
hook_plugin_metricsは公式プラグインのフックだけ
claude_code.hook_plugin_metrics は、フックが呼び出しごとの指標を出したときのイベントです。出せるのは公式Anthropicマーケットプレイスからインストールしたプラグインのフックに限られます。サードパーティのマーケットプレイスのプラグインや、ユーザーが設定したフックは、このイベントを出しません。
属性は plugin_id(<name>@<marketplace> 形式)、hook_event に加え、プラグインが出した指標のキーが最大20個です。キー名は ^[a-z][a-z0-9_]{0,39}$ に合う必要があり、値は真偽値か数値です。
つまり、自社製プラグインのフックの挙動をこのイベントで測ることはできません。自社プラグインの利用を見るには、plugin_loaded と skill_activated を主軸にし、フックについては hook_execution_* 系のイベントなど別の手段を考えることになります。
exporterを置かない選択肢: Analytics API
OTelはコレクターとバックエンドの用意が前提です。そこまで手を入れたくない組織向けに、EnterpriseプランではAnalytics APIでも同じ問いに答えられます。
GET /v1/organizations/analytics/plugins は、プラグインごと・日ごとのインストール数と呼び出し数を、Claude CodeとCoworkをまたいで返します。ユーザー、RBACグループ、プロダクトでグループ化できます。認証には read:analytics スコープ付きのAPIキーが要り、作成するのはPrimary Ownerです。
OTelとの違いを並べると、選び分けの軸が見えます。
| 観点 | OpenTelemetry | Analytics API |
|---|---|---|
| 前提 | OpenTelemetryexporterとバックエンド | Analytics APIEnterpriseプランと read:analytics キー |
| データの置き場 | OpenTelemetry自社のバックエンド | Analytics APIAnthropic側の記録を都度取得 |
| 対象 | OpenTelemetryClaude Codeのイベント | Analytics APIClaude CodeとCowork |
| 粒度 | OpenTelemetry1イベントごと(セッション・スキル・コスト) | Analytics APIプラグイン別・日別の件数 |
| 名前の扱い | OpenTelemetry既定でthird-partyに潰れる。実名化は OTEL_LOG_TOOL_DETAILS | Analytics API名前の無い活動は third-party の集計行にまとまる |
セッション単位の相関や費用の内訳まで掘りたいならOTel、まず導入数と呼び出し数の推移だけ欲しいならAPI、という分担です。両方を併用してもかまいません。
端末側で見る: 本人が確かめる4つの場所
管理者でなく、本人が自分の使用状況を確かめるなら、Claude Code自身が4か所で見せます。すべて、利用者が自分のマシンのセッションで実行するコマンドです。
/pluginのInstalledタブ。14日以上かつ10セッション以上使われていないプラグインはNot used recentlyの見出しに移り、詳細にLast used:の行が出ます/skill-doctor。一度も起動されていないスキルを、プラグイン由来のものも含めて洗い出します/doctor。ユーザーがインストールしたスキル、MCPサーバー、プラグインのうち使われていないものを、無効化の候補として挙げます/usage。Pro・Max・Team・Enterpriseプランで、直近の利用をスキル、サブエージェント、プラグイン、MCPサーバーの割合で示します
Not used recentlyは、--plugin-dir やskillsディレクトリから読み込んだプラグイン、managed settingsで有効化したプラグイン、シードディレクトリのプラグインには出ません。テーマ・出力スタイル・モニター・ワークフローを含むプラグインも対象外です。これらは呼び出しの記録が付かないまま使われるためです。組織が strictKnownMarketplaces を設定している場合は、見出しも Last used: の行も表示されません。
Anthropicのディレクトリに載せたプラグインの利用状況は、claude.com側の公開後のドキュメントが案内先です。提出の流れはClaudeプラグイン提出ポータルの記事にあります。
まとめ: どの層で何を測るか
測る対象を3層に分けると迷いません。導入は plugin_installed、有効な構成は plugin_loaded、実際に使われたかは skill_activated とコストcounterです。
実運用で先に決めたいのは、名前をどこまで開けるかです。実名が必要なら OTEL_LOG_TOOL_DETAILS=1 の副作用(コマンドやツール入力まで流れる)を、コレクターの承認範囲と突き合わせます。名前が不要なら plugin_id_hash で数だけ追う手もあります。
exporterを用意できない組織は、EnterpriseプランのAnalytics APIから入るのが最短です。プラグインの配布側の管理はPlugins APIが別の入口になります。