systemprompt_cli/commands/analytics/tools/
mod.rs1mod 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}