trustformers_debug/streaming_debugger/
functions.rs1use super::types::*;
6use anyhow::Result;
7use std::sync::Arc;
8use tracing::info;
9impl crate::DebugSession {
11 pub async fn enable_streaming(
13 &mut self,
14 config: StreamingDebugConfig,
15 ) -> Result<Arc<StreamingDebugger>> {
16 let streaming_debugger = Arc::new(StreamingDebugger::new(config));
17 streaming_debugger.start().await?;
18 info!("Enabled streaming for debug session {}", self.id());
19 Ok(streaming_debugger)
20 }
21}
22#[macro_export]
24macro_rules! stream_tensor {
25 ($streamer:expr, $session_id:expr, $tensor:expr, $name:expr) => {{
26 let tensor_id = uuid::Uuid::new_v4();
27 let shape = $tensor.shape().to_vec();
28 let values: Vec<f64> = $tensor.iter().map(|&x| x.into()).collect();
29 $streamer
30 .send_tensor_data($session_id, tensor_id, $name.to_string(), shape, values)
31 .await
32 }};
33}
34#[macro_export]
35macro_rules! stream_gradients {
36 ($streamer:expr, $session_id:expr, $layer_name:expr, $gradients:expr) => {{
37 let gradient_values: Vec<f64> = $gradients.iter().map(|&x| x.into()).collect();
38 $streamer
39 .send_gradient_flow($session_id, $layer_name.to_string(), &gradient_values)
40 .await
41 }};
42}
43#[macro_export]
44macro_rules! stream_anomaly {
45 (
46 $streamer:expr, $session_id:expr, $anomaly_type:expr, $severity:expr,
47 $description:expr
48 ) => {{
49 $streamer
50 .send_anomaly_detected(
51 $session_id,
52 $anomaly_type,
53 $severity,
54 $description.to_string(),
55 0.95,
56 vec![],
57 )
58 .await
59 }};
60}
61#[cfg(test)]
62mod tests {
63 use super::*;
64 use std::collections::HashMap;
65 use std::time::{Duration, SystemTime};
66
67 use uuid::Uuid;
68 #[tokio::test]
69 async fn test_streaming_debugger_creation() {
70 let config = StreamingDebugConfig::default();
71 let debugger = StreamingDebugger::new(config);
72 assert!(!*debugger.is_running.read().await);
73 }
74 #[tokio::test(flavor = "multi_thread")]
75 async fn test_start_stop_streaming() {
76 let config = StreamingDebugConfig {
77 stream_interval_ms: 50,
78 ..Default::default()
79 };
80 let debugger = StreamingDebugger::new(config);
81 let test_result = tokio::time::timeout(Duration::from_secs(3), async {
82 assert!(debugger.start().await.is_ok());
83 assert!(*debugger.is_running.read().await);
84 tokio::time::sleep(Duration::from_millis(50)).await;
85 assert!(debugger.stop().await.is_ok());
86 assert!(!*debugger.is_running.read().await);
87 tokio::time::sleep(Duration::from_millis(100)).await;
88 Ok::<(), anyhow::Error>(())
89 })
90 .await;
91 assert!(test_result.is_ok(), "Test timed out");
92 assert!(test_result.expect("test should not time out").is_ok());
93 }
94 #[tokio::test(flavor = "multi_thread")]
95 async fn test_subscription() {
96 let config = StreamingDebugConfig {
97 stream_interval_ms: 50,
98 ..Default::default()
99 };
100 let debugger = StreamingDebugger::new(config);
101 let test_result = tokio::time::timeout(Duration::from_secs(3), async {
102 debugger.start().await.expect("start should succeed");
103 let subscription = debugger
104 .subscribe(
105 "test_subscriber".to_string(),
106 StreamFormat::Json,
107 StreamFilter::default(),
108 )
109 .await
110 .expect("subscribe should succeed");
111 assert_eq!(debugger.get_subscribers().await.len(), 1);
112 debugger
113 .unsubscribe(subscription.subscriber_id())
114 .await
115 .expect("unsubscribe should succeed");
116 assert_eq!(debugger.get_subscribers().await.len(), 0);
117 debugger.stop().await.expect("stop should succeed");
118 tokio::time::sleep(Duration::from_millis(100)).await;
119 Ok::<(), anyhow::Error>(())
120 })
121 .await;
122 assert!(test_result.is_ok(), "Test timed out");
123 assert!(test_result.expect("test should not time out").is_ok());
124 }
125 #[tokio::test]
126 async fn test_tensor_statistics() {
127 let config = StreamingDebugConfig::default();
128 let debugger = StreamingDebugger::new(config);
129 let values = vec![1.0, 2.0, 3.0, 4.0, 5.0];
130 let stats = debugger.compute_tensor_statistics(&values);
131 assert_eq!(stats.mean, 3.0);
132 assert!(stats.std > 0.0);
133 assert_eq!(stats.min, 1.0);
134 assert_eq!(stats.max, 5.0);
135 assert_eq!(stats.zero_count, 0);
136 }
137 #[tokio::test]
138 async fn test_gradient_statistics() {
139 let config = StreamingDebugConfig::default();
140 let debugger = StreamingDebugger::new(config);
141 let gradients = vec![0.1, -0.2, 0.3, -0.1, 0.0];
142 let stats = debugger.compute_gradient_statistics(&gradients);
143 assert!(stats.l1_norm > 0.0);
144 assert!(stats.l2_norm > 0.0);
145 assert_eq!(stats.max_grad, 0.3);
146 assert_eq!(stats.min_grad, -0.2);
147 }
148 #[tokio::test]
149 async fn test_event_filtering() {
150 let session_id1 = Uuid::new_v4();
151 let session_id2 = Uuid::new_v4();
152 let filter = StreamFilter {
153 session_ids: Some(vec![session_id1]),
154 event_types: Some(vec!["TensorData".to_string()]),
155 min_severity: None,
156 time_range: None,
157 custom_filters: HashMap::new(),
158 };
159 let matching_event = StreamEvent::TensorData {
160 session_id: session_id1,
161 tensor_id: Uuid::new_v4(),
162 name: "test".to_string(),
163 shape: vec![2, 2],
164 values: vec![1.0, 2.0, 3.0, 4.0],
165 statistics: TensorStatistics {
166 mean: 2.5,
167 std: 1.29,
168 min: 1.0,
169 max: 4.0,
170 nan_count: 0,
171 inf_count: 0,
172 zero_count: 0,
173 sparsity: 0.0,
174 },
175 timestamp: SystemTime::now(),
176 };
177 let non_matching_event = StreamEvent::TensorData {
178 session_id: session_id2,
179 tensor_id: Uuid::new_v4(),
180 name: "test".to_string(),
181 shape: vec![2, 2],
182 values: vec![1.0, 2.0, 3.0, 4.0],
183 statistics: TensorStatistics {
184 mean: 2.5,
185 std: 1.29,
186 min: 1.0,
187 max: 4.0,
188 nan_count: 0,
189 inf_count: 0,
190 zero_count: 0,
191 sparsity: 0.0,
192 },
193 timestamp: SystemTime::now(),
194 };
195 assert!(StreamSubscription::matches_filter(&matching_event, &filter));
196 assert!(!StreamSubscription::matches_filter(
197 &non_matching_event,
198 &filter
199 ));
200 }
201}
202pub trait AggregationRule {
204 fn aggregate(&self, events: &[StreamEvent]) -> Result<f64>;
205 fn rule_name(&self) -> &str;
206}
207#[cfg(test)]
208mod enhanced_tests {
209 use super::*;
210 use std::time::{Duration, Instant, SystemTime};
211 use uuid::Uuid;
212 #[tokio::test(flavor = "multi_thread")]
213 async fn test_enhanced_streaming_debugger() {
214 let base_config = StreamingDebugConfig {
215 stream_interval_ms: 50,
216 ..Default::default()
217 };
218 let adaptive_config = AdaptiveStreamingConfig {
219 monitoring_interval_ms: 500,
220 ..Default::default()
221 };
222 let aggregation_config = RealTimeAggregationConfig {
223 window_size_seconds: 1,
224 ..Default::default()
225 };
226 let buffering_config = IntelligentBufferingConfig::default();
227 let mut debugger = EnhancedStreamingDebugger::new(
228 base_config,
229 adaptive_config,
230 aggregation_config,
231 buffering_config,
232 );
233 let test_result = tokio::time::timeout(Duration::from_secs(5), async {
234 assert!(debugger.start_enhanced_streaming().await.is_ok());
235 tokio::time::sleep(Duration::from_millis(100)).await;
236 assert!(debugger.stop_enhanced_streaming().await.is_ok());
237 tokio::time::sleep(Duration::from_millis(200)).await;
238 Ok::<(), anyhow::Error>(())
239 })
240 .await;
241 assert!(test_result.is_ok(), "Test timed out");
242 assert!(test_result.expect("test should not time out").is_ok());
243 }
244 #[tokio::test]
245 async fn test_network_condition_monitor() {
246 let mut monitor = NetworkConditionMonitor::new();
247 monitor.update_conditions().await;
248 assert!(monitor.quality_score >= 0.0);
249 assert!(monitor.quality_score <= 1.0);
250 assert!(!monitor.history.is_empty());
251 }
252 #[test]
253 fn test_buffer_performance_predictor() {
254 let predictor = BufferPerformancePredictor {
255 performance_history: vec![
256 BufferPerformancePoint {
257 buffer_size: 500,
258 throughput: 100.0,
259 latency: 50.0,
260 memory_usage: 50000,
261 timestamp: Instant::now(),
262 },
263 BufferPerformancePoint {
264 buffer_size: 1000,
265 throughput: 150.0,
266 latency: 40.0,
267 memory_usage: 100000,
268 timestamp: Instant::now(),
269 },
270 ],
271 model_params: vec![],
272 accuracy: 0.8,
273 };
274 let optimal_size =
275 predictor.predict_optimal_size().expect("predict_optimal_size should succeed");
276 assert_eq!(optimal_size, 1000);
277 }
278 #[tokio::test]
279 async fn test_importance_scorer() {
280 let scorer = ImportanceScorer::new();
281 let critical_event = StreamEvent::AnomalyDetected {
282 session_id: Uuid::new_v4(),
283 anomaly_type: AnomalyType::GradientExplosion,
284 severity: AnomalySeverity::Critical,
285 description: "Critical gradient explosion".to_string(),
286 confidence: 0.95,
287 affected_components: vec!["layer1".to_string()],
288 timestamp: SystemTime::now(),
289 };
290 let low_event = StreamEvent::AnomalyDetected {
291 session_id: Uuid::new_v4(),
292 anomaly_type: AnomalyType::TrainingStagnation,
293 severity: AnomalySeverity::Low,
294 description: "Slow convergence detected".to_string(),
295 confidence: 0.6,
296 affected_components: vec!["layer2".to_string()],
297 timestamp: SystemTime::now(),
298 };
299 let critical_score = scorer
300 .calculate_importance(&critical_event)
301 .await
302 .expect("calculate_importance should succeed for critical event");
303 let low_score = scorer
304 .calculate_importance(&low_event)
305 .await
306 .expect("calculate_importance should succeed for low event");
307 assert!(critical_score > low_score);
308 }
309}