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