quantrs2_device/performance_analytics_dashboard/
mod.rs

1//! Performance Analytics Dashboard
2//!
3//! This module has been refactored from a monolithic 3,092-line file into a clean,
4//! modular architecture to eliminate configuration explosion and improve maintainability.
5//!
6//! ## Module Structure
7//!
8//! - `config`: Configuration management (dashboard, analytics, visualization settings)
9//! - `analytics`: Analytics engines (statistical, trend, anomaly detection, prediction)
10//! - `alerting`: Alert management and notification systems
11//! - `data`: Data collection, storage, and quality monitoring
12//! - `visualization`: Dashboard rendering and chart generation
13//! - `session`: User session and permission management
14//!
15//! ## Key Improvements
16//!
17//! - **Configuration Organization**: Massive config structs organized into logical modules
18//! - **Separation of Concerns**: Each module handles a specific dashboard aspect
19//! - **Maintainability**: ~400-500 lines per module vs. 3,092 lines in single file
20//! - **Testability**: Independent testing of analytics engines and components
21//! - **Extensibility**: Easy to add new analytics or visualization features
22
23use std::collections::{BTreeMap, HashMap, VecDeque};
24use std::sync::{Arc, Mutex, RwLock};
25use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
26
27// Import specific types to avoid naming conflicts
28use quantrs2_circuit::prelude::{
29    PerformanceAnalyzer,
30    PerformanceSnapshot,
31    PerformanceSummary,
32    ProfilerConfig as ProfilerConfiguration,
33    // Avoid importing RealtimeMetrics, AnomalyDetectionAlgorithm, StorageConfig, StorageBackend
34    // to prevent conflicts with local types
35    ProfilingReport,
36    ProfilingSession,
37    QuantumProfiler,
38};
39use quantrs2_core::{
40    error::{QuantRS2Error, QuantRS2Result},
41    gate::GateOp,
42    qubit::QubitId,
43};
44
45// SciRS2 dependencies for advanced analytics
46#[cfg(feature = "scirs2")]
47use scirs2_graph::{
48    betweenness_centrality, closeness_centrality, dijkstra_path, minimum_spanning_tree,
49    strongly_connected_components, Graph,
50};
51#[cfg(feature = "scirs2")]
52use scirs2_linalg::{
53    cholesky, det, eig, inv, matrix_norm, prelude::*, qr, svd, trace, LinalgError, LinalgResult,
54};
55#[cfg(feature = "scirs2")]
56use scirs2_optimize::{minimize, OptimizeResult};
57#[cfg(feature = "scirs2")]
58use scirs2_stats::{
59    corrcoef,
60    distributions::{chi2, exponential, gamma, norm},
61    ks_2samp, mean, pearsonr, shapiro_wilk, spearmanr, std, ttest_1samp, ttest_ind, var,
62    Alternative, TTestResult,
63};
64
65// Fallback implementations when SciRS2 is not available
66#[cfg(not(feature = "scirs2"))]
67mod fallback_scirs2 {
68    use scirs2_core::ndarray::{Array1, Array2, ArrayView1, ArrayView2};
69
70    pub fn mean(_data: &ArrayView1<f64>) -> Result<f64, String> {
71        Ok(0.0)
72    }
73    pub fn std(_data: &ArrayView1<f64>, _ddof: i32) -> Result<f64, String> {
74        Ok(1.0)
75    }
76    pub fn pearsonr(
77        _x: &ArrayView1<f64>,
78        _y: &ArrayView1<f64>,
79        _alt: &str,
80    ) -> Result<(f64, f64), String> {
81        Ok((0.0, 0.5))
82    }
83    pub fn trace(_matrix: &ArrayView2<f64>) -> Result<f64, String> {
84        Ok(1.0)
85    }
86    pub fn inv(_matrix: &ArrayView2<f64>) -> Result<Array2<f64>, String> {
87        Ok(Array2::eye(2))
88    }
89
90    pub struct OptimizeResult {
91        pub x: Array1<f64>,
92        pub fun: f64,
93        pub success: bool,
94        pub nit: usize,
95        pub nfev: usize,
96        pub message: String,
97    }
98
99    pub fn minimize(
100        _func: fn(&Array1<f64>) -> f64,
101        _x0: &Array1<f64>,
102        _method: &str,
103    ) -> Result<OptimizeResult, String> {
104        Ok(OptimizeResult {
105            x: Array1::zeros(2),
106            fun: 0.0,
107            success: true,
108            nit: 0,
109            nfev: 0,
110            message: "Fallback optimization".to_string(),
111        })
112    }
113}
114
115#[cfg(not(feature = "scirs2"))]
116use fallback_scirs2::*;
117
118use scirs2_core::ndarray::{s, Array1, Array2, Array3, Array4, ArrayView1, ArrayView2, Axis};
119use scirs2_core::Complex64;
120use scirs2_core::random::prelude::*;
121use serde::{Deserialize, Serialize};
122use tokio::sync::{broadcast, mpsc};
123
124use crate::{
125    adaptive_compilation::AdaptiveCompilationConfig,
126    backend_traits::{query_backend_capabilities, BackendCapabilities},
127    calibration::{CalibrationManager, DeviceCalibration},
128    integrated_device_manager::{
129        IntegratedExecutionResult, IntegratedQuantumDeviceManager, PerformanceAnalytics,
130    },
131    ml_optimization::MLOptimizationConfig,
132    topology::HardwareTopology,
133    CircuitResult, DeviceError, DeviceResult,
134};
135
136// Module declarations
137pub mod alerting;
138pub mod analytics;
139pub mod config;
140pub mod data;
141pub mod session;
142pub mod visualization;
143
144// Re-exports for backward compatibility
145pub use alerting::{AlertManager, NotificationDispatcher}; // Specific imports to avoid ActiveAlert conflict
146pub use analytics::{AnomalyDetector, PerformancePredictor, StatisticalAnalyzer, TrendAnalyzer}; // Specific imports to avoid Anomaly conflict
147pub use config::*;
148pub use data::*; // Keep data::Anomaly and data::ActiveAlert as primary
149pub use session::*;
150pub use visualization::*;
151
152/// Main Performance Analytics Dashboard
153pub struct PerformanceAnalyticsDashboard {
154    config: PerformanceDashboardConfig,
155    integrated_manager: Option<Arc<IntegratedQuantumDeviceManager>>,
156    ml_engine: Option<Arc<Mutex<MLOptimizationConfig>>>,
157    compilation_pipeline: Option<Arc<AdaptiveCompilationConfig>>,
158
159    // Data storage and caching
160    realtime_data: Arc<RwLock<RealtimeMetrics>>,
161    historical_data: Arc<RwLock<HistoricalData>>,
162    statistical_cache: Arc<Mutex<StatisticalAnalysisResults>>,
163    prediction_cache: Arc<Mutex<PerformancePredictions>>,
164    alert_manager: Arc<Mutex<AlertManager>>,
165
166    // Analytics engines
167    statistical_analyzer: Arc<Mutex<StatisticalAnalyzer>>,
168    trend_analyzer: Arc<Mutex<TrendAnalyzer>>,
169    anomaly_detector: Arc<Mutex<AnomalyDetector>>,
170    predictor: Arc<Mutex<PerformancePredictor>>,
171
172    // Communication channels
173    event_sender: broadcast::Sender<DashboardEvent>,
174    data_collector: Arc<Mutex<DataCollector>>,
175
176    // State management
177    dashboard_state: Arc<RwLock<DashboardState>>,
178    user_sessions: Arc<Mutex<HashMap<String, UserSession>>>,
179}
180
181/// Dashboard event types
182#[derive(Debug, Clone)]
183pub enum DashboardEvent {
184    MetricsUpdated(RealtimeMetrics),
185    AlertTriggered(ActiveAlert),
186    AlertResolved(String),
187    AnomalyDetected(Anomaly),
188    PredictionUpdated(PerformancePredictions),
189    UserAction(UserAction),
190    SystemStatusChanged(SystemStatus),
191}
192
193/// Dashboard state management
194#[derive(Debug, Clone)]
195pub struct DashboardState {
196    pub current_view: DashboardView,
197    pub filters: Vec<DataFilter>,
198    pub time_range: TimeRange,
199    pub aggregation_level: AggregationLevel,
200    pub refresh_enabled: bool,
201    pub last_update: SystemTime,
202}
203
204/// Dashboard view types
205#[derive(Debug, Clone, PartialEq)]
206pub enum DashboardView {
207    Overview,
208    RealTimeMetrics,
209    HistoricalAnalysis,
210    PredictiveAnalytics,
211    Alerts,
212    CustomView(String),
213}
214
215/// Data filter for queries
216#[derive(Debug, Clone)]
217pub struct DataFilter {
218    pub field: String,
219    pub operator: FilterOperator,
220    pub value: FilterValue,
221}
222
223/// Filter operators
224#[derive(Debug, Clone, PartialEq)]
225pub enum FilterOperator {
226    Equals,
227    NotEquals,
228    GreaterThan,
229    LessThan,
230    Contains,
231    StartsWith,
232    EndsWith,
233    InRange,
234}
235
236/// Filter value types
237#[derive(Debug, Clone)]
238pub enum FilterValue {
239    String(String),
240    Number(f64),
241    Boolean(bool),
242    Range(f64, f64),
243    List(Vec<String>),
244}
245
246/// Time range specification
247#[derive(Debug, Clone)]
248pub struct TimeRange {
249    pub start: SystemTime,
250    pub end: SystemTime,
251}
252
253/// User action tracking
254#[derive(Debug, Clone)]
255pub struct UserAction {
256    pub user_id: String,
257    pub action_type: ActionType,
258    pub timestamp: SystemTime,
259    pub details: HashMap<String, String>,
260}
261
262/// Action types
263#[derive(Debug, Clone, PartialEq)]
264pub enum ActionType {
265    ViewChange,
266    FilterApplied,
267    ExportRequested,
268    AlertAcknowledged,
269    ConfigurationChanged,
270    CustomQuery,
271}
272
273/// System status
274#[derive(Debug, Clone, PartialEq)]
275pub enum SystemStatus {
276    Healthy,
277    Warning,
278    Error,
279    Maintenance,
280    Unknown,
281}
282
283impl PerformanceAnalyticsDashboard {
284    /// Create a new performance analytics dashboard
285    pub fn new(config: PerformanceDashboardConfig) -> DeviceResult<Self> {
286        let (event_sender, _) = broadcast::channel(1000);
287
288        Ok(Self {
289            config: config.clone(),
290            integrated_manager: None,
291            ml_engine: None,
292            compilation_pipeline: None,
293            realtime_data: Arc::new(RwLock::new(RealtimeMetrics::new())),
294            historical_data: Arc::new(RwLock::new(HistoricalData::new())),
295            statistical_cache: Arc::new(Mutex::new(StatisticalAnalysisResults::new())),
296            prediction_cache: Arc::new(Mutex::new(PerformancePredictions::new())),
297            alert_manager: Arc::new(Mutex::new(AlertManager::new(config.alert_config.clone()))),
298            statistical_analyzer: Arc::new(Mutex::new(StatisticalAnalyzer::new(
299                config.analytics_config.clone(),
300            ))),
301            trend_analyzer: Arc::new(Mutex::new(TrendAnalyzer::new(
302                config.analytics_config.clone(),
303            ))),
304            anomaly_detector: Arc::new(Mutex::new(AnomalyDetector::new(
305                config.analytics_config.clone(),
306            ))),
307            predictor: Arc::new(Mutex::new(PerformancePredictor::new(
308                config.prediction_config.clone(),
309            ))),
310            event_sender,
311            data_collector: Arc::new(Mutex::new(DataCollector::new(config.clone()))),
312            dashboard_state: Arc::new(RwLock::new(DashboardState::default())),
313            user_sessions: Arc::new(Mutex::new(HashMap::new())),
314        })
315    }
316
317    /// Initialize dashboard with device manager
318    pub fn with_device_manager(mut self, manager: Arc<IntegratedQuantumDeviceManager>) -> Self {
319        self.integrated_manager = Some(manager);
320        self
321    }
322
323    /// Initialize dashboard with ML optimization engine
324    pub fn with_ml_engine(mut self, engine: Arc<Mutex<MLOptimizationConfig>>) -> Self {
325        self.ml_engine = Some(engine);
326        self
327    }
328
329    /// Initialize dashboard with compilation pipeline
330    pub fn with_compilation_pipeline(mut self, pipeline: Arc<AdaptiveCompilationConfig>) -> Self {
331        self.compilation_pipeline = Some(pipeline);
332        self
333    }
334
335    /// Start the dashboard and begin data collection
336    pub async fn start(&self) -> DeviceResult<()> {
337        // Start data collection
338        let collector = self.data_collector.clone();
339        let mut collector_guard = collector.lock().unwrap();
340        collector_guard.start_collection().await?;
341        drop(collector_guard);
342
343        // Start analytics engines
344        self.start_analytics_engines().await?;
345
346        // Start alert monitoring
347        let alert_manager = self.alert_manager.clone();
348        let mut alert_guard = alert_manager.lock().unwrap();
349        alert_guard.start_monitoring().await?;
350        drop(alert_guard);
351
352        Ok(())
353    }
354
355    /// Stop the dashboard
356    pub async fn stop(&self) -> DeviceResult<()> {
357        // Stop data collection
358        let collector = self.data_collector.clone();
359        let mut collector_guard = collector.lock().unwrap();
360        collector_guard.stop_collection().await?;
361        drop(collector_guard);
362
363        // Stop analytics engines
364        self.stop_analytics_engines().await?;
365
366        // Stop alert monitoring
367        let alert_manager = self.alert_manager.clone();
368        let mut alert_guard = alert_manager.lock().unwrap();
369        alert_guard.stop_monitoring().await?;
370
371        Ok(())
372    }
373
374    // Private helper methods
375    async fn start_analytics_engines(&self) -> DeviceResult<()> {
376        // Implementation will be in the analytics module
377        Ok(())
378    }
379
380    async fn stop_analytics_engines(&self) -> DeviceResult<()> {
381        // Implementation will be in the analytics module
382        Ok(())
383    }
384}
385
386impl Default for DashboardState {
387    fn default() -> Self {
388        Self {
389            current_view: DashboardView::Overview,
390            filters: Vec::new(),
391            time_range: TimeRange {
392                start: SystemTime::now() - Duration::from_secs(3600), // Last hour
393                end: SystemTime::now(),
394            },
395            aggregation_level: AggregationLevel::Minute,
396            refresh_enabled: true,
397            last_update: SystemTime::now(),
398        }
399    }
400}
401
402impl TimeRange {
403    /// Create a new time range for the last N seconds
404    pub fn last_seconds(seconds: u64) -> Self {
405        let now = SystemTime::now();
406        Self {
407            start: now - Duration::from_secs(seconds),
408            end: now,
409        }
410    }
411
412    /// Create a new time range for the last N minutes
413    pub fn last_minutes(minutes: u64) -> Self {
414        Self::last_seconds(minutes * 60)
415    }
416
417    /// Create a new time range for the last N hours
418    pub fn last_hours(hours: u64) -> Self {
419        Self::last_seconds(hours * 3600)
420    }
421}