Skip to main content

systemprompt_runtime/trace/repository/
tool.rs

1//! Tool-call rows for trace views.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use systemprompt_identifiers::{McpServerId, McpToolName, TraceId};
7
8use super::{Result, TraceRepository};
9use crate::trace::models::{ToolExecutionFilter, ToolExecutionItem};
10
11impl TraceRepository {
12    pub async fn list_tool_executions(
13        &self,
14        filter: &ToolExecutionFilter,
15    ) -> Result<Vec<ToolExecutionItem>> {
16        let rows = sqlx::query!(
17            r#"
18        SELECT
19            started_at as "timestamp!",
20            trace_id as "trace_id!: TraceId",
21            tool_name as "tool_name!",
22            server_name,
23            status as "status!",
24            execution_time_ms
25        FROM mcp_tool_executions
26        WHERE ($1::timestamptz IS NULL OR started_at >= $1)
27          AND ($2::text IS NULL OR tool_name ILIKE $2)
28          AND ($3::text IS NULL OR server_name ILIKE $3)
29          AND ($4::text IS NULL OR status = $4)
30        ORDER BY started_at DESC
31        LIMIT $5
32        "#,
33            filter.since,
34            filter.name.as_deref(),
35            filter.server.as_deref(),
36            filter.status.as_deref(),
37            filter.limit
38        )
39        .fetch_all(&*self.pool)
40        .await?;
41
42        Ok(rows
43            .into_iter()
44            .map(|r| ToolExecutionItem {
45                timestamp: r.timestamp,
46                trace_id: r.trace_id,
47                tool_name: McpToolName::new(r.tool_name),
48                server_name: Some(McpServerId::new(r.server_name)),
49                status: r.status,
50                execution_time_ms: r.execution_time_ms,
51            })
52            .collect())
53    }
54}