Claude Code 效率分析指標工具開發實作:Session 評分與效率報告生成
下面我們來開發使用 claude code 的效率指標圖表功能
效率指標計算器
目標:計算每個 session 的效率分數,找出你的高效與低效 session
新增效率指標模組
新增 lib/efficiency.mjs:
import { extractToolCalls } from './analytics.mjs';
/**
* 計算 session 效率指標
*/
export function calcEfficiencyMetrics(messages) {
const turns = messages.filter(m => m.type === 'assistant').length;
const userMsgs = messages.filter(m => m.type === 'user').length;
// 工具呼叫統計
const allToolCalls = extractToolCalls(messages);
const toolCalls = allToolCalls.length;
// 工具錯誤數
let toolErrors = 0;
for (const msg of messages) {
if (msg.type !== 'user') continue;
for (const c of msg.message?.content ?? []) {
if (c.type === 'tool_result' && c.is_error) toolErrors++;
}
}
// 重複修改的檔案數
const editCounts = {};
for (const call of allToolCalls) {
if (['Edit', 'Write', 'MultiEdit'].includes(call.name)) {
const fp = call.input?.file_path ?? 'unknown';
editCounts[fp] = (editCounts[fp] ?? 0) + 1;
}
}
const repeatedEdits = Object.values(editCounts).filter(n => n >= 3).length;
// Token 統計
let totalTokens = 0;
for (const msg of messages) {
if (msg.type !== 'assistant') continue;
const u = msg.message?.usage;
if (u) totalTokens += (u.input_tokens ?? 0) + (u.output_tokens ?? 0);
}
const burnRate = turns > 0 ? totalTokens / turns : 0;
const errorRate = toolCalls > 0 ? toolErrors / toolCalls : 0;
// 效率分數
let score = 100;
score -= Math.max(0, (turns - 15) * 2);
score -= Math.max(0, (burnRate - 5000) / 1000);
score -= errorRate * 200;
score -= repeatedEdits * 10;
score = Math.max(0, Math.min(100, score));
return {
turns,
user_msgs: userMsgs,
tool_calls: toolCalls,
tool_errors: toolErrors,
error_rate: errorRate,
repeated_edits: repeatedEdits,
total_tokens: totalTokens,
burn_rate: burnRate,
efficiency_score: score,
};
}
/**
* 將效率分數轉為等級
*/
export function scoreGrade(score) {
if (score >= 80) return { grade: 'A', label: '高效', emoji: '$' };
if (score >= 60) return { grade: 'B', label: '正常', emoji: 'O' };
if (score >= 40) return { grade: 'C', label: '偏低', emoji: '!' };
return { grade: 'D', label: '高摩擦', emoji: 'X' };
}
新增效率報告腳本
新增 efficiency-report.mjs:
import { scanProjects, scanProjectSessions } from './lib/scanner.mjs';
import { parseJsonl } from './lib/parser.mjs';
import { calcEfficiencyMetrics, scoreGrade } from './lib/efficiency.mjs';
const DAYS = parseInt(process.argv[2] ?? '30', 10);
const cutoff = new Date();
cutoff.setDate(cutoff.getDate() - DAYS);
const sessions = [];
for (const proj of scanProjects()) {
for (const session of scanProjectSessions(proj)) {
if (new Date(session.first_message_time) < cutoff) continue;
const messages = parseJsonl(session.file_path);
const metrics = calcEfficiencyMetrics(messages);
sessions.push({ ...session, ...metrics });
}
}
// 按效率分數排序
sessions.sort((a, b) => b.efficiency_score - a.efficiency_score);
console.log(`\n Session 效率分析(過去 ${DAYS} 天,共 ${sessions.length} 個)\n`);
// 分布統計
const grades = { A: 0, B: 0, C: 0, D: 0 };
for (const s of sessions) {
grades[scoreGrade(s.efficiency_score).grade]++;
}
console.log('等級分布:');
console.log(` A(高效):${grades.A} 個`);
console.log(` B(正常):${grades.B} 個`);
console.log(` ️ C(偏低):${grades.C} 個`);
console.log(` D(高摩擦):${grades.D} 個`);
// TOP 5 高效
console.log('\n\n 效率最高的 Sessions:\n');
for (const s of sessions.slice(0, 5)) {
const { emoji, label } = scoreGrade(s.efficiency_score);
const date = new Date(s.first_message_time).toLocaleDateString();
const summary = (s.summary ?? '(無摘要)').slice(0, 50);
console.log(` ${emoji} [${s.efficiency_score.toFixed(0)}分] [${date}] ${s.turns}輪 ${s.total_tokens.toLocaleString()}tokens`);
console.log(` ${summary}`);
}
// TOP 5 低效
console.log('\n\n 需要改善的 Sessions:\n');
for (const s of sessions.slice(-5).reverse()) {
const { emoji, label } = scoreGrade(s.efficiency_score);
const date = new Date(s.first_message_time).toLocaleDateString();
const summary = (s.summary ?? '(無摘要)').slice(0, 50);
console.log(` ${emoji} [${s.efficiency_score.toFixed(0)}分] [${date}] ${s.turns}輪 ${s.tool_errors}錯誤 ${s.repeated_edits}重複修改`);
console.log(` ${summary}`);
}
// 平均指標
const avg = sessions.reduce((acc, s) => ({
score: acc.score + s.efficiency_score,
turns: acc.turns + s.turns,
burnRate: acc.burnRate + s.burn_rate,
errorRate: acc.errorRate + s.error_rate,
}), { score: 0, turns: 0, burnRate: 0, errorRate: 0 });
const n = sessions.length || 1;
console.log('\n\n 平均指標:');
console.log(` 效率分數:${(avg.score / n).toFixed(1)} 分`);
console.log(` 平均輪數:${(avg.turns / n).toFixed(1)} 輪`);
console.log(` 平均燃耗率:${(avg.burnRate / n).toFixed(0)} tokens/輪`);
console.log(` 平均工具錯誤率:${(avg.errorRate / n * 100).toFixed(1)}%`);
接著來執行
node efficiency-report.mjs # 過去 30 天
node efficiency-report.mjs 7 # 過去 7 天
D:\Git\mathTalk\class\Claude-Code-Analytics\src>node monthly-report.mjs
生成 30 天報告中...
月報已生成:ce-report-2026-06-12.md
Sessions:130 個
總費用:$12460.32 USD
平均效率分:32.9
最後的報告如下:
一、整體概覽
| 指標 | 數值 |
|---|---|
| 總 Session 數 | 130 |
| 總 Token 用量 | 33,902,068 |
| 估算總費用 | $12460.32 USD |
| 平均每 Session 費用 | $95.8486 USD |
| 估算月費用 | $12460.32 USD |
| 平均效率分數 | 32.9 / 100 |
二、效率分布
| 等級 | 數量 | 比例 |
|---|---|---|
| A(高效,80+) | 31 | 24% |
| B(正常,60-79) | 10 | 8% |
| ️ C(偏低,40-59) | 7 | 5% |
| D(高摩擦,<40) | 82 | 63% |