Skip to main content

Mountain/IPC/Common/
PerformanceMetrics.rs

1//! # Performance Metrics Tracking
2//!
3//! Provides performance measurement and tracking for IPC components.
4//! Used to monitor throughput, latency, and resource usage.
5
6use std::time::{Duration, Instant};
7
8use serde::Serialize;
9
10/// Performance metrics for IPC operations
11#[derive(Debug, Clone, Serialize)]
12pub struct PerformanceMetrics {
13	/// Messages per second (throughput)
14	pub messages_per_second:f64,
15	/// Average response time in milliseconds
16	pub average_latency_ms:f64,
17	/// Peak response time in milliseconds
18	pub peak_latency_ms:f64,
19	/// Compression ratio (compressed_size / original_size)
20	pub compression_ratio:f64,
21	/// Connection pool utilization (0.0 to 1.0)
22	pub pool_utilization:f64,
23	/// Memory usage in bytes
24	pub memory_usage_bytes:u64,
25	/// CPU usage as percentage (0.0 to 100.0)
26	pub cpu_usage_percent:f64,
27	/// Total messages processed
28	pub total_messages:u64,
29	/// Failed messages
30	pub failed_messages:u64,
31	/// Last update timestamp (skipped for serialization as Instant is not
32	/// serializable)
33	#[serde(skip)]
34	pub last_updated:Instant,
35}
36
37impl PerformanceMetrics {
38	/// Create new performance metrics with default values
39	pub fn new() -> Self {
40		Self {
41			messages_per_second:0.0,
42			average_latency_ms:0.0,
43			peak_latency_ms:0.0,
44			compression_ratio:1.0,
45			pool_utilization:0.0,
46			memory_usage_bytes:0,
47			cpu_usage_percent:0.0,
48			total_messages:0,
49			failed_messages:0,
50			last_updated:Instant::now(),
51		}
52	}
53
54	/// Record a successful message with its latency
55	pub fn record_message(&mut self, latency:Duration) {
56		let latency_ms = latency.as_millis() as f64;
57
58		// Update average latency
59		if self.total_messages > 0 {
60			self.average_latency_ms =
61				(self.average_latency_ms * self.total_messages as f64 + latency_ms) / (self.total_messages + 1) as f64;
62		} else {
63			self.average_latency_ms = latency_ms;
64		}
65
66		// Update peak latency
67		if latency_ms > self.peak_latency_ms {
68			self.peak_latency_ms = latency_ms;
69		}
70
71		self.total_messages += 1;
72		self.last_updated = Instant::now();
73	}
74
75	/// Record a failed message
76	pub fn record_failure(&mut self) {
77		self.failed_messages += 1;
78		self.last_updated = Instant::now();
79	}
80
81	/// Calculate success rate (0.0 to 1.0)
82	pub fn success_rate(&self) -> f64 {
83		if self.total_messages == 0 {
84			return 1.0;
85		}
86		1.0 - (self.failed_messages as f64 / self.total_messages as f64)
87	}
88
89	/// Check if latency is within acceptable thresholds
90	pub fn is_latency_acceptable(&self, threshold_ms:f64) -> bool {
91		self.average_latency_ms <= threshold_ms && self.peak_latency_ms <= threshold_ms * 2.0
92	}
93
94	/// Get message success rate as percentage
95	pub fn success_rate_percent(&self) -> f64 { self.success_rate() * 100.0 }
96}
97
98impl Default for PerformanceMetrics {
99	fn default() -> Self { Self::new() }
100}
101
102/// Throughput metrics for measuring message flow
103#[derive(Debug, Clone)]
104pub struct ThroughputMetrics {
105	/// Messages received
106	pub messages_received:u64,
107	/// Messages sent
108	pub messages_sent:u64,
109	/// Bytes received
110	pub bytes_received:u64,
111	/// Bytes sent
112	pub bytes_sent:u64,
113	/// Start time of measurement period
114	pub start_time:Instant,
115}
116
117impl ThroughputMetrics {
118	/// Create new throughput metrics
119	pub fn new() -> Self {
120		Self {
121			messages_received:0,
122			messages_sent:0,
123			bytes_received:0,
124			bytes_sent:0,
125			start_time:Instant::now(),
126		}
127	}
128
129	/// Record a received message
130	pub fn record_received(&mut self, bytes:u64) {
131		self.messages_received += 1;
132		self.bytes_received += bytes;
133	}
134
135	/// Record a sent message
136	pub fn record_sent(&mut self, bytes:u64) {
137		self.messages_sent += 1;
138		self.bytes_sent += bytes;
139	}
140
141	/// Calculate messages per second received
142	pub fn messages_per_second_received(&self) -> f64 {
143		let elapsed = self.start_time.elapsed().as_secs_f64();
144		if elapsed > 0.0 { self.messages_received as f64 / elapsed } else { 0.0 }
145	}
146
147	/// Calculate messages per second sent
148	pub fn messages_per_second_sent(&self) -> f64 {
149		let elapsed = self.start_time.elapsed().as_secs_f64();
150		if elapsed > 0.0 { self.messages_sent as f64 / elapsed } else { 0.0 }
151	}
152
153	/// Calculate bytes per second received
154	pub fn bytes_per_second_received(&self) -> f64 {
155		let elapsed = self.start_time.elapsed().as_secs_f64();
156		if elapsed > 0.0 { self.bytes_received as f64 / elapsed } else { 0.0 }
157	}
158
159	/// Calculate bytes per second sent
160	pub fn bytes_per_second_sent(&self) -> f64 {
161		let elapsed = self.start_time.elapsed().as_secs_f64();
162		if elapsed > 0.0 { self.bytes_sent as f64 / elapsed } else { 0.0 }
163	}
164}
165
166impl Default for ThroughputMetrics {
167	fn default() -> Self { Self::new() }
168}