systemprompt_analytics/repository/tools/
list_queries.rs1use anyhow::Result;
2use chrono::{DateTime, Utc};
3
4use super::ToolAnalyticsRepository;
5use crate::models::cli::ToolListRow;
6
7impl ToolAnalyticsRepository {
8 #[allow(clippy::too_many_arguments)]
9 pub async fn list_tools(
10 &self,
11 start: DateTime<Utc>,
12 end: DateTime<Utc>,
13 limit: i64,
14 server_filter: Option<&str>,
15 sort_order: &str,
16 ) -> Result<Vec<ToolListRow>> {
17 if let Some(server) = server_filter {
18 let pattern = format!("%{}%", server);
19 self.list_tools_with_filter(start, end, limit, &pattern, sort_order)
20 .await
21 } else {
22 self.list_tools_unfiltered(start, end, limit, sort_order)
23 .await
24 }
25 }
26
27 #[allow(clippy::too_many_arguments)]
28 async fn list_tools_with_filter(
29 &self,
30 start: DateTime<Utc>,
31 end: DateTime<Utc>,
32 limit: i64,
33 pattern: &str,
34 sort_order: &str,
35 ) -> Result<Vec<ToolListRow>> {
36 match sort_order {
37 "success_rate" => sqlx::query_as!(
38 ToolListRow,
39 r#"
40 SELECT
41 tool_name as "tool_name!",
42 server_name as "server_name!",
43 COUNT(*)::bigint as "execution_count!",
44 COUNT(*) FILTER (WHERE status = 'success')::bigint as "success_count!",
45 COALESCE(AVG(execution_time_ms)::float8, 0) as "avg_time!",
46 MAX(created_at) as "last_used!"
47 FROM mcp_tool_executions
48 WHERE created_at >= $1 AND created_at < $2 AND server_name ILIKE $3
49 GROUP BY tool_name, server_name
50 ORDER BY CASE WHEN COUNT(*) > 0
51 THEN COUNT(*) FILTER (WHERE status = 'success')::float / COUNT(*)::float
52 ELSE 0 END DESC
53 LIMIT $4
54 "#,
55 start,
56 end,
57 pattern,
58 limit
59 )
60 .fetch_all(&*self.pool)
61 .await
62 .map_err(Into::into),
63 "avg_time" => sqlx::query_as!(
64 ToolListRow,
65 r#"
66 SELECT
67 tool_name as "tool_name!",
68 server_name as "server_name!",
69 COUNT(*)::bigint as "execution_count!",
70 COUNT(*) FILTER (WHERE status = 'success')::bigint as "success_count!",
71 COALESCE(AVG(execution_time_ms)::float8, 0) as "avg_time!",
72 MAX(created_at) as "last_used!"
73 FROM mcp_tool_executions
74 WHERE created_at >= $1 AND created_at < $2 AND server_name ILIKE $3
75 GROUP BY tool_name, server_name
76 ORDER BY COALESCE(AVG(execution_time_ms), 0) DESC
77 LIMIT $4
78 "#,
79 start,
80 end,
81 pattern,
82 limit
83 )
84 .fetch_all(&*self.pool)
85 .await
86 .map_err(Into::into),
87 _ => sqlx::query_as!(
88 ToolListRow,
89 r#"
90 SELECT
91 tool_name as "tool_name!",
92 server_name as "server_name!",
93 COUNT(*)::bigint as "execution_count!",
94 COUNT(*) FILTER (WHERE status = 'success')::bigint as "success_count!",
95 COALESCE(AVG(execution_time_ms)::float8, 0) as "avg_time!",
96 MAX(created_at) as "last_used!"
97 FROM mcp_tool_executions
98 WHERE created_at >= $1 AND created_at < $2 AND server_name ILIKE $3
99 GROUP BY tool_name, server_name
100 ORDER BY COUNT(*) DESC
101 LIMIT $4
102 "#,
103 start,
104 end,
105 pattern,
106 limit
107 )
108 .fetch_all(&*self.pool)
109 .await
110 .map_err(Into::into),
111 }
112 }
113
114 async fn list_tools_unfiltered(
115 &self,
116 start: DateTime<Utc>,
117 end: DateTime<Utc>,
118 limit: i64,
119 sort_order: &str,
120 ) -> Result<Vec<ToolListRow>> {
121 match sort_order {
122 "success_rate" => sqlx::query_as!(
123 ToolListRow,
124 r#"
125 SELECT
126 tool_name as "tool_name!",
127 server_name as "server_name!",
128 COUNT(*)::bigint as "execution_count!",
129 COUNT(*) FILTER (WHERE status = 'success')::bigint as "success_count!",
130 COALESCE(AVG(execution_time_ms)::float8, 0) as "avg_time!",
131 MAX(created_at) as "last_used!"
132 FROM mcp_tool_executions
133 WHERE created_at >= $1 AND created_at < $2
134 GROUP BY tool_name, server_name
135 ORDER BY CASE WHEN COUNT(*) > 0
136 THEN COUNT(*) FILTER (WHERE status = 'success')::float / COUNT(*)::float
137 ELSE 0 END DESC
138 LIMIT $3
139 "#,
140 start,
141 end,
142 limit
143 )
144 .fetch_all(&*self.pool)
145 .await
146 .map_err(Into::into),
147 "avg_time" => sqlx::query_as!(
148 ToolListRow,
149 r#"
150 SELECT
151 tool_name as "tool_name!",
152 server_name as "server_name!",
153 COUNT(*)::bigint as "execution_count!",
154 COUNT(*) FILTER (WHERE status = 'success')::bigint as "success_count!",
155 COALESCE(AVG(execution_time_ms)::float8, 0) as "avg_time!",
156 MAX(created_at) as "last_used!"
157 FROM mcp_tool_executions
158 WHERE created_at >= $1 AND created_at < $2
159 GROUP BY tool_name, server_name
160 ORDER BY COALESCE(AVG(execution_time_ms), 0) DESC
161 LIMIT $3
162 "#,
163 start,
164 end,
165 limit
166 )
167 .fetch_all(&*self.pool)
168 .await
169 .map_err(Into::into),
170 _ => sqlx::query_as!(
171 ToolListRow,
172 r#"
173 SELECT
174 tool_name as "tool_name!",
175 server_name as "server_name!",
176 COUNT(*)::bigint as "execution_count!",
177 COUNT(*) FILTER (WHERE status = 'success')::bigint as "success_count!",
178 COALESCE(AVG(execution_time_ms)::float8, 0) as "avg_time!",
179 MAX(created_at) as "last_used!"
180 FROM mcp_tool_executions
181 WHERE created_at >= $1 AND created_at < $2
182 GROUP BY tool_name, server_name
183 ORDER BY COUNT(*) DESC
184 LIMIT $3
185 "#,
186 start,
187 end,
188 limit
189 )
190 .fetch_all(&*self.pool)
191 .await
192 .map_err(Into::into),
193 }
194 }
195}