systemprompt_cli/commands/infrastructure/logs/request/
mod.rs1mod list;
7mod show;
8mod stats;
9
10use anyhow::Result;
11use clap::Subcommand;
12use schemars::JsonSchema;
13use serde::{Deserialize, Serialize};
14use systemprompt_runtime::DatabaseContext;
15
16use super::types::{MessageRow, ToolCallRow};
17use crate::CliConfig;
18use crate::shared::render_result;
19
20#[derive(Debug, Subcommand)]
21pub enum RequestCommands {
22 #[command(
23 about = "List recent AI requests",
24 after_help = "EXAMPLES:\n systemprompt infra logs request list\n systemprompt infra \
25 logs request list --model gpt-4 --since 1h"
26 )]
27 List(list::ListArgs),
28
29 #[command(
30 about = "Show AI request details",
31 after_help = "EXAMPLES:\n systemprompt infra logs request show abc123\n systemprompt \
32 infra logs request show abc123 --messages --tools"
33 )]
34 Show(show::ShowArgs),
35
36 #[command(
37 about = "Show aggregate AI request statistics",
38 after_help = "EXAMPLES:\n systemprompt infra logs request stats\n systemprompt infra \
39 logs request stats --since 24h"
40 )]
41 Stats(stats::StatsArgs),
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
45pub struct RequestListRow {
46 pub request_id: String,
47 pub timestamp: String,
48 pub provider: String,
49 pub model: String,
50 pub tokens: String,
51 pub cost: String,
52 #[serde(skip_serializing_if = "Option::is_none")]
53 pub latency_ms: Option<i64>,
54 pub status: String,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
58pub struct RequestListOutput {
59 pub requests: Vec<RequestListRow>,
60 pub total: u64,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
64pub struct RequestShowOutput {
65 pub request_id: String,
66 pub provider: String,
67 pub model: String,
68 pub input_tokens: i32,
69 pub output_tokens: i32,
70 pub cost_dollars: f64,
71 pub latency_ms: i64,
72 pub status: String,
73 #[serde(skip_serializing_if = "Option::is_none")]
74 pub error_message: Option<String>,
75 pub messages: Vec<MessageRow>,
76 pub linked_mcp_calls: Vec<ToolCallRow>,
77}
78
79pub async fn execute(command: RequestCommands, config: &CliConfig) -> Result<()> {
80 match command {
81 RequestCommands::List(args) => {
82 let result = list::execute(args, config).await?;
83 render_result(&result);
84 Ok(())
85 },
86 RequestCommands::Show(args) => {
87 let result = show::execute(args, config).await?;
88 render_result(&result);
89 Ok(())
90 },
91 RequestCommands::Stats(args) => stats::execute(args, config).await,
92 }
93}
94
95pub async fn execute_with_pool(
96 command: RequestCommands,
97 db_ctx: &DatabaseContext,
98 config: &CliConfig,
99) -> Result<()> {
100 match command {
101 RequestCommands::List(args) => {
102 let result = list::execute_with_pool(args, db_ctx, config).await?;
103 render_result(&result);
104 Ok(())
105 },
106 RequestCommands::Show(args) => {
107 let result = show::execute_with_pool(args, db_ctx, config).await?;
108 render_result(&result);
109 Ok(())
110 },
111 RequestCommands::Stats(args) => stats::execute_with_pool(args, db_ctx, config).await,
112 }
113}