(
config: &Config,
group_by: &str,
_since: Option<String>,
_until: Option<String>,
format: OutputFormat,
)
| 248 | } |
| 249 | |
| 250 | pub async fn stats( |
| 251 | config: &Config, |
| 252 | group_by: &str, |
| 253 | _since: Option<String>, |
| 254 | _until: Option<String>, |
| 255 | format: OutputFormat, |
| 256 | ) -> Result<()> { |
| 257 | let ds = StatsDataSource::new(config.clone()); |
| 258 | let stats = ds.load().await?; |
| 259 | |
| 260 | let mut writer = OutputWriter::new(std::io::stdout(), format); |
| 261 | |
| 262 | match format { |
| 263 | OutputFormat::Json => { |
| 264 | writer.write_json(&stats)?; |
| 265 | } |
| 266 | OutputFormat::Raw | OutputFormat::Jsonl => { |
| 267 | writer.write_json(&stats)?; |
| 268 | } |
| 269 | OutputFormat::Table => { |
| 270 | writer.writeln("=== Claude Code Usage Statistics ===\n")?; |
| 271 | |
| 272 | writer.writeln(&format!("Total Messages: {}", stats.total_messages))?; |
| 273 | writer.writeln(&format!("Total Sessions: {}", stats.total_sessions))?; |
| 274 | writer.writeln(&format!("Total Tokens: {}", stats.total_tokens()))?; |
| 275 | writer.writeln(&format!("First Session: {}", stats.first_session_date))?; |
| 276 | writer.writeln(&format!("Last Computed: {}", stats.last_computed_date))?; |
| 277 | |
| 278 | if let Some(ref longest) = stats.longest_session { |
| 279 | writer.writeln(&format!( |
| 280 | "\nLongest Session: {} ({} messages)", |
| 281 | longest.session_id, longest.message_count |
| 282 | ))?; |
| 283 | } |
| 284 | |
| 285 | writer.writeln("\n--- Model Usage ---")?; |
| 286 | let mut model_table = create_table(); |
| 287 | model_table.set_header(vec!["Model", "Input Tokens", "Output Tokens"]); |
| 288 | |
| 289 | for (model, usage) in &stats.model_usage { |
| 290 | model_table.add_row(vec![ |
| 291 | Cell::new(model), |
| 292 | Cell::new(usage.input_tokens), |
| 293 | Cell::new(usage.output_tokens), |
| 294 | ]); |
| 295 | } |
| 296 | writer.write_table(model_table)?; |
| 297 | |
| 298 | if group_by == "date" { |
| 299 | writer.writeln("\n--- Daily Activity (last 10 days) ---")?; |
| 300 | let mut daily_table = create_table(); |
| 301 | daily_table.set_header(vec!["Date", "Messages", "Sessions", "Tool Calls"]); |
| 302 | |
| 303 | for activity in stats.daily_activity.iter().rev().take(10) { |
| 304 | daily_table.add_row(vec![ |
| 305 | Cell::new(&activity.date), |
| 306 | Cell::new(activity.message_count), |
| 307 | Cell::new(activity.session_count), |
no test coverage detected