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