Skip to main content

things3_cli/mcp/middleware/
performance.rs

1//! Performance monitoring middleware
2
3use super::{McpMiddleware, MiddlewareContext, MiddlewareResult};
4use crate::mcp::{CallToolRequest, CallToolResult, McpResult};
5use std::time::Duration;
6
7pub struct PerformanceMiddleware {
8    slow_request_threshold: Duration,
9}
10
11impl PerformanceMiddleware {
12    /// Create a new performance middleware
13    #[must_use]
14    pub fn new(slow_request_threshold: Duration) -> Self {
15        Self {
16            slow_request_threshold,
17        }
18    }
19
20    /// Create with default threshold (1 second)
21    #[must_use]
22    pub fn create_default() -> Self {
23        Self::new(Duration::from_secs(1))
24    }
25
26    /// Create with custom threshold
27    #[must_use]
28    pub fn with_threshold(threshold: Duration) -> Self {
29        Self::new(threshold)
30    }
31}
32
33#[async_trait::async_trait]
34impl McpMiddleware for PerformanceMiddleware {
35    fn name(&self) -> &'static str {
36        "performance"
37    }
38
39    fn priority(&self) -> i32 {
40        200 // runs last — measures total wall time
41    }
42
43    async fn after_request(
44        &self,
45        request: &CallToolRequest,
46        _response: &mut CallToolResult,
47        context: &mut MiddlewareContext,
48    ) -> McpResult<MiddlewareResult> {
49        let elapsed = context.elapsed();
50
51        // Record performance metrics
52        context.set_metadata(
53            "duration_ms".to_string(),
54            serde_json::Value::Number(serde_json::Number::from(
55                u64::try_from(elapsed.as_millis()).unwrap_or(u64::MAX),
56            )),
57        );
58
59        context.set_metadata(
60            "is_slow".to_string(),
61            serde_json::Value::Bool(elapsed > self.slow_request_threshold),
62        );
63
64        // Log slow requests
65        if elapsed > self.slow_request_threshold {
66            println!(
67                "[PERF] Slow request detected: {} took {:?} (threshold: {:?})",
68                request.name, elapsed, self.slow_request_threshold
69            );
70        }
71
72        Ok(MiddlewareResult::Continue)
73    }
74}