Token Usage Analytics and Monitoring for Claude Code
Overview
Effective token usage monitoring is crucial for managing costs and optimizing performance in Claude Code applications. This guide provides implementation patterns for tracking, analyzing, and optimizing token consumption across single and multi-agent systems.
Token Economics (2025)
Token-to-Cost Mapping
const TOKEN_COSTS = {
"claude-4-opus": {
input: 15.00, // per million tokens
output: 75.00, // per million tokens
cacheWrite: 18.75, // 25% premium
cacheRead: 1.50 // 90% discount
},
"claude-4-sonnet": {
input: 3.00,
output: 15.00,
cacheWrite: 3.75,
cacheRead: 0.30
},
"claude-3-5-haiku": {
input: 0.80,
output: 4.00,
cacheWrite: 1.00,
cacheRead: 0.08
}
};Implementation Patterns
1. Basic Token Tracking System
import json
import sqlite3
from datetime import datetime
from typing import Dict, List, Optional
from dataclasses import dataclass, asdict
import anthropic
@dataclass
class TokenUsage:
"""Token usage record."""
timestamp: str
model: str
request_id: str
input_tokens: int
output_tokens: int
cache_creation_tokens: int
cache_read_tokens: int
total_cost: float
latency_ms: int
user_id: Optional[str] = None
session_id: Optional[str] = None
prompt_category: Optional[str] = None
class TokenAnalytics:
"""Comprehensive token usage tracking and analytics."""
def __init__(self, db_path: str = "token_usage.db"):
self.db_path = db_path
self.client = None
self._init_db()
def _init_db(self):
"""Initialize SQLite database for token tracking."""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS token_usage (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
model TEXT NOT NULL,
request_id TEXT NOT NULL,
input_tokens INTEGER NOT NULL,
output_tokens INTEGER NOT NULL,
cache_creation_tokens INTEGER DEFAULT 0,
cache_read_tokens INTEGER DEFAULT 0,
total_cost REAL NOT NULL,
latency_ms INTEGER NOT NULL,
user_id TEXT,
session_id TEXT,
prompt_category TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
# Create indexes for common queries
cursor.execute("CREATE INDEX IF NOT EXISTS idx_timestamp ON token_usage(timestamp)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_user_id ON token_usage(user_id)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_model ON token_usage(model)")
conn.commit()
conn.close()
def track_usage(
self,
response: anthropic.types.Message,
latency_ms: int,
user_id: Optional[str] = None,
session_id: Optional[str] = None,
prompt_category: Optional[str] = None
):
"""Track token usage from API response."""
usage = response.usage
model = response.model
# Calculate costs
model_costs = self._get_model_costs(model)
input_cost = (usage.input_tokens / 1_000_000) * model_costs["input"]
output_cost = (usage.output_tokens / 1_000_000) * model_costs["output"]
cache_creation_cost = 0
cache_read_cost = 0
if hasattr(usage, 'cache_creation_input_tokens'):
cache_creation_cost = (usage.cache_creation_input_tokens / 1_000_000) * model_costs["cacheWrite"]
if hasattr(usage, 'cache_read_input_tokens'):
cache_read_cost = (usage.cache_read_input_tokens / 1_000_000) * model_costs["cacheRead"]
total_cost = input_cost + output_cost + cache_creation_cost + cache_read_cost
# Create usage record
usage_record = TokenUsage(
timestamp=datetime.utcnow().isoformat(),
model=model,
request_id=response.id,
input_tokens=usage.input_tokens,
output_tokens=usage.output_tokens,
cache_creation_tokens=getattr(usage, 'cache_creation_input_tokens', 0),
cache_read_tokens=getattr(usage, 'cache_read_input_tokens', 0),
total_cost=total_cost,
latency_ms=latency_ms,
user_id=user_id,
session_id=session_id,
prompt_category=prompt_category
)
self._save_usage(usage_record)
return usage_record
def _save_usage(self, usage: TokenUsage):
"""Save usage record to database."""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute("""
INSERT INTO token_usage (
timestamp, model, request_id, input_tokens, output_tokens,
cache_creation_tokens, cache_read_tokens, total_cost, latency_ms,
user_id, session_id, prompt_category
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
usage.timestamp, usage.model, usage.request_id,
usage.input_tokens, usage.output_tokens,
usage.cache_creation_tokens, usage.cache_read_tokens,
usage.total_cost, usage.latency_ms,
usage.user_id, usage.session_id, usage.prompt_category
))
conn.commit()
conn.close()
def _get_model_costs(self, model: str) -> Dict[str, float]:
"""Get cost structure for a model."""
# Simplified model mapping
if "opus" in model:
return {"input": 15.00, "output": 75.00, "cacheWrite": 18.75, "cacheRead": 1.50}
elif "sonnet" in model:
return {"input": 3.00, "output": 15.00, "cacheWrite": 3.75, "cacheRead": 0.30}
elif "haiku" in model:
return {"input": 0.80, "output": 4.00, "cacheWrite": 1.00, "cacheRead": 0.08}
else:
return {"input": 3.00, "output": 15.00, "cacheWrite": 3.75, "cacheRead": 0.30}
def get_usage_summary(
self,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
user_id: Optional[str] = None
) -> Dict[str, any]:
"""Get usage summary statistics."""
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
# Build query
query = "SELECT * FROM token_usage WHERE 1=1"
params = []
if start_date:
query += " AND timestamp >= ?"
params.append(start_date)
if end_date:
query += " AND timestamp <= ?"
params.append(end_date)
if user_id:
query += " AND user_id = ?"
params.append(user_id)
cursor.execute(query, params)
rows = cursor.fetchall()
# Calculate statistics
total_requests = len(rows)
total_input_tokens = sum(row[4] for row in rows)
total_output_tokens = sum(row[5] for row in rows)
total_cache_tokens = sum(row[6] + row[7] for row in rows)
total_cost = sum(row[8] for row in rows)
avg_latency = sum(row[9] for row in rows) / total_requests if total_requests > 0 else 0
# Model breakdown
model_usage = {}
for row in rows:
model = row[2]
if model not in model_usage:
model_usage[model] = {"requests": 0, "cost": 0}
model_usage[model]["requests"] += 1
model_usage[model]["cost"] += row[8]
conn.close()
return {
"total_requests": total_requests,
"total_input_tokens": total_input_tokens,
"total_output_tokens": total_output_tokens,
"total_cache_tokens": total_cache_tokens,
"total_cost": round(total_cost, 2),
"average_latency_ms": round(avg_latency),
"cost_per_request": round(total_cost / total_requests, 4) if total_requests > 0 else 0,
"cache_hit_rate": round(total_cache_tokens / total_input_tokens * 100, 2) if total_input_tokens > 0 else 0,
"model_breakdown": model_usage
}2. Real-time Monitoring Dashboard
import { EventEmitter } from 'events';
interface TokenMetrics {
timestamp: number;
model: string;
inputTokens: number;
outputTokens: number;
cacheTokens: number;
cost: number;
latency: number;
}
interface AlertRule {
id: string;
type: 'cost' | 'tokens' | 'latency' | 'rate';
threshold: number;
window: number; // seconds
action: (metrics: TokenMetrics[]) => void;
}
class TokenMonitor extends EventEmitter {
private metrics: TokenMetrics[] = [];
private alerts: Map<string, AlertRule> = new Map();
private costAccumulator = 0;
private tokenAccumulator = 0;
constructor() {
super();
// Clean old metrics every hour
setInterval(() => this.cleanOldMetrics(), 3600000);
}
recordMetrics(metrics: TokenMetrics) {
this.metrics.push(metrics);
this.costAccumulator += metrics.cost;
this.tokenAccumulator += metrics.inputTokens + metrics.outputTokens;
// Emit real-time events
this.emit('metrics', metrics);
this.emit('cost-update', this.costAccumulator);
// Check alerts
this.checkAlerts();
}
addAlert(rule: AlertRule) {
this.alerts.set(rule.id, rule);
}
removeAlert(id: string) {
this.alerts.delete(id);
}
private checkAlerts() {
const now = Date.now();
for (const [id, rule] of this.alerts) {
const windowStart = now - (rule.window * 1000);
const windowMetrics = this.metrics.filter(m => m.timestamp >= windowStart);
let triggered = false;
switch (rule.type) {
case 'cost':
const windowCost = windowMetrics.reduce((sum, m) => sum + m.cost, 0);
triggered = windowCost > rule.threshold;
break;
case 'tokens':
const windowTokens = windowMetrics.reduce(
(sum, m) => sum + m.inputTokens + m.outputTokens, 0
);
triggered = windowTokens > rule.threshold;
break;
case 'latency':
const avgLatency = windowMetrics.reduce((sum, m) => sum + m.latency, 0) /
windowMetrics.length;
triggered = avgLatency > rule.threshold;
break;
case 'rate':
const requestRate = windowMetrics.length / rule.window;
triggered = requestRate > rule.threshold;
break;
}
if (triggered) {
rule.action(windowMetrics);
this.emit('alert', { rule, metrics: windowMetrics });
}
}
}
getRealtimeStats(windowSeconds: number = 300) {
const now = Date.now();
const windowStart = now - (windowSeconds * 1000);
const windowMetrics = this.metrics.filter(m => m.timestamp >= windowStart);
if (windowMetrics.length === 0) {
return {
requests: 0,
totalCost: 0,
avgLatency: 0,
tokensPerSecond: 0,
costPerMinute: 0
};
}
const totalCost = windowMetrics.reduce((sum, m) => sum + m.cost, 0);
const totalTokens = windowMetrics.reduce(
(sum, m) => sum + m.inputTokens + m.outputTokens, 0
);
const avgLatency = windowMetrics.reduce((sum, m) => sum + m.latency, 0) /
windowMetrics.length;
return {
requests: windowMetrics.length,
totalCost: totalCost.toFixed(4),
avgLatency: Math.round(avgLatency),
tokensPerSecond: Math.round(totalTokens / windowSeconds),
costPerMinute: (totalCost / windowSeconds * 60).toFixed(4),
modelBreakdown: this.getModelBreakdown(windowMetrics)
};
}
private getModelBreakdown(metrics: TokenMetrics[]) {
const breakdown: Record<string, any> = {};
for (const metric of metrics) {
if (!breakdown[metric.model]) {
breakdown[metric.model] = {
requests: 0,
cost: 0,
avgLatency: 0,
latencies: []
};
}
breakdown[metric.model].requests++;
breakdown[metric.model].cost += metric.cost;
breakdown[metric.model].latencies.push(metric.latency);
}
// Calculate average latencies
for (const model in breakdown) {
const latencies = breakdown[model].latencies;
breakdown[model].avgLatency = Math.round(
latencies.reduce((a, b) => a + b, 0) / latencies.length
);
delete breakdown[model].latencies;
}
return breakdown;
}
private cleanOldMetrics() {
const oneHourAgo = Date.now() - 3600000;
this.metrics = this.metrics.filter(m => m.timestamp > oneHourAgo);
}
}
// Usage example
const monitor = new TokenMonitor();
// Add cost alert
monitor.addAlert({
id: 'high-cost',
type: 'cost',
threshold: 10.00, // $10 in 5 minutes
window: 300,
action: (metrics) => {
console.error(`⚠️ High cost alert: $${
metrics.reduce((sum, m) => sum + m.cost, 0).toFixed(2)
} in last 5 minutes`);
// Send notification, pause requests, etc.
}
});
// Add latency alert
monitor.addAlert({
id: 'high-latency',
type: 'latency',
threshold: 5000, // 5 seconds average
window: 60,
action: (metrics) => {
const avgLatency = metrics.reduce((sum, m) => sum + m.latency, 0) / metrics.length;
console.warn(`⚠️ High latency: ${avgLatency}ms average`);
}
});
// Real-time dashboard updates
monitor.on('metrics', (metrics: TokenMetrics) => {
console.log(`📊 ${metrics.model}: ${metrics.cost.toFixed(4)} | ${metrics.latency}ms`);
});
monitor.on('cost-update', (totalCost: number) => {
console.log(`💰 Total cost: $${totalCost.toFixed(2)}`);
});3. Advanced Analytics with Anomaly Detection
import numpy as np
from sklearn.ensemble import IsolationForest
from collections import deque
import pandas as pd
class TokenAnomalyDetector:
"""Detect anomalies in token usage patterns."""
def __init__(self, window_size: int = 100):
self.window_size = window_size
self.token_history = deque(maxlen=window_size)
self.cost_history = deque(maxlen=window_size)
self.latency_history = deque(maxlen=window_size)
self.model = IsolationForest(contamination=0.1, random_state=42)
self.is_trained = False
def add_observation(self, tokens: int, cost: float, latency: int):
"""Add new observation to history."""
self.token_history.append(tokens)
self.cost_history.append(cost)
self.latency_history.append(latency)
# Train model once we have enough data
if len(self.token_history) >= 50 and not self.is_trained:
self._train_model()
def _train_model(self):
"""Train anomaly detection model."""
# Prepare features
features = np.column_stack([
list(self.token_history),
list(self.cost_history),
list(self.latency_history)
])
# Normalize features
features = (features - features.mean(axis=0)) / features.std(axis=0)
# Train model
self.model.fit(features)
self.is_trained = True
def is_anomaly(self, tokens: int, cost: float, latency: int) -> Dict[str, any]:
"""Check if current observation is anomalous."""
if not self.is_trained:
return {"is_anomaly": False, "reason": "Model not trained"}
# Prepare feature
feature = np.array([[tokens, cost, latency]])
# Normalize using history statistics
history_features = np.column_stack([
list(self.token_history),
list(self.cost_history),
list(self.latency_history)
])
mean = history_features.mean(axis=0)
std = history_features.std(axis=0)
feature_norm = (feature - mean) / std
# Predict
prediction = self.model.predict(feature_norm)[0]
anomaly_score = self.model.score_samples(feature_norm)[0]
# Determine reason if anomaly
reason = None
if prediction == -1: # Anomaly detected
# Check which dimension is most anomalous
z_scores = np.abs(feature_norm[0])
max_z_idx = np.argmax(z_scores)
dimensions = ['tokens', 'cost', 'latency']
reason = f"Unusual {dimensions[max_z_idx]} value"
return {
"is_anomaly": prediction == -1,
"anomaly_score": float(anomaly_score),
"reason": reason,
"z_scores": {
"tokens": float(z_scores[0]),
"cost": float(z_scores[1]),
"latency": float(z_scores[2])
}
}
def get_usage_trends(self) -> Dict[str, any]:
"""Analyze usage trends."""
if len(self.token_history) < 10:
return {"error": "Insufficient data"}
df = pd.DataFrame({
'tokens': list(self.token_history),
'cost': list(self.cost_history),
'latency': list(self.latency_history)
})
# Calculate rolling statistics
window = min(20, len(df) // 2)
return {
"token_trend": {
"mean": float(df['tokens'].mean()),
"std": float(df['tokens'].std()),
"rolling_mean": list(df['tokens'].rolling(window).mean().dropna()),
"trend": "increasing" if df['tokens'].iloc[-window:].mean() > df['tokens'].iloc[:window].mean() else "decreasing"
},
"cost_trend": {
"mean": float(df['cost'].mean()),
"std": float(df['cost'].std()),
"rolling_mean": list(df['cost'].rolling(window).mean().dropna()),
"trend": "increasing" if df['cost'].iloc[-window:].mean() > df['cost'].iloc[:window].mean() else "decreasing"
},
"latency_trend": {
"mean": float(df['latency'].mean()),
"std": float(df['latency'].std()),
"rolling_mean": list(df['latency'].rolling(window).mean().dropna()),
"trend": "increasing" if df['latency'].iloc[-window:].mean() > df['latency'].iloc[:window].mean() else "decreasing"
}
}4. Multi-Agent Token Optimization
interface AgentConfig {
id: string;
name: string;
modelPreference: string[];
maxTokensPerRequest: number;
costBudgetPerHour: number;
}
interface TokenBudget {
agentId: string;
allocated: number;
used: number;
remaining: number;
resetTime: number;
}
class MultiAgentTokenOptimizer {
private agents: Map<string, AgentConfig> = new Map();
private budgets: Map<string, TokenBudget> = new Map();
private usageHistory: Map<string, TokenMetrics[]> = new Map();
constructor(private client: Anthropic) {
// Reset budgets hourly
setInterval(() => this.resetBudgets(), 3600000);
}
registerAgent(config: AgentConfig) {
this.agents.set(config.id, config);
this.budgets.set(config.id, {
agentId: config.id,
allocated: config.costBudgetPerHour,
used: 0,
remaining: config.costBudgetPerHour,
resetTime: Date.now() + 3600000
});
this.usageHistory.set(config.id, []);
}
async executeRequest(
agentId: string,
messages: any[],
preferredModel?: string
) {
const agent = this.agents.get(agentId);
const budget = this.budgets.get(agentId);
if (!agent || !budget) {
throw new Error(`Agent ${agentId} not registered`);
}
// Select optimal model based on budget and preference
const model = this.selectOptimalModel(agent, budget, preferredModel);
// Estimate cost before request
const estimatedCost = this.estimateRequestCost(messages, model);
if (estimatedCost > budget.remaining) {
// Try cheaper model or reject
const cheaperModel = this.findCheaperModel(agent, budget, estimatedCost);
if (!cheaperModel) {
throw new Error(`Insufficient budget for agent ${agentId}`);
}
model = cheaperModel;
}
// Execute request with monitoring
const startTime = Date.now();
const response = await this.client.messages.create({
model,
messages,
max_tokens: agent.maxTokensPerRequest
});
const latency = Date.now() - startTime;
// Track usage
const actualCost = this.calculateActualCost(response);
budget.used += actualCost;
budget.remaining -= actualCost;
const metrics: TokenMetrics = {
timestamp: Date.now(),
model,
inputTokens: response.usage.input_tokens,
outputTokens: response.usage.output_tokens,
cacheTokens: response.usage.cache_read_input_tokens || 0,
cost: actualCost,
latency
};
this.usageHistory.get(agentId)!.push(metrics);
return {
response,
metrics,
budgetStatus: {
used: budget.used.toFixed(4),
remaining: budget.remaining.toFixed(4),
percentUsed: (budget.used / budget.allocated * 100).toFixed(1)
}
};
}
private selectOptimalModel(
agent: AgentConfig,
budget: TokenBudget,
preferred?: string
): string {
// If preferred model is within budget, use it
if (preferred && agent.modelPreference.includes(preferred)) {
return preferred;
}
// Otherwise, select based on remaining budget
const budgetPercentRemaining = budget.remaining / budget.allocated;
if (budgetPercentRemaining > 0.5) {
// Plenty of budget - use best model
return agent.modelPreference[0];
} else if (budgetPercentRemaining > 0.2) {
// Conservative - use middle tier
return agent.modelPreference[1] || agent.modelPreference[0];
} else {
// Low budget - use cheapest
return agent.modelPreference[agent.modelPreference.length - 1];
}
}
private estimateRequestCost(messages: any[], model: string): number {
// Rough token estimation (4 chars = 1 token)
const textLength = JSON.stringify(messages).length;
const estimatedTokens = Math.ceil(textLength / 4);
const modelCosts = this.getModelCosts(model);
return (estimatedTokens / 1_000_000) * modelCosts.input;
}
private calculateActualCost(response: any): number {
const model = response.model;
const usage = response.usage;
const costs = this.getModelCosts(model);
const inputCost = (usage.input_tokens / 1_000_000) * costs.input;
const outputCost = (usage.output_tokens / 1_000_000) * costs.output;
const cacheCost = (usage.cache_read_input_tokens || 0) / 1_000_000 * costs.cacheRead;
return inputCost + outputCost + cacheCost;
}
private findCheaperModel(
agent: AgentConfig,
budget: TokenBudget,
requiredCost: number
): string | null {
// Try models in reverse order (cheapest first)
for (let i = agent.modelPreference.length - 1; i >= 0; i--) {
const model = agent.modelPreference[i];
const modelCosts = this.getModelCosts(model);
// Estimate if this model would fit in budget
const estimatedCost = requiredCost * (modelCosts.input / 15.00); // Relative to opus
if (estimatedCost <= budget.remaining) {
return model;
}
}
return null;
}
private resetBudgets() {
const now = Date.now();
for (const [agentId, budget] of this.budgets) {
if (now >= budget.resetTime) {
budget.allocated = this.agents.get(agentId)!.costBudgetPerHour;
budget.used = 0;
budget.remaining = budget.allocated;
budget.resetTime = now + 3600000;
// Clean old history
const history = this.usageHistory.get(agentId)!;
const oneHourAgo = now - 3600000;
this.usageHistory.set(
agentId,
history.filter(m => m.timestamp > oneHourAgo)
);
}
}
}
getAgentReport(agentId: string) {
const agent = this.agents.get(agentId);
const budget = this.budgets.get(agentId);
const history = this.usageHistory.get(agentId);
if (!agent || !budget || !history) {
return null;
}
const totalRequests = history.length;
const avgCostPerRequest = totalRequests > 0
? history.reduce((sum, m) => sum + m.cost, 0) / totalRequests
: 0;
const modelUsage: Record<string, number> = {};
for (const metric of history) {
modelUsage[metric.model] = (modelUsage[metric.model] || 0) + 1;
}
return {
agent: agent.name,
budget: {
allocated: budget.allocated.toFixed(2),
used: budget.used.toFixed(2),
remaining: budget.remaining.toFixed(2),
percentUsed: (budget.used / budget.allocated * 100).toFixed(1)
},
usage: {
totalRequests,
avgCostPerRequest: avgCostPerRequest.toFixed(4),
modelBreakdown: modelUsage,
projectedHourlyCost: (avgCostPerRequest * totalRequests).toFixed(2)
}
};
}
private getModelCosts(model: string) {
// Implementation same as earlier examples
if (model.includes('opus')) {
return { input: 15.00, output: 75.00, cacheRead: 1.50 };
} else if (model.includes('sonnet')) {
return { input: 3.00, output: 15.00, cacheRead: 0.30 };
} else {
return { input: 0.80, output: 4.00, cacheRead: 0.08 };
}
}
}Monitoring Best Practices
1. Set Up Tiered Alerts
ALERT_THRESHOLDS = {
"cost": {
"warning": 10.00, # $10/hour
"critical": 50.00, # $50/hour
"emergency": 100.00 # $100/hour
},
"tokens": {
"warning": 1_000_000, # 1M tokens/hour
"critical": 5_000_000, # 5M tokens/hour
"emergency": 10_000_000 # 10M tokens/hour
},
"latency": {
"warning": 3000, # 3 seconds
"critical": 5000, # 5 seconds
"emergency": 10000 # 10 seconds
}
}2. Implement Cost Controls
class CostController {
private dailyLimit: number;
private hourlyLimit: number;
private currentDailySpend = 0;
private currentHourlySpend = 0;
constructor(dailyLimit: number, hourlyLimit: number) {
this.dailyLimit = dailyLimit;
this.hourlyLimit = hourlyLimit;
// Reset counters
setInterval(() => this.currentHourlySpend = 0, 3600000);
setInterval(() => this.currentDailySpend = 0, 86400000);
}
canProceed(estimatedCost: number): {
allowed: boolean;
reason?: string;
} {
if (this.currentHourlySpend + estimatedCost > this.hourlyLimit) {
return { allowed: false, reason: "Hourly limit exceeded" };
}
if (this.currentDailySpend + estimatedCost > this.dailyLimit) {
return { allowed: false, reason: "Daily limit exceeded" };
}
return { allowed: true };
}
recordSpend(amount: number) {
this.currentHourlySpend += amount;
this.currentDailySpend += amount;
}
}3. Optimize Token Usage
def optimize_prompt(prompt: str, max_tokens: int = 1000) -> str:
"""Optimize prompt to reduce token usage while maintaining quality."""
# Remove excessive whitespace
prompt = ' '.join(prompt.split())
# Use abbreviations for common terms
replacements = {
"artificial intelligence": "AI",
"machine learning": "ML",
"natural language processing": "NLP",
"for example": "e.g.",
"that is": "i.e.",
}
for full, abbr in replacements.items():
prompt = prompt.replace(full, abbr)
# Truncate if still too long (rough estimate: 4 chars = 1 token)
if len(prompt) > max_tokens * 4:
prompt = prompt[:max_tokens * 4] + "..."
return promptDashboard Integration
Sample Grafana Query
-- Token usage over time
SELECT
DATE_TRUNC('hour', timestamp) as time,
SUM(input_tokens + output_tokens) as total_tokens,
SUM(total_cost) as total_cost,
AVG(latency_ms) as avg_latency
FROM token_usage
WHERE timestamp >= NOW() - INTERVAL '24 hours'
GROUP BY time
ORDER BY time;
-- Cost by model
SELECT
model,
COUNT(*) as requests,
SUM(total_cost) as total_cost,
AVG(total_cost) as avg_cost_per_request
FROM token_usage
WHERE timestamp >= NOW() - INTERVAL '24 hours'
GROUP BY model
ORDER BY total_cost DESC;
-- Cache efficiency
SELECT
DATE_TRUNC('hour', timestamp) as time,
SUM(cache_read_tokens)::float / NULLIF(SUM(input_tokens), 0) * 100 as cache_hit_rate,
SUM(cache_read_tokens) * 2.70 / 1000000 as cache_savings
FROM token_usage
WHERE timestamp >= NOW() - INTERVAL '24 hours'
GROUP BY time
ORDER BY time;ROI Calculation
def calculate_optimization_roi(
baseline_metrics: Dict[str, float],
optimized_metrics: Dict[str, float],
implementation_hours: float = 40,
developer_rate: float = 150.0
) -> Dict[str, float]:
"""Calculate ROI for token optimization efforts."""
# Implementation cost
implementation_cost = implementation_hours * developer_rate
# Monthly savings
baseline_monthly = baseline_metrics["daily_cost"] * 30
optimized_monthly = optimized_metrics["daily_cost"] * 30
monthly_savings = baseline_monthly - optimized_monthly
# Payback period
payback_months = implementation_cost / monthly_savings if monthly_savings > 0 else float('inf')
# Annual ROI
annual_savings = monthly_savings * 12
annual_roi = ((annual_savings - implementation_cost) / implementation_cost) * 100
return {
"implementation_cost": implementation_cost,
"monthly_savings": monthly_savings,
"annual_savings": annual_savings,
"payback_months": payback_months,
"annual_roi_percent": annual_roi,
"cost_reduction_percent": ((baseline_monthly - optimized_monthly) / baseline_monthly) * 100
}Conclusion
Effective token usage monitoring and analytics are essential for:
- Cost Control: Prevent budget overruns with real-time alerts
- Performance Optimization: Identify and fix latency issues
- Capacity Planning: Understand usage patterns for scaling
- ROI Demonstration: Quantify the value of optimization efforts
Implement these patterns progressively, starting with basic tracking and gradually adding advanced analytics as your usage scales.