pulseengine_mcp_monitoring/
collector.rs1use crate::{config::MonitoringConfig, metrics::ServerMetrics};
4use pulseengine_mcp_protocol::{Error, Request, Response};
5use std::sync::atomic::{AtomicU64, Ordering};
6use std::sync::Arc;
7use tokio::time::Instant;
8
9#[derive(Debug, Clone)]
11pub struct RequestContext {
12 pub request_id: uuid::Uuid,
13}
14
15pub struct MetricsCollector {
17 config: MonitoringConfig,
18 start_time: Instant,
19 request_count: Arc<AtomicU64>,
20 error_count: Arc<AtomicU64>,
21}
22
23impl MetricsCollector {
24 pub fn new(config: MonitoringConfig) -> Self {
25 Self {
26 config,
27 start_time: Instant::now(),
28 request_count: Arc::new(AtomicU64::new(0)),
29 error_count: Arc::new(AtomicU64::new(0)),
30 }
31 }
32
33 pub fn start_collection(&self) {
34 if self.config.enabled {
35 } else {
37 }
39 }
40
41 pub fn stop_collection(&self) {
42 }
44
45 pub fn process_request(
52 &self,
53 request: Request,
54 _context: &RequestContext,
55 ) -> Result<Request, Error> {
56 if self.config.enabled {
57 self.request_count.fetch_add(1, Ordering::Relaxed);
58 }
59 Ok(request)
60 }
61
62 pub fn process_response(
69 &self,
70 response: Response,
71 _context: &RequestContext,
72 ) -> Result<Response, Error> {
73 if self.config.enabled && response.error.is_some() {
74 self.error_count.fetch_add(1, Ordering::Relaxed);
75 }
76 Ok(response)
77 }
78
79 pub fn get_current_metrics(&self) -> ServerMetrics {
80 let uptime_seconds = self.start_time.elapsed().as_secs();
81 let requests_total = self.request_count.load(Ordering::Relaxed);
82 let errors_total = self.error_count.load(Ordering::Relaxed);
83
84 ServerMetrics {
85 requests_total,
86 requests_per_second: if uptime_seconds > 0 {
87 #[allow(clippy::cast_precision_loss)]
88 {
89 requests_total as f64 / uptime_seconds as f64
90 }
91 } else {
92 0.0
93 },
94 average_response_time_ms: 0.0, error_rate: if requests_total > 0 {
96 #[allow(clippy::cast_precision_loss)]
97 {
98 errors_total as f64 / requests_total as f64
99 }
100 } else {
101 0.0
102 },
103 active_connections: 0, memory_usage_bytes: 0, uptime_seconds,
106 }
107 }
108
109 pub fn get_uptime_seconds(&self) -> u64 {
110 self.start_time.elapsed().as_secs()
111 }
112}
113
114#[cfg(test)]
115#[path = "collector_tests.rs"]
116mod collector_tests;