systemprompt_logging/trace/
service.rs1use anyhow::Result;
2use chrono::{DateTime, Utc};
3use sqlx::PgPool;
4use std::sync::Arc;
5use systemprompt_identifiers::TaskId;
6
7use crate::models::LogEntry;
8
9use super::models::{
10 AiRequestDetail, AiRequestListItem, AiRequestStats, AiRequestSummary, AuditLookupResult,
11 AuditToolCallRow, ConversationMessage, ExecutionStepSummary, LevelCount, LinkedMcpCall,
12 LogSearchItem, LogTimeRange, McpExecutionSummary, ModuleCount, ToolExecutionFilter,
13 ToolExecutionItem, TraceEvent, TraceListFilter, TraceListItem,
14};
15use super::{
16 audit_queries, list_queries, log_lookup_queries, log_search_queries, log_summary_queries,
17 queries, request_queries, tool_queries,
18};
19
20#[derive(Debug, Clone)]
21pub struct TraceQueryService {
22 pool: Arc<PgPool>,
23}
24
25impl TraceQueryService {
26 pub const fn new(pool: Arc<PgPool>) -> Self {
27 Self { pool }
28 }
29
30 pub async fn get_log_events(&self, trace_id: &str) -> Result<Vec<TraceEvent>> {
31 queries::fetch_log_events(&self.pool, trace_id).await
32 }
33
34 pub async fn get_ai_request_summary(&self, trace_id: &str) -> Result<AiRequestSummary> {
35 queries::fetch_ai_request_summary(&self.pool, trace_id).await
36 }
37
38 pub async fn get_ai_request_events(&self, trace_id: &str) -> Result<Vec<TraceEvent>> {
39 queries::fetch_ai_request_events(&self.pool, trace_id).await
40 }
41
42 pub async fn get_mcp_execution_summary(&self, trace_id: &str) -> Result<McpExecutionSummary> {
43 queries::fetch_mcp_execution_summary(&self.pool, trace_id).await
44 }
45
46 pub async fn get_mcp_execution_events(&self, trace_id: &str) -> Result<Vec<TraceEvent>> {
47 queries::fetch_mcp_execution_events(&self.pool, trace_id).await
48 }
49
50 pub async fn get_task_id(&self, trace_id: &str) -> Result<Option<TaskId>> {
51 Ok(queries::fetch_task_id_for_trace(&self.pool, trace_id)
52 .await?
53 .map(TaskId::from))
54 }
55
56 pub async fn get_execution_step_summary(&self, trace_id: &str) -> Result<ExecutionStepSummary> {
57 queries::fetch_execution_step_summary(&self.pool, trace_id).await
58 }
59
60 pub async fn get_execution_step_events(&self, trace_id: &str) -> Result<Vec<TraceEvent>> {
61 queries::fetch_execution_step_events(&self.pool, trace_id).await
62 }
63
64 pub async fn get_all_trace_data(
65 &self,
66 trace_id: &str,
67 ) -> Result<(
68 Vec<TraceEvent>,
69 Vec<TraceEvent>,
70 Vec<TraceEvent>,
71 Vec<TraceEvent>,
72 AiRequestSummary,
73 McpExecutionSummary,
74 ExecutionStepSummary,
75 Option<TaskId>,
76 )> {
77 tokio::try_join!(
78 self.get_log_events(trace_id),
79 self.get_ai_request_events(trace_id),
80 self.get_mcp_execution_events(trace_id),
81 self.get_execution_step_events(trace_id),
82 self.get_ai_request_summary(trace_id),
83 self.get_mcp_execution_summary(trace_id),
84 self.get_execution_step_summary(trace_id),
85 self.get_task_id(trace_id),
86 )
87 }
88
89 pub async fn list_traces(&self, filter: &TraceListFilter) -> Result<Vec<TraceListItem>> {
90 list_queries::list_traces(&self.pool, filter).await
91 }
92
93 pub async fn list_tool_executions(
94 &self,
95 filter: &ToolExecutionFilter,
96 ) -> Result<Vec<ToolExecutionItem>> {
97 tool_queries::list_tool_executions(&self.pool, filter).await
98 }
99
100 pub async fn search_logs(
101 &self,
102 pattern: &str,
103 since: Option<DateTime<Utc>>,
104 level: Option<&str>,
105 limit: i64,
106 ) -> Result<Vec<LogSearchItem>> {
107 log_search_queries::search_logs(&self.pool, pattern, since, level, limit).await
108 }
109
110 pub async fn search_tool_executions(
111 &self,
112 pattern: &str,
113 since: Option<DateTime<Utc>>,
114 limit: i64,
115 ) -> Result<Vec<ToolExecutionItem>> {
116 log_search_queries::search_tool_executions(&self.pool, pattern, since, limit).await
117 }
118
119 pub async fn list_ai_requests(
120 &self,
121 since: Option<DateTime<Utc>>,
122 model: Option<&str>,
123 provider: Option<&str>,
124 limit: i64,
125 ) -> Result<Vec<AiRequestListItem>> {
126 request_queries::list_ai_requests(&self.pool, since, model, provider, limit).await
127 }
128
129 pub async fn get_ai_request_stats(
130 &self,
131 since: Option<DateTime<Utc>>,
132 ) -> Result<AiRequestStats> {
133 request_queries::get_ai_request_stats(&self.pool, since).await
134 }
135
136 pub async fn find_ai_request_detail(&self, id: &str) -> Result<Option<AiRequestDetail>> {
137 request_queries::find_ai_request_detail(&self.pool, id).await
138 }
139
140 pub async fn find_ai_request_for_audit(&self, id: &str) -> Result<Option<AuditLookupResult>> {
141 audit_queries::find_ai_request_for_audit(&self.pool, id).await
142 }
143
144 pub async fn list_audit_messages(&self, request_id: &str) -> Result<Vec<ConversationMessage>> {
145 audit_queries::list_audit_messages(&self.pool, request_id).await
146 }
147
148 pub async fn list_audit_tool_calls(&self, request_id: &str) -> Result<Vec<AuditToolCallRow>> {
149 audit_queries::list_audit_tool_calls(&self.pool, request_id).await
150 }
151
152 pub async fn list_linked_mcp_calls(&self, request_id: &str) -> Result<Vec<LinkedMcpCall>> {
153 audit_queries::list_linked_mcp_calls(&self.pool, request_id).await
154 }
155
156 pub async fn find_log_by_id(&self, id: &str) -> Result<Option<LogEntry>> {
157 log_lookup_queries::find_log_by_id(&self.pool, id).await
158 }
159
160 pub async fn find_log_by_partial_id(&self, id_prefix: &str) -> Result<Option<LogEntry>> {
161 log_lookup_queries::find_log_by_partial_id(&self.pool, id_prefix).await
162 }
163
164 pub async fn find_logs_by_trace_id(&self, trace_id: &str) -> Result<Vec<LogEntry>> {
165 log_lookup_queries::find_logs_by_trace_id(&self.pool, trace_id).await
166 }
167
168 pub async fn list_logs_filtered(
169 &self,
170 since: Option<DateTime<Utc>>,
171 level: Option<&str>,
172 limit: i64,
173 ) -> Result<Vec<LogEntry>> {
174 log_lookup_queries::list_logs_filtered(&self.pool, since, level, limit).await
175 }
176
177 pub async fn count_logs_by_level(
178 &self,
179 since: Option<DateTime<Utc>>,
180 ) -> Result<Vec<LevelCount>> {
181 log_summary_queries::count_logs_by_level(&self.pool, since).await
182 }
183
184 pub async fn top_modules(
185 &self,
186 since: Option<DateTime<Utc>>,
187 limit: i64,
188 ) -> Result<Vec<ModuleCount>> {
189 log_summary_queries::top_modules(&self.pool, since, limit).await
190 }
191
192 pub async fn log_time_range(&self, since: Option<DateTime<Utc>>) -> Result<LogTimeRange> {
193 log_summary_queries::log_time_range(&self.pool, since).await
194 }
195
196 pub async fn total_log_count(&self) -> Result<i64> {
197 log_summary_queries::total_log_count(&self.pool).await
198 }
199}