lc/cli/
usage.rs

1//! Usage statistics commands
2
3use crate::analytics::usage_stats::{display_usage_overview, BarChart, UsageAnalyzer};
4use crate::cli::UsageCommands;
5use anyhow::Result;
6use colored::Colorize;
7
8/// Handle usage-related commands
9pub async fn handle(
10    command: Option<UsageCommands>,
11    days: Option<u64>,
12    tokens_only: bool,
13    requests_only: bool,
14    limit: Option<usize>,
15) -> Result<()> {
16    // Convert types to match what the analytics module expects
17    let days_u32 = days.map(|d| d as u32);
18    let limit_val = limit.unwrap_or(10);
19
20    let analyzer = UsageAnalyzer::new()?;
21    let stats = analyzer.get_usage_stats(days_u32)?;
22
23    if stats.total_requests == 0 {
24        println!("{} No usage data found", "â„šī¸".blue());
25        if days.is_some() {
26            println!("Try expanding the time range or check if you have any logged interactions.");
27        }
28        return Ok(());
29    }
30
31    match command {
32        Some(UsageCommands::Daily { count }) => {
33            let value_type = determine_value_type(tokens_only, requests_only);
34
35            BarChart::render_time_series(
36                "📅 Daily Usage",
37                &stats.daily_usage,
38                value_type,
39                50,
40                count.min(limit_val),
41            );
42        }
43        Some(UsageCommands::Weekly { count }) => {
44            let value_type = determine_value_type(tokens_only, requests_only);
45
46            BarChart::render_time_series(
47                "📊 Weekly Usage",
48                &stats.weekly_usage,
49                value_type,
50                50,
51                count.min(limit_val),
52            );
53        }
54        Some(UsageCommands::Monthly { count }) => {
55            let value_type = determine_value_type(tokens_only, requests_only);
56
57            BarChart::render_time_series(
58                "📈 Monthly Usage",
59                &stats.monthly_usage,
60                value_type,
61                50,
62                count.min(limit_val),
63            );
64        }
65        Some(UsageCommands::Yearly { count }) => {
66            let value_type = determine_value_type(tokens_only, requests_only);
67
68            BarChart::render_time_series(
69                "📊 Yearly Usage",
70                &stats.yearly_usage,
71                value_type,
72                50,
73                count.min(limit_val),
74            );
75        }
76        Some(UsageCommands::Models { count }) => {
77            let value_type = determine_value_type(tokens_only, requests_only);
78
79            BarChart::render_horizontal(
80                "🤖 Top Models by Usage",
81                &stats.model_usage,
82                value_type,
83                50,
84                count.min(limit_val),
85            );
86        }
87        None => {
88            // Default: show overview and top charts
89            display_usage_overview(&stats);
90
91            if !tokens_only && !requests_only {
92                // Show both tokens and requests by default
93                BarChart::render_horizontal(
94                    "🤖 Top Models by Token Usage",
95                    &stats.model_usage,
96                    "tokens",
97                    50,
98                    limit_val.min(5),
99                );
100
101                BarChart::render_time_series(
102                    "📅 Recent Daily Usage (Tokens)",
103                    &stats.daily_usage,
104                    "tokens",
105                    50,
106                    limit_val.min(14),
107                );
108            } else if tokens_only {
109                BarChart::render_horizontal(
110                    "🤖 Top Models by Token Usage",
111                    &stats.model_usage,
112                    "tokens",
113                    50,
114                    limit_val.min(10),
115                );
116
117                BarChart::render_time_series(
118                    "📅 Recent Daily Token Usage",
119                    &stats.daily_usage,
120                    "tokens",
121                    50,
122                    limit_val.min(14),
123                );
124            } else if requests_only {
125                BarChart::render_horizontal(
126                    "🤖 Top Models by Request Count",
127                    &stats.model_usage,
128                    "requests",
129                    50,
130                    limit_val.min(10),
131                );
132
133                BarChart::render_time_series(
134                    "📅 Recent Daily Request Count",
135                    &stats.daily_usage,
136                    "requests",
137                    50,
138                    limit_val.min(14),
139                );
140            }
141        }
142    }
143
144    Ok(())
145}
146
147/// Determine which value type to display based on flags
148fn determine_value_type(tokens_only: bool, requests_only: bool) -> &'static str {
149    if tokens_only {
150        "tokens"
151    } else if requests_only {
152        "requests"
153    } else {
154        "tokens" // Default to tokens when neither flag is set
155    }
156}