systemprompt_cli/commands/analytics/sessions/
mod.rs1mod live;
2mod stats;
3mod trends;
4
5use anyhow::Result;
6use clap::Subcommand;
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9use systemprompt_runtime::DatabaseContext;
10
11use crate::CliConfig;
12
13#[derive(Debug, Subcommand)]
14pub enum SessionsCommands {
15 #[command(about = "Session statistics")]
16 Stats(stats::StatsArgs),
17
18 #[command(about = "Session trends over time")]
19 Trends(trends::TrendsArgs),
20
21 #[command(about = "Real-time active sessions")]
22 Live(live::LiveArgs),
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
26pub struct SessionStatsOutput {
27 pub period: String,
28 pub total_sessions: i64,
29 pub active_sessions: i64,
30 pub unique_users: i64,
31 pub avg_duration_seconds: i64,
32 pub avg_requests_per_session: f64,
33 pub conversion_rate: f64,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
37pub struct SessionTrendPoint {
38 pub timestamp: String,
39 pub session_count: i64,
40 pub active_users: i64,
41 pub avg_duration_seconds: i64,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
45pub struct SessionTrendsOutput {
46 pub period: String,
47 pub group_by: String,
48 pub points: Vec<SessionTrendPoint>,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
52pub struct ActiveSessionRow {
53 pub session_id: String,
54 pub user_type: String,
55 pub started_at: String,
56 pub duration_seconds: i64,
57 pub request_count: i64,
58 pub last_activity: String,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
62pub struct LiveSessionsOutput {
63 pub active_count: i64,
64 pub sessions: Vec<ActiveSessionRow>,
65 pub timestamp: String,
66}
67
68pub async fn execute(command: SessionsCommands, config: &CliConfig) -> Result<()> {
69 match command {
70 SessionsCommands::Stats(args) => stats::execute(args, config).await,
71 SessionsCommands::Trends(args) => trends::execute(args, config).await,
72 SessionsCommands::Live(args) => live::execute(args, config).await,
73 }
74}
75
76pub async fn execute_with_pool(
77 command: SessionsCommands,
78 db_ctx: &DatabaseContext,
79 config: &CliConfig,
80) -> Result<()> {
81 match command {
82 SessionsCommands::Stats(args) => stats::execute_with_pool(args, db_ctx, config).await,
83 SessionsCommands::Trends(args) => trends::execute_with_pool(args, db_ctx, config).await,
84 SessionsCommands::Live(args) => live::execute_with_pool(args, db_ctx, config).await,
85 }
86}