systemprompt_cli/commands/analytics/requests/
mod.rs1mod list;
12mod models;
13mod stats;
14mod trends;
15
16use anyhow::Result;
17use clap::Subcommand;
18use schemars::JsonSchema;
19use serde::{Deserialize, Serialize};
20
21use crate::context::CommandContext;
22use crate::shared::render_result;
23
24#[derive(Debug, Subcommand)]
25pub enum RequestsCommands {
26 #[command(
27 about = "Dashboard request metrics: time range, model filter, cache-hit rate, CSV export. For a quick operational aggregate, use `infra logs request stats`"
28 )]
29 Stats(stats::StatsArgs),
30
31 #[command(
32 about = "Dashboard list of AI requests with time range, model filter, and CSV export. For a quick operational list, use `infra logs request list`"
33 )]
34 List(list::ListArgs),
35
36 #[command(about = "AI request trends over time")]
37 Trends(trends::TrendsArgs),
38
39 #[command(about = "Model usage breakdown")]
40 Models(models::ModelsArgs),
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
44pub struct RequestStatsOutput {
45 pub period: String,
46 pub total_requests: i64,
47 pub total_tokens: i64,
48 pub input_tokens: i64,
49 pub output_tokens: i64,
50 pub total_cost_microdollars: i64,
51 pub avg_latency_ms: i64,
52 pub cache_hit_rate: f64,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
56pub struct RequestTrendPoint {
57 pub timestamp: String,
58 pub request_count: i64,
59 pub total_tokens: i64,
60 pub cost_microdollars: i64,
61 pub avg_latency_ms: i64,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
65pub struct RequestTrendsOutput {
66 pub period: String,
67 pub group_by: String,
68 pub points: Vec<RequestTrendPoint>,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
72pub struct ModelUsageRow {
73 pub provider: String,
74 pub model: String,
75 pub request_count: i64,
76 pub total_tokens: i64,
77 pub total_cost_microdollars: i64,
78 pub avg_latency_ms: i64,
79 pub percentage: f64,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
83pub struct ModelsOutput {
84 pub period: String,
85 pub models: Vec<ModelUsageRow>,
86 pub total_requests: i64,
87}
88
89pub async fn execute(command: RequestsCommands, ctx: &CommandContext) -> Result<()> {
90 let db_ctx = ctx.database().await?;
91 match command {
92 RequestsCommands::Stats(args) => {
93 let result = stats::execute_with_pool(args, &db_ctx, &ctx.cli).await?;
94 render_result(&result, &ctx.cli);
95 Ok(())
96 },
97 RequestsCommands::List(args) => {
98 let result = list::execute_with_pool(args, &db_ctx, &ctx.cli).await?;
99 render_result(&result, &ctx.cli);
100 Ok(())
101 },
102 RequestsCommands::Trends(args) => {
103 let result = trends::execute_with_pool(args, &db_ctx, &ctx.cli).await?;
104 render_result(&result, &ctx.cli);
105 Ok(())
106 },
107 RequestsCommands::Models(args) => {
108 let result = models::execute_with_pool(args, &db_ctx, &ctx.cli).await?;
109 render_result(&result, &ctx.cli);
110 Ok(())
111 },
112 }
113}