Skip to main content

ironflow_cli/commands/
stats.rs

1//! Stats commands: aggregate and historical.
2
3use anyhow::Result;
4use clap::{Args, Subcommand};
5use ironflow_sdk::IronflowClient;
6use ironflow_sdk::client::StatsHistoryParams;
7use uuid::Uuid;
8
9use crate::output;
10
11/// Stats subcommand arguments.
12///
13/// # Examples
14///
15/// ```
16/// use ironflow_cli::commands::stats::StatsArgs;
17/// ```
18#[derive(Debug, Args)]
19pub struct StatsArgs {
20    /// Stats subcommand. Omit for aggregate stats.
21    #[command(subcommand)]
22    pub command: Option<StatsCommands>,
23}
24
25/// Available stats subcommands.
26///
27/// # Examples
28///
29/// ```
30/// use ironflow_cli::commands::stats::StatsCommands;
31/// ```
32#[derive(Debug, Subcommand)]
33pub enum StatsCommands {
34    /// Show time-bucketed historical statistics.
35    History {
36        /// Filter by workflow name (case-insensitive substring match).
37        #[arg(long)]
38        workflow: Option<String>,
39        /// Time period: 24h, 7d, 30d, 90d. Defaults to 7d.
40        #[arg(long, default_value = "7d")]
41        period: String,
42        /// Bucket granularity: 1h, 1d, 1w. Auto-derived from period when omitted.
43        #[arg(long)]
44        granularity: Option<String>,
45        /// Filter by run status (pending, running, completed, failed, etc.).
46        #[arg(long)]
47        status: Option<String>,
48        /// Filter by labels. Comma-separated `key:value` pairs.
49        #[arg(long)]
50        label: Option<String>,
51        /// Filter by step presence (only applies to completed/cancelled runs).
52        #[arg(long)]
53        has_steps: Option<bool>,
54        /// Filter by author: the user ID that triggered the run.
55        ///
56        /// Also matches runs triggered by one of that user's API keys.
57        #[arg(long)]
58        created_by: Option<Uuid>,
59        /// Filter by concurrency group: only runs that belong to this group.
60        #[arg(long)]
61        concurrency_group: Option<String>,
62    },
63}
64
65/// Execute the `stats` command tree.
66///
67/// # Errors
68///
69/// Returns an error on API failure.
70pub async fn execute(client: &IronflowClient, args: &StatsArgs, json_mode: bool) -> Result<()> {
71    match &args.command {
72        None => {
73            let response = client.get_stats().await?;
74            output::print_output(json_mode, &response, || output::stats_table(&response.data))?;
75        }
76        Some(StatsCommands::History {
77            workflow,
78            period,
79            granularity,
80            status,
81            label,
82            has_steps,
83            created_by,
84            concurrency_group,
85        }) => {
86            let params = StatsHistoryParams {
87                workflow: workflow.as_deref(),
88                period: Some(period.as_str()),
89                granularity: granularity.as_deref(),
90                status: status.as_deref(),
91                label: label.as_deref(),
92                has_steps: *has_steps,
93                created_by: *created_by,
94                concurrency_group: concurrency_group.as_deref(),
95            };
96            let response = client.stats_history_with(&params).await?;
97            output::print_output(json_mode, &response, || {
98                output::stats_history_table(&response.data)
99            })?;
100        }
101    }
102    Ok(())
103}