Skip to main content

chub_cli/commands/
telemetry_cmd.rs

1use clap::{Args, Subcommand};
2use owo_colors::OwoColorize;
3
4use chub_core::identity::get_or_create_client_id;
5use chub_core::team::analytics;
6use chub_core::telemetry::{get_telemetry_url, is_feedback_enabled, is_telemetry_enabled};
7
8#[derive(Args)]
9pub struct TelemetryArgs {
10    #[command(subcommand)]
11    command: TelemetryCommand,
12}
13
14#[derive(Subcommand)]
15enum TelemetryCommand {
16    /// Show telemetry configuration and status
17    Status,
18    /// Export the raw event journal (JSONL)
19    Export,
20    /// Clear the local event journal
21    Clear,
22}
23
24pub fn run(args: TelemetryArgs, json: bool) {
25    match args.command {
26        TelemetryCommand::Status => run_status(json),
27        TelemetryCommand::Export => run_export(),
28        TelemetryCommand::Clear => run_clear(json),
29    }
30}
31
32fn run_status(json: bool) {
33    let telemetry_enabled = is_telemetry_enabled();
34    let feedback_enabled = is_feedback_enabled();
35    let remote_url = get_telemetry_url();
36    let journal_size = analytics::journal_size_bytes();
37    let events = analytics::load_events();
38
39    if json {
40        let client_id = get_or_create_client_id();
41        println!(
42            "{}",
43            serde_json::json!({
44                "telemetry": telemetry_enabled,
45                "feedback": feedback_enabled,
46                "mode": if remote_url.is_some() { "local+remote" } else { "local" },
47                "remote_url": remote_url,
48                "client_id_prefix": client_id.as_deref().map(|s| &s[..s.len().min(8)]),
49                "journal_events": events.len(),
50                "journal_size_bytes": journal_size,
51            })
52        );
53    } else {
54        let tl = if telemetry_enabled {
55            "enabled".green().to_string()
56        } else {
57            "disabled".red().to_string()
58        };
59        let fb = if feedback_enabled {
60            "enabled".green().to_string()
61        } else {
62            "disabled".red().to_string()
63        };
64        let mode = if remote_url.is_some() {
65            "local + remote".cyan().to_string()
66        } else {
67            "local only".yellow().to_string()
68        };
69
70        eprintln!("{}", "Telemetry Status".bold());
71        eprintln!("  Telemetry: {}", tl);
72        eprintln!("  Feedback:  {}", fb);
73        eprintln!("  Mode:      {}", mode);
74        if let Some(ref url) = remote_url {
75            eprintln!("  Remote:    {}", url);
76        } else {
77            eprintln!(
78                "  Remote:    {}",
79                "(not configured — set telemetry_url in config to enable)".dimmed()
80            );
81        }
82        if let Some(cid) = get_or_create_client_id() {
83            let prefix = &cid[..cid.len().min(8)];
84            eprintln!("  Client ID: {}...", prefix);
85        }
86        eprintln!(
87            "  Journal:   {} events, {:.1} KB",
88            events.len(),
89            journal_size as f64 / 1024.0
90        );
91
92        eprintln!("\n{}", "Configuration:".bold());
93        eprintln!("  Disable:  CHUB_TELEMETRY=0 or telemetry: false in config");
94        eprintln!("  Remote:   Set telemetry_url in ~/.chub/config.yaml");
95        eprintln!("  View:     chub stats --days 30");
96        eprintln!("  Export:   chub telemetry export > events.jsonl");
97        eprintln!("  Clear:    chub telemetry clear");
98    }
99}
100
101fn run_export() {
102    print!("{}", analytics::export_raw());
103}
104
105fn run_clear(json: bool) {
106    let events = analytics::load_events();
107    let count = events.len();
108
109    if analytics::clear_journal() {
110        if json {
111            println!(
112                "{}",
113                serde_json::json!({ "status": "cleared", "events_removed": count })
114            );
115        } else {
116            eprintln!("{} ({} events removed)", "Journal cleared.".green(), count);
117        }
118    } else if json {
119        println!(
120            "{}",
121            serde_json::json!({ "status": "error", "reason": "could_not_delete" })
122        );
123    } else {
124        eprintln!("{}", "Failed to clear journal.".red());
125    }
126}