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::{Deserialize, 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 serializable)
32	#[serde(skip)]
33	pub last_updated:Instant,
34}
35
36impl PerformanceMetrics {
37	/// Create new performance metrics with default values
38	pub fn new() -> Self {
39		Self {
40			messages_per_second:0.0,
41			average_latency_ms:0.0,
42			peak_latency_ms:0.0,
43			compression_ratio:1.0,
44			pool_utilization:0.0,
45			memory_usage_bytes:0,
46			cpu_usage_percent:0.0,
47			total_messages:0,
48			failed_messages:0,
49			last_updated:Instant::now(),
50		}
51	}
52
53	/// Record a successful message with its latency
54	pub fn record_message(&mut self, latency:Duration) {
55		let latency_ms = latency.as_millis() as f64;
56
57		// Update average latency
58		if self.total_messages > 0 {
59			self.average_latency_ms =
60				(self.average_latency_ms * self.total_messages as f64 + latency_ms) / (self.total_messages + 1) as f64;
61		} else {
62			self.average_latency_ms = latency_ms;
63		}
64
65		// Update peak latency
66		if latency_ms > self.peak_latency_ms {
67			self.peak_latency_ms = latency_ms;
68		}
69
70		self.total_messages += 1;
71		self.last_updated = Instant::now();
72	}
73
74	/// Record a failed message
75	pub fn record_failure(&mut self) {
76		self.failed_messages += 1;
77		self.last_updated = Instant::now();
78	}
79
80	/// Calculate success rate (0.0 to 1.0)
81	pub fn success_rate(&self) -> f64 {
82		if self.total_messages == 0 {
83			return 1.0;
84		}
85		1.0 - (self.failed_messages as f64 / self.total_messages as f64)
86	}
87
88	/// Check if latency is within acceptable thresholds
89	pub fn is_latency_acceptable(&self, threshold_ms:f64) -> bool {
90		self.average_latency_ms <= threshold_ms && self.peak_latency_ms <= threshold_ms * 2.0
91	}
92
93	/// Get message success rate as percentage
94	pub fn success_rate_percent(&self) -> f64 { self.success_rate() * 100.0 }
95}
96
97impl Default for PerformanceMetrics {
98	fn default() -> Self { Self::new() }
99}
100
101/// Throughput metrics for measuring message flow
102#[derive(Debug, Clone)]
103pub struct ThroughputMetrics {
104	/// Messages received
105	pub messages_received:u64,
106	/// Messages sent
107	pub messages_sent:u64,
108	/// Bytes received
109	pub bytes_received:u64,
110	/// Bytes sent
111	pub bytes_sent:u64,
112	/// Start time of measurement period
113	pub start_time:Instant,
114}
115
116impl ThroughputMetrics {
117	/// Create new throughput metrics
118	pub fn new() -> Self {
119		Self {
120			messages_received:0,
121			messages_sent:0,
122			bytes_received:0,
123			bytes_sent:0,
124			start_time:Instant::now(),
125		}
126	}
127
128	/// Record a received message
129	pub fn record_received(&mut self, bytes:u64) {
130		self.messages_received += 1;
131		self.bytes_received += bytes;
132	}
133
134	/// Record a sent message
135	pub fn record_sent(&mut self, bytes:u64) {
136		self.messages_sent += 1;
137		self.bytes_sent += bytes;
138	}
139
140	/// Calculate messages per second received
141	pub fn messages_per_second_received(&self) -> f64 {
142		let elapsed = self.start_time.elapsed().as_secs_f64();
143		if elapsed > 0.0 { self.messages_received as f64 / elapsed } else { 0.0 }
144	}
145
146	/// Calculate messages per second sent
147	pub fn messages_per_second_sent(&self) -> f64 {
148		let elapsed = self.start_time.elapsed().as_secs_f64();
149		if elapsed > 0.0 { self.messages_sent as f64 / elapsed } else { 0.0 }
150	}
151
152	/// Calculate bytes per second received
153	pub fn bytes_per_second_received(&self) -> f64 {
154		let elapsed = self.start_time.elapsed().as_secs_f64();
155		if elapsed > 0.0 { self.bytes_received as f64 / elapsed } else { 0.0 }
156	}
157
158	/// Calculate bytes per second sent
159	pub fn bytes_per_second_sent(&self) -> f64 {
160		let elapsed = self.start_time.elapsed().as_secs_f64();
161		if elapsed > 0.0 { self.bytes_sent as f64 / elapsed } else { 0.0 }
162	}
163}
164
165impl Default for ThroughputMetrics {
166	fn default() -> Self { Self::new() }
167}