Add SDK usage tracking to JSONL logs

Features:
- New UsageLogger utility that writes usage metrics to daily JSONL files
- Captures token counts, costs, timing, and cache metrics from SDK result messages
- Usage logs stored in ~/.claude-mem/usage-logs/ (one file per day)
- Added analyze-usage.js script for analyzing usage patterns

Usage data captured:
- Token counts (input, output, cache creation, cache read)
- Total cost in USD per API call
- Duration metrics (total and API time)
- Number of turns per session
- Session and project attribution

Analysis script features:
- Aggregates totals by project and model
- Shows cache hit rates and savings
- Displays cost breakdowns and averages
- npm scripts: usage:analyze and usage:today

Files:
- src/utils/usage-logger.ts (new)
- src/services/worker-service.ts (modified - captures SDK result messages)
- scripts/analyze-usage.js (new)
- package.json (added usage:* npm scripts)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2025-11-02 21:53:42 -05:00
parent 9215c7e1f5
commit f20bb5bced
7 changed files with 327 additions and 29 deletions
+61
View File
@@ -0,0 +1,61 @@
import { appendFileSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';
/**
* Usage data structure from Claude Agent SDK result messages
*/
export interface UsageData {
timestamp: string;
sessionDbId: number;
claudeSessionId: string;
project: string;
promptNumber: number;
model: string;
sessionId: string; // SDK session ID
uuid: string; // SDK message UUID
durationMs: number;
durationApiMs: number;
numTurns: number;
totalCostUsd: number;
usage: {
inputTokens: number;
outputTokens: number;
cacheCreationInputTokens: number;
cacheReadInputTokens: number;
};
}
/**
* Logger for capturing usage metrics to JSONL files
*/
export class UsageLogger {
private logDir: string;
private logFile: string;
constructor() {
this.logDir = join(homedir(), '.claude-mem', 'usage-logs');
// Create a daily log file
const date = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
this.logFile = join(this.logDir, `usage-${date}.jsonl`);
}
/**
* Log usage data from SDK result message
*/
logUsage(data: UsageData): void {
try {
const line = JSON.stringify(data) + '\n';
appendFileSync(this.logFile, line, 'utf-8');
} catch (error) {
console.error('Failed to log usage data:', error);
}
}
/**
* Get the current log file path
*/
getLogFilePath(): string {
return this.logFile;
}
}