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