Skip to main content

systemprompt_cli/commands/analytics/tools/
mod.rs

1mod list;
2mod show;
3mod stats;
4mod trends;
5
6use anyhow::Result;
7use clap::Subcommand;
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10use systemprompt_runtime::DatabaseContext;
11
12use crate::shared::render_result;
13use crate::CliConfig;
14
15#[derive(Debug, Subcommand)]
16pub enum ToolsCommands {
17    #[command(about = "Aggregate tool statistics")]
18    Stats(stats::StatsArgs),
19
20    #[command(about = "List tools with metrics")]
21    List(list::ListArgs),
22
23    #[command(about = "Tool usage trends over time")]
24    Trends(trends::TrendsArgs),
25
26    #[command(about = "Deep dive into specific tool")]
27    Show(show::ShowArgs),
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
31pub struct ToolStatsOutput {
32    pub period: String,
33    pub total_tools: i64,
34    pub total_executions: i64,
35    pub successful: i64,
36    pub failed: i64,
37    pub timeout: i64,
38    pub success_rate: f64,
39    pub avg_execution_time_ms: i64,
40    pub p95_execution_time_ms: i64,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
44pub struct ToolListRow {
45    pub tool_name: String,
46    pub server_name: String,
47    pub execution_count: i64,
48    pub success_rate: f64,
49    pub avg_execution_time_ms: i64,
50    pub last_used: String,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
54pub struct ToolListOutput {
55    pub tools: Vec<ToolListRow>,
56    pub total: i64,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
60pub struct ToolTrendPoint {
61    pub timestamp: String,
62    pub execution_count: i64,
63    pub success_rate: f64,
64    pub avg_execution_time_ms: i64,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
68pub struct ToolTrendsOutput {
69    pub tool: Option<String>,
70    pub period: String,
71    pub group_by: String,
72    pub points: Vec<ToolTrendPoint>,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
76pub struct ToolShowOutput {
77    pub tool_name: String,
78    pub period: String,
79    pub summary: ToolStatsOutput,
80    pub status_breakdown: Vec<StatusBreakdownItem>,
81    pub top_errors: Vec<ErrorItem>,
82    pub usage_by_agent: Vec<AgentUsageItem>,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
86pub struct StatusBreakdownItem {
87    pub status: String,
88    pub count: i64,
89    pub percentage: f64,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
93pub struct ErrorItem {
94    pub error_message: String,
95    pub count: i64,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
99pub struct AgentUsageItem {
100    pub agent_name: String,
101    pub count: i64,
102    pub percentage: f64,
103}
104
105pub async fn execute(command: ToolsCommands, config: &CliConfig) -> Result<()> {
106    match command {
107        ToolsCommands::Stats(args) => {
108            let result = stats::execute(args, config).await?;
109            render_result(&result);
110            Ok(())
111        },
112        ToolsCommands::List(args) => {
113            let result = list::execute(args, config).await?;
114            render_result(&result);
115            Ok(())
116        },
117        ToolsCommands::Trends(args) => {
118            let result = trends::execute(args, config).await?;
119            render_result(&result);
120            Ok(())
121        },
122        ToolsCommands::Show(args) => {
123            let result = show::execute(args, config).await?;
124            render_result(&result);
125            Ok(())
126        },
127    }
128}
129
130pub async fn execute_with_pool(
131    command: ToolsCommands,
132    db_ctx: &DatabaseContext,
133    config: &CliConfig,
134) -> Result<()> {
135    match command {
136        ToolsCommands::Stats(args) => {
137            let result = stats::execute_with_pool(args, db_ctx, config).await?;
138            render_result(&result);
139            Ok(())
140        },
141        ToolsCommands::List(args) => {
142            let result = list::execute_with_pool(args, db_ctx, config).await?;
143            render_result(&result);
144            Ok(())
145        },
146        ToolsCommands::Trends(args) => {
147            let result = trends::execute_with_pool(args, db_ctx, config).await?;
148            render_result(&result);
149            Ok(())
150        },
151        ToolsCommands::Show(args) => {
152            let result = show::execute_with_pool(args, db_ctx, config).await?;
153            render_result(&result);
154            Ok(())
155        },
156    }
157}