1use crate::{
8 error::{QuantRS2Error, QuantRS2Result},
9 hardware_compilation::{HardwarePlatform, NativeGateType},
10 qubit::QubitId,
11};
12use scirs2_core::Complex64;
13use std::{
14 collections::{HashMap, HashSet, VecDeque},
15 fmt,
16 sync::{Arc, RwLock},
17 thread,
18 time::{Duration, SystemTime},
19};
20
21#[derive(Debug, Clone)]
23pub struct MonitoringConfig {
24 pub monitoring_interval: Duration,
26 pub data_retention_period: Duration,
28 pub alert_thresholds: AlertThresholds,
30 pub enabled_metrics: HashSet<MetricType>,
32 pub platform_configs: HashMap<HardwarePlatform, PlatformMonitoringConfig>,
34 pub export_settings: ExportSettings,
36}
37
38#[derive(Debug, Clone)]
40pub struct AlertThresholds {
41 pub max_gate_error_rate: f64,
43 pub max_readout_error_rate: f64,
45 pub min_coherence_time: Duration,
47 pub max_calibration_drift: f64,
49 pub max_temperature: f64,
51 pub max_queue_depth: usize,
53 pub max_execution_time: Duration,
55}
56
57#[derive(Debug, Clone)]
59pub struct PlatformMonitoringConfig {
60 pub platform: HardwarePlatform,
62 pub monitored_metrics: HashSet<MetricType>,
64 pub sampling_rates: HashMap<MetricType, Duration>,
66 pub custom_thresholds: HashMap<String, f64>,
68 pub connection_settings: HashMap<String, String>,
70}
71
72#[derive(Debug, Clone)]
74pub struct ExportSettings {
75 pub enable_export: bool,
77 pub export_formats: Vec<ExportFormat>,
79 pub export_destinations: Vec<ExportDestination>,
81 pub export_frequency: Duration,
83 pub compression_enabled: bool,
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
89pub enum ExportFormat {
90 JSON,
91 CSV,
92 Parquet,
93 InfluxDB,
94 Prometheus,
95 Custom,
96}
97
98#[derive(Debug, Clone)]
100pub enum ExportDestination {
101 File(String),
102 Database(DatabaseConfig),
103 Cloud(CloudConfig),
104 Stream(StreamConfig),
105}
106
107#[derive(Debug, Clone)]
109pub struct DatabaseConfig {
110 pub connection_string: String,
111 pub table_name: String,
112 pub credentials: HashMap<String, String>,
113}
114
115#[derive(Debug, Clone)]
117pub struct CloudConfig {
118 pub provider: String,
119 pub endpoint: String,
120 pub credentials: HashMap<String, String>,
121}
122
123#[derive(Debug, Clone)]
125pub struct StreamConfig {
126 pub stream_type: String,
127 pub endpoint: String,
128 pub topic: String,
129}
130
131#[derive(Debug, Clone, PartialEq, Eq, Hash)]
133pub enum MetricType {
134 GateErrorRate,
136 GateFidelity,
137 GateExecutionTime,
138 GateCalibrationDrift,
139
140 QubitCoherenceTime,
142 QubitReadoutError,
143 QubitTemperature,
144 QubitCrosstalk,
145
146 SystemUptime,
148 QueueDepth,
149 Throughput,
150 Latency,
151
152 EnvironmentalTemperature,
154 MagneticField,
155 Vibration,
156 ElectromagneticNoise,
157
158 CPUUsage,
160 MemoryUsage,
161 NetworkLatency,
162 StorageUsage,
163
164 Custom(String),
166}
167
168#[derive(Debug)]
170pub struct RealtimeMonitor {
171 config: MonitoringConfig,
173 collectors: Arc<RwLock<HashMap<HardwarePlatform, Box<dyn MetricCollector>>>>,
175 data_store: Arc<RwLock<RealtimeDataStore>>,
177 analytics_engine: Arc<RwLock<AnalyticsEngine>>,
179 alert_manager: Arc<RwLock<AlertManager>>,
181 optimization_advisor: Arc<RwLock<OptimizationAdvisor>>,
183 dashboard: Arc<RwLock<PerformanceDashboard>>,
185 export_manager: Arc<RwLock<ExportManager>>,
187 monitoring_status: Arc<RwLock<MonitoringStatus>>,
189}
190
191pub trait MetricCollector: std::fmt::Debug + Send + Sync {
193 fn collect_metrics(&self) -> QuantRS2Result<Vec<MetricMeasurement>>;
195
196 fn supported_metrics(&self) -> HashSet<MetricType>;
198
199 fn platform(&self) -> HardwarePlatform;
201
202 fn initialize(&mut self) -> QuantRS2Result<()>;
204
205 fn is_connected(&self) -> bool;
207
208 fn disconnect(&mut self) -> QuantRS2Result<()>;
210}
211
212#[derive(Debug, Clone)]
214pub struct MetricMeasurement {
215 pub metric_type: MetricType,
217 pub value: MetricValue,
219 pub timestamp: SystemTime,
221 pub qubit: Option<QubitId>,
223 pub gate_type: Option<NativeGateType>,
225 pub metadata: HashMap<String, String>,
227 pub uncertainty: Option<f64>,
229}
230
231#[derive(Debug, Clone)]
233pub enum MetricValue {
234 Float(f64),
235 Integer(i64),
236 Boolean(bool),
237 String(String),
238 Array(Vec<f64>),
239 Complex(Complex64),
240 Duration(Duration),
241}
242
243#[derive(Debug)]
245pub struct RealtimeDataStore {
246 time_series: HashMap<MetricType, VecDeque<MetricMeasurement>>,
248 aggregated_stats: HashMap<MetricType, AggregatedStats>,
250 retention_settings: HashMap<MetricType, Duration>,
252 current_data_size: usize,
254 max_data_size: usize,
256}
257
258#[derive(Debug, Clone)]
260pub struct AggregatedStats {
261 pub mean: f64,
263 pub std_dev: f64,
265 pub min: f64,
267 pub max: f64,
269 pub median: f64,
271 pub p95: f64,
273 pub p99: f64,
275 pub sample_count: usize,
277 pub last_updated: SystemTime,
279}
280
281#[derive(Debug)]
283pub struct AnalyticsEngine {
284 trend_analyzers: HashMap<MetricType, Box<dyn TrendAnalyzer>>,
286 anomaly_detectors: HashMap<MetricType, Box<dyn AnomalyDetector>>,
288 correlation_analyzers: Vec<Box<dyn CorrelationAnalyzer>>,
290 predictive_models: HashMap<MetricType, Box<dyn PredictiveModel>>,
292 analysis_cache: HashMap<String, AnalysisResult>,
294}
295
296pub trait TrendAnalyzer: std::fmt::Debug + Send + Sync {
298 fn analyze_trend(&self, data: &[MetricMeasurement]) -> QuantRS2Result<TrendAnalysis>;
300
301 fn name(&self) -> &str;
303}
304
305pub trait AnomalyDetector: std::fmt::Debug + Send + Sync {
307 fn detect_anomalies(&self, data: &[MetricMeasurement]) -> QuantRS2Result<Vec<Anomaly>>;
309
310 fn name(&self) -> &str;
312
313 fn confidence_threshold(&self) -> f64;
315}
316
317pub trait CorrelationAnalyzer: std::fmt::Debug + Send + Sync {
319 fn analyze_correlations(
321 &self,
322 data: &HashMap<MetricType, Vec<MetricMeasurement>>,
323 ) -> QuantRS2Result<Vec<Correlation>>;
324
325 fn name(&self) -> &str;
327}
328
329pub trait PredictiveModel: std::fmt::Debug + Send + Sync {
331 fn predict(
333 &self,
334 historical_data: &[MetricMeasurement],
335 horizon: Duration,
336 ) -> QuantRS2Result<Prediction>;
337
338 fn update(&mut self, new_data: &[MetricMeasurement]) -> QuantRS2Result<()>;
340
341 fn name(&self) -> &str;
343
344 fn accuracy(&self) -> f64;
346}
347
348#[derive(Debug, Clone)]
350pub struct TrendAnalysis {
351 pub direction: TrendDirection,
353 pub strength: f64,
355 pub duration: Duration,
357 pub significance: f64,
359 pub extrapolation: Option<f64>,
361}
362
363#[derive(Debug, Clone, Copy, PartialEq, Eq)]
365pub enum TrendDirection {
366 Increasing,
367 Decreasing,
368 Stable,
369 Oscillating,
370 Unknown,
371}
372
373#[derive(Debug, Clone)]
375pub struct Anomaly {
376 pub anomaly_type: AnomalyType,
378 pub confidence: f64,
380 pub metric: MetricType,
382 pub timestamp: SystemTime,
384 pub description: String,
386 pub suggested_actions: Vec<String>,
388}
389
390#[derive(Debug, Clone, Copy, PartialEq, Eq)]
392pub enum AnomalyType {
393 Outlier,
394 PatternBreak,
395 Drift,
396 Spike,
397 PerformanceDegradation,
398 SystemFailure,
399}
400
401#[derive(Debug, Clone)]
403pub struct Correlation {
404 pub metric1: MetricType,
406 pub metric2: MetricType,
408 pub coefficient: f64,
410 pub significance: f64,
412 pub correlation_type: CorrelationType,
414 pub time_lag: Option<Duration>,
416}
417
418#[derive(Debug, Clone, Copy, PartialEq, Eq)]
420pub enum CorrelationType {
421 Positive,
422 Negative,
423 NonLinear,
424 Causal,
425 Spurious,
426}
427
428#[derive(Debug, Clone)]
430pub struct Prediction {
431 pub predicted_values: Vec<(SystemTime, f64)>,
433 pub confidence_intervals: Vec<(f64, f64)>,
435 pub accuracy_estimate: f64,
437 pub model_name: String,
439 pub horizon: Duration,
441}
442
443#[derive(Debug, Clone)]
445pub struct AnalysisResult {
446 pub analysis_type: String,
448 pub result_data: HashMap<String, String>,
450 pub confidence: f64,
452 pub timestamp: SystemTime,
454}
455
456#[derive(Debug)]
458pub struct AlertManager {
459 active_alerts: HashMap<String, Alert>,
461 alert_rules: Vec<AlertRule>,
463 alert_handlers: Vec<Box<dyn AlertHandler>>,
465 alert_history: VecDeque<Alert>,
467 suppression_rules: Vec<SuppressionRule>,
469}
470
471#[derive(Debug, Clone)]
473pub struct Alert {
474 pub id: String,
476 pub level: AlertLevel,
478 pub message: String,
480 pub affected_metrics: Vec<MetricType>,
482 pub timestamp: SystemTime,
484 pub source: String,
486 pub suggested_actions: Vec<String>,
488 pub status: AlertStatus,
490}
491
492#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
494pub enum AlertLevel {
495 Info,
496 Warning,
497 Critical,
498 Emergency,
499}
500
501#[derive(Debug, Clone, Copy, PartialEq, Eq)]
503pub enum AlertStatus {
504 Active,
505 Acknowledged,
506 Resolved,
507 Suppressed,
508}
509
510#[derive(Debug, Clone)]
512pub struct AlertRule {
513 pub id: String,
515 pub name: String,
517 pub condition: AlertCondition,
519 pub alert_level: AlertLevel,
521 pub message_template: String,
523 pub cooldown_period: Duration,
525}
526
527#[derive(Debug, Clone)]
529pub enum AlertCondition {
530 Threshold {
532 metric: MetricType,
533 operator: ComparisonOperator,
534 threshold: f64,
535 duration: Duration,
536 },
537 RateOfChange {
539 metric: MetricType,
540 rate_threshold: f64,
541 time_window: Duration,
542 },
543 AnomalyDetected {
545 metric: MetricType,
546 confidence_threshold: f64,
547 },
548 Complex {
550 expression: String,
551 required_metrics: Vec<MetricType>,
552 },
553}
554
555#[derive(Debug, Clone, Copy, PartialEq, Eq)]
557pub enum ComparisonOperator {
558 GreaterThan,
559 LessThan,
560 Equal,
561 NotEqual,
562 GreaterThanOrEqual,
563 LessThanOrEqual,
564}
565
566pub trait AlertHandler: std::fmt::Debug + Send + Sync {
568 fn handle_alert(&self, alert: &Alert) -> QuantRS2Result<()>;
570
571 fn name(&self) -> &str;
573
574 fn can_handle(&self, level: AlertLevel) -> bool;
576}
577
578#[derive(Debug, Clone)]
580pub struct SuppressionRule {
581 pub id: String,
583 pub condition: SuppressionCondition,
585 pub duration: Duration,
587 pub description: String,
589}
590
591#[derive(Debug, Clone)]
593pub enum SuppressionCondition {
594 AlertType(String),
596 MaintenanceWindow(SystemTime, SystemTime),
598 MetricPattern(MetricType, String),
600}
601
602#[derive(Debug)]
604pub struct OptimizationAdvisor {
605 optimization_strategies: HashMap<String, Box<dyn OptimizationStrategy>>,
607 recommendation_engine: RecommendationEngine,
609 active_recommendations: Vec<OptimizationRecommendation>,
611 recommendation_history: VecDeque<OptimizationRecommendation>,
613}
614
615pub trait OptimizationStrategy: std::fmt::Debug + Send + Sync {
617 fn analyze(&self, data: &RealtimeDataStore) -> QuantRS2Result<Vec<OptimizationRecommendation>>;
619
620 fn name(&self) -> &str;
622
623 fn priority(&self) -> u32;
625}
626
627#[derive(Debug, Clone)]
629pub struct OptimizationRecommendation {
630 pub id: String,
632 pub recommendation_type: RecommendationType,
634 pub description: String,
636 pub affected_components: Vec<String>,
638 pub expected_improvement: ExpectedImprovement,
640 pub implementation_difficulty: DifficultyLevel,
642 pub priority: RecommendationPriority,
644 pub timestamp: SystemTime,
646}
647
648#[derive(Debug, Clone, Copy, PartialEq, Eq)]
650pub enum RecommendationType {
651 GateOptimization,
652 CalibrationAdjustment,
653 CircuitOptimization,
654 ResourceReallocation,
655 EnvironmentalAdjustment,
656 MaintenanceRequired,
657 UpgradeRecommendation,
658}
659
660#[derive(Debug, Clone)]
662pub struct ExpectedImprovement {
663 pub fidelity_improvement: Option<f64>,
665 pub speed_improvement: Option<f64>,
667 pub error_rate_reduction: Option<f64>,
669 pub resource_savings: Option<f64>,
671}
672
673#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
675pub enum DifficultyLevel {
676 Easy,
677 Medium,
678 Hard,
679 ExpertRequired,
680}
681
682#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
684pub enum RecommendationPriority {
685 Low,
686 Medium,
687 High,
688 Critical,
689}
690
691#[derive(Debug)]
693pub struct RecommendationEngine {
694 ml_models: HashMap<String, Box<dyn MLModel>>,
696 rule_based_rules: Vec<RecommendationRule>,
698 knowledge_base: KnowledgeBase,
700}
701
702pub trait MLModel: std::fmt::Debug + Send + Sync {
704 fn train(&mut self, training_data: &[TrainingExample]) -> QuantRS2Result<()>;
706
707 fn predict(
709 &self,
710 input_data: &[MetricMeasurement],
711 ) -> QuantRS2Result<Vec<OptimizationRecommendation>>;
712
713 fn accuracy(&self) -> f64;
715
716 fn name(&self) -> &str;
718}
719
720#[derive(Debug, Clone)]
722pub struct TrainingExample {
723 pub input_metrics: Vec<MetricMeasurement>,
725 pub expected_recommendation: OptimizationRecommendation,
727 pub actual_outcome: Option<OutcomeMetrics>,
729}
730
731#[derive(Debug, Clone)]
733pub struct OutcomeMetrics {
734 pub performance_improvement: f64,
736 pub implementation_success: bool,
738 pub implementation_time: Duration,
740 pub side_effects: Vec<String>,
742}
743
744#[derive(Debug, Clone)]
746pub struct RecommendationRule {
747 pub id: String,
749 pub condition: String,
751 pub recommendation_template: OptimizationRecommendation,
753 pub weight: f64,
755}
756
757#[derive(Debug)]
759pub struct KnowledgeBase {
760 best_practices: HashMap<String, BestPractice>,
762 issue_solutions: HashMap<String, Solution>,
764 platform_knowledge: HashMap<HardwarePlatform, PlatformKnowledge>,
766}
767
768#[derive(Debug, Clone)]
770pub struct BestPractice {
771 pub id: String,
773 pub description: String,
775 pub applicable_platforms: Vec<HardwarePlatform>,
777 pub expected_benefits: Vec<String>,
779 pub implementation_steps: Vec<String>,
781}
782
783#[derive(Debug, Clone)]
785pub struct Solution {
786 pub id: String,
788 pub problem_description: String,
790 pub solution_description: String,
792 pub success_rate: f64,
794 pub complexity: DifficultyLevel,
796}
797
798#[derive(Debug, Clone)]
800pub struct PlatformKnowledge {
801 pub platform: HardwarePlatform,
803 pub known_limitations: Vec<String>,
805 pub optimization_opportunities: Vec<String>,
807 pub common_failure_modes: Vec<String>,
809 pub vendor_tips: Vec<String>,
811}
812
813#[derive(Debug)]
815pub struct PerformanceDashboard {
816 widgets: HashMap<String, Box<dyn DashboardWidget>>,
818 layout: DashboardLayout,
820 update_frequency: Duration,
822 dashboard_state: DashboardState,
824}
825
826pub trait DashboardWidget: std::fmt::Debug + Send + Sync {
828 fn render(&self, data: &RealtimeDataStore) -> QuantRS2Result<WidgetData>;
830
831 fn get_config(&self) -> WidgetConfig;
833
834 fn update_config(&mut self, config: WidgetConfig) -> QuantRS2Result<()>;
836}
837
838#[derive(Debug, Clone)]
840pub struct WidgetData {
841 pub widget_type: String,
843 pub data: HashMap<String, String>,
845 pub visualization_hints: Vec<String>,
847 pub timestamp: SystemTime,
849}
850
851#[derive(Debug, Clone)]
853pub struct WidgetConfig {
854 pub title: String,
856 pub size: (u32, u32),
858 pub position: (u32, u32),
860 pub refresh_rate: Duration,
862 pub data_source: String,
864 pub display_options: HashMap<String, String>,
866}
867
868#[derive(Debug, Clone)]
870pub struct DashboardLayout {
871 pub layout_type: LayoutType,
873 pub grid_dimensions: (u32, u32),
875 pub widget_positions: HashMap<String, (u32, u32)>,
877}
878
879#[derive(Debug, Clone, Copy, PartialEq, Eq)]
881pub enum LayoutType {
882 Grid,
883 Flexible,
884 Stacked,
885 Tabbed,
886}
887
888#[derive(Debug, Clone)]
890pub struct DashboardState {
891 pub active_widgets: HashSet<String>,
893 pub last_update: SystemTime,
895 pub mode: DashboardMode,
897}
898
899#[derive(Debug, Clone, Copy, PartialEq, Eq)]
901pub enum DashboardMode {
902 Monitoring,
903 Analysis,
904 Debugging,
905 Maintenance,
906}
907
908#[derive(Debug)]
910pub struct ExportManager {
911 exporters: HashMap<ExportFormat, Box<dyn DataExporter>>,
913 export_queue: VecDeque<ExportTask>,
915 export_stats: ExportStatistics,
917}
918
919pub trait DataExporter: std::fmt::Debug + Send + Sync {
921 fn export(
923 &self,
924 data: &[MetricMeasurement],
925 destination: &ExportDestination,
926 ) -> QuantRS2Result<()>;
927
928 fn format(&self) -> ExportFormat;
930
931 fn validate_config(&self, destination: &ExportDestination) -> QuantRS2Result<()>;
933}
934
935#[derive(Debug, Clone)]
937pub struct ExportTask {
938 pub id: String,
940 pub data_range: (SystemTime, SystemTime),
942 pub format: ExportFormat,
944 pub destination: ExportDestination,
946 pub priority: TaskPriority,
948 pub created: SystemTime,
950}
951
952#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
954pub enum TaskPriority {
955 Low,
956 Normal,
957 High,
958 Urgent,
959}
960
961#[derive(Debug, Clone)]
963pub struct ExportStatistics {
964 pub total_exports: u64,
966 pub failed_exports: u64,
968 pub average_export_time: Duration,
970 pub total_data_volume: u64,
972 pub last_export_time: SystemTime,
974}
975
976#[derive(Debug, Clone)]
978pub struct MonitoringStatus {
979 pub overall_status: SystemStatus,
981 pub platform_statuses: HashMap<HardwarePlatform, PlatformStatus>,
983 pub active_collectors: usize,
985 pub total_data_points: u64,
987 pub active_alerts: usize,
989 pub uptime: Duration,
991}
992
993#[derive(Debug, Clone, Copy, PartialEq, Eq)]
995pub enum SystemStatus {
996 Healthy,
997 Degraded,
998 Critical,
999 Offline,
1000}
1001
1002#[derive(Debug, Clone)]
1004pub struct PlatformStatus {
1005 pub connection_status: ConnectionStatus,
1007 pub last_data_collection: SystemTime,
1009 pub collection_rate: f64,
1011 pub error_rate: f64,
1013 pub platform_metrics: HashMap<String, f64>,
1015}
1016
1017#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1019pub enum ConnectionStatus {
1020 Connected,
1021 Disconnected,
1022 Reconnecting,
1023 Error,
1024}
1025
1026impl RealtimeMonitor {
1027 pub fn new(config: MonitoringConfig) -> QuantRS2Result<Self> {
1029 Ok(Self {
1030 config: config.clone(),
1031 collectors: Arc::new(RwLock::new(HashMap::new())),
1032 data_store: Arc::new(RwLock::new(RealtimeDataStore::new(
1033 config.data_retention_period,
1034 ))),
1035 analytics_engine: Arc::new(RwLock::new(AnalyticsEngine::new())),
1036 alert_manager: Arc::new(RwLock::new(AlertManager::new(config.alert_thresholds))),
1037 optimization_advisor: Arc::new(RwLock::new(OptimizationAdvisor::new())),
1038 dashboard: Arc::new(RwLock::new(PerformanceDashboard::new())),
1039 export_manager: Arc::new(RwLock::new(ExportManager::new(config.export_settings))),
1040 monitoring_status: Arc::new(RwLock::new(MonitoringStatus::new())),
1041 })
1042 }
1043
1044 pub fn start_monitoring(&self) -> QuantRS2Result<()> {
1046 self.initialize_collectors()?;
1048
1049 self.start_data_collection_threads()?;
1051
1052 self.start_analytics_engine()?;
1054
1055 self.start_alert_processing()?;
1057
1058 self.start_export_processing()?;
1060
1061 {
1063 let mut status = self.monitoring_status.write().map_err(|e| {
1064 QuantRS2Error::LockPoisoned(format!("Monitoring status RwLock poisoned: {e}"))
1065 })?;
1066 status.overall_status = SystemStatus::Healthy;
1067 }
1068
1069 Ok(())
1070 }
1071
1072 pub const fn stop_monitoring(&self) -> QuantRS2Result<()> {
1074 Ok(())
1076 }
1077
1078 pub fn register_collector(
1080 &self,
1081 platform: HardwarePlatform,
1082 collector: Box<dyn MetricCollector>,
1083 ) -> QuantRS2Result<()> {
1084 let mut collectors = self
1085 .collectors
1086 .write()
1087 .map_err(|e| QuantRS2Error::LockPoisoned(format!("Collectors RwLock poisoned: {e}")))?;
1088 collectors.insert(platform, collector);
1089 Ok(())
1090 }
1091
1092 pub fn get_current_metrics(
1094 &self,
1095 metric_types: Option<Vec<MetricType>>,
1096 ) -> QuantRS2Result<Vec<MetricMeasurement>> {
1097 let data_store = self
1098 .data_store
1099 .read()
1100 .map_err(|e| QuantRS2Error::LockPoisoned(format!("Data store RwLock poisoned: {e}")))?;
1101
1102 let mut results = Vec::new();
1103
1104 match metric_types {
1105 Some(types) => {
1106 for metric_type in types {
1107 if let Some(time_series) = data_store.time_series.get(&metric_type) {
1108 if let Some(latest) = time_series.back() {
1109 results.push(latest.clone());
1110 }
1111 }
1112 }
1113 }
1114 None => {
1115 for time_series in data_store.time_series.values() {
1116 if let Some(latest) = time_series.back() {
1117 results.push(latest.clone());
1118 }
1119 }
1120 }
1121 }
1122
1123 Ok(results)
1124 }
1125
1126 pub fn get_historical_metrics(
1128 &self,
1129 metric_type: MetricType,
1130 start_time: SystemTime,
1131 end_time: SystemTime,
1132 ) -> QuantRS2Result<Vec<MetricMeasurement>> {
1133 let data_store = self
1134 .data_store
1135 .read()
1136 .map_err(|e| QuantRS2Error::LockPoisoned(format!("Data store RwLock poisoned: {e}")))?;
1137
1138 if let Some(time_series) = data_store.time_series.get(&metric_type) {
1139 let filtered: Vec<MetricMeasurement> = time_series
1140 .iter()
1141 .filter(|measurement| {
1142 measurement.timestamp >= start_time && measurement.timestamp <= end_time
1143 })
1144 .cloned()
1145 .collect();
1146
1147 Ok(filtered)
1148 } else {
1149 Ok(Vec::new())
1150 }
1151 }
1152
1153 pub fn get_aggregated_stats(
1155 &self,
1156 metric_type: MetricType,
1157 ) -> QuantRS2Result<Option<AggregatedStats>> {
1158 let data_store = self
1159 .data_store
1160 .read()
1161 .map_err(|e| QuantRS2Error::LockPoisoned(format!("Data store RwLock poisoned: {e}")))?;
1162 Ok(data_store.aggregated_stats.get(&metric_type).cloned())
1163 }
1164
1165 pub fn get_active_alerts(&self) -> QuantRS2Result<Vec<Alert>> {
1167 let alert_manager = self.alert_manager.read().map_err(|e| {
1168 QuantRS2Error::LockPoisoned(format!("Alert manager RwLock poisoned: {e}"))
1169 })?;
1170 Ok(alert_manager.active_alerts.values().cloned().collect())
1171 }
1172
1173 pub fn get_optimization_recommendations(
1175 &self,
1176 ) -> QuantRS2Result<Vec<OptimizationRecommendation>> {
1177 let optimization_advisor = self.optimization_advisor.read().map_err(|e| {
1178 QuantRS2Error::LockPoisoned(format!("Optimization advisor RwLock poisoned: {e}"))
1179 })?;
1180 Ok(optimization_advisor.active_recommendations.clone())
1181 }
1182
1183 pub fn get_monitoring_status(&self) -> QuantRS2Result<MonitoringStatus> {
1185 Ok(self
1186 .monitoring_status
1187 .read()
1188 .map_err(|e| {
1189 QuantRS2Error::LockPoisoned(format!("Monitoring status RwLock poisoned: {e}"))
1190 })?
1191 .clone())
1192 }
1193
1194 pub fn collect_metrics_now(&self) -> QuantRS2Result<usize> {
1196 let collectors = self
1197 .collectors
1198 .read()
1199 .map_err(|e| QuantRS2Error::LockPoisoned(format!("Collectors RwLock poisoned: {e}")))?;
1200 let mut total_metrics = 0;
1201
1202 for collector in collectors.values() {
1203 let metrics = collector.collect_metrics()?;
1204 total_metrics += metrics.len();
1205
1206 self.store_metrics(metrics)?;
1208 }
1209
1210 Ok(total_metrics)
1211 }
1212
1213 pub fn update_analytics(&self) -> QuantRS2Result<()> {
1215 let data_store = self
1216 .data_store
1217 .read()
1218 .map_err(|e| QuantRS2Error::LockPoisoned(format!("Data store RwLock poisoned: {e}")))?;
1219 let analytics = self.analytics_engine.write().map_err(|e| {
1220 QuantRS2Error::LockPoisoned(format!("Analytics engine RwLock poisoned: {e}"))
1221 })?;
1222
1223 for (metric_type, time_series) in &data_store.time_series {
1225 if let Some(analyzer) = analytics.trend_analyzers.get(metric_type) {
1226 let data: Vec<MetricMeasurement> = time_series.iter().cloned().collect();
1227 let _trend = analyzer.analyze_trend(&data)?;
1228 }
1230 }
1231
1232 Ok(())
1233 }
1234
1235 fn initialize_collectors(&self) -> QuantRS2Result<()> {
1237 for (platform, platform_config) in &self.config.platform_configs {
1239 let collector = self.create_collector_for_platform(*platform, platform_config)?;
1241 self.register_collector(*platform, collector)?;
1242 }
1243 Ok(())
1244 }
1245
1246 fn create_collector_for_platform(
1247 &self,
1248 platform: HardwarePlatform,
1249 config: &PlatformMonitoringConfig,
1250 ) -> QuantRS2Result<Box<dyn MetricCollector>> {
1251 match platform {
1252 HardwarePlatform::Superconducting => {
1253 Ok(Box::new(SuperconductingCollector::new(config.clone())))
1254 }
1255 HardwarePlatform::TrappedIon => Ok(Box::new(TrappedIonCollector::new(config.clone()))),
1256 HardwarePlatform::Photonic => Ok(Box::new(PhotonicCollector::new(config.clone()))),
1257 HardwarePlatform::NeutralAtom => {
1258 Ok(Box::new(NeutralAtomCollector::new(config.clone())))
1259 }
1260 _ => Ok(Box::new(GenericCollector::new(config.clone()))),
1261 }
1262 }
1263
1264 fn start_data_collection_threads(&self) -> QuantRS2Result<()> {
1265 let collectors = Arc::clone(&self.collectors);
1267 let data_store = Arc::clone(&self.data_store);
1268 let monitoring_interval = self.config.monitoring_interval;
1269
1270 thread::spawn(move || loop {
1271 thread::sleep(monitoring_interval);
1272
1273 if let Ok(collectors_guard) = collectors.read() {
1275 for collector in collectors_guard.values() {
1276 if let Ok(metrics) = collector.collect_metrics() {
1277 if let Ok(mut store) = data_store.write() {
1278 for metric in metrics {
1279 store.add_measurement(metric);
1280 }
1281 }
1282 }
1283 }
1284 }
1285 });
1286
1287 Ok(())
1288 }
1289
1290 const fn start_analytics_engine(&self) -> QuantRS2Result<()> {
1291 Ok(())
1293 }
1294
1295 const fn start_alert_processing(&self) -> QuantRS2Result<()> {
1296 Ok(())
1298 }
1299
1300 const fn start_export_processing(&self) -> QuantRS2Result<()> {
1301 Ok(())
1303 }
1304
1305 fn store_metrics(&self, metrics: Vec<MetricMeasurement>) -> QuantRS2Result<()> {
1306 let mut data_store = self
1307 .data_store
1308 .write()
1309 .map_err(|e| QuantRS2Error::LockPoisoned(format!("Data store RwLock poisoned: {e}")))?;
1310 for metric in metrics {
1311 data_store.add_measurement(metric);
1312 }
1313 Ok(())
1314 }
1315}
1316
1317#[derive(Debug)]
1319struct SuperconductingCollector {
1320 config: PlatformMonitoringConfig,
1321 connected: bool,
1322}
1323
1324impl SuperconductingCollector {
1325 const fn new(config: PlatformMonitoringConfig) -> Self {
1326 Self {
1327 config,
1328 connected: false,
1329 }
1330 }
1331}
1332
1333impl MetricCollector for SuperconductingCollector {
1334 fn collect_metrics(&self) -> QuantRS2Result<Vec<MetricMeasurement>> {
1335 let mut metrics = Vec::new();
1337
1338 metrics.push(MetricMeasurement {
1340 metric_type: MetricType::GateErrorRate,
1341 value: MetricValue::Float(0.001),
1342 timestamp: SystemTime::now(),
1343 qubit: Some(QubitId::new(0)),
1344 gate_type: Some(NativeGateType::CNOT),
1345 metadata: HashMap::new(),
1346 uncertainty: Some(0.0001),
1347 });
1348
1349 metrics.push(MetricMeasurement {
1351 metric_type: MetricType::QubitCoherenceTime,
1352 value: MetricValue::Duration(Duration::from_micros(100)),
1353 timestamp: SystemTime::now(),
1354 qubit: Some(QubitId::new(0)),
1355 gate_type: None,
1356 metadata: HashMap::new(),
1357 uncertainty: Some(0.01),
1358 });
1359
1360 Ok(metrics)
1361 }
1362
1363 fn supported_metrics(&self) -> HashSet<MetricType> {
1364 let mut metrics = HashSet::new();
1365 metrics.insert(MetricType::GateErrorRate);
1366 metrics.insert(MetricType::QubitCoherenceTime);
1367 metrics.insert(MetricType::QubitReadoutError);
1368 metrics.insert(MetricType::QubitTemperature);
1369 metrics
1370 }
1371
1372 fn platform(&self) -> HardwarePlatform {
1373 HardwarePlatform::Superconducting
1374 }
1375
1376 fn initialize(&mut self) -> QuantRS2Result<()> {
1377 self.connected = true;
1378 Ok(())
1379 }
1380
1381 fn is_connected(&self) -> bool {
1382 self.connected
1383 }
1384
1385 fn disconnect(&mut self) -> QuantRS2Result<()> {
1386 self.connected = false;
1387 Ok(())
1388 }
1389}
1390
1391#[derive(Debug)]
1393struct TrappedIonCollector {
1394 config: PlatformMonitoringConfig,
1395 connected: bool,
1396}
1397
1398impl TrappedIonCollector {
1399 const fn new(config: PlatformMonitoringConfig) -> Self {
1400 Self {
1401 config,
1402 connected: false,
1403 }
1404 }
1405}
1406
1407impl MetricCollector for TrappedIonCollector {
1408 fn collect_metrics(&self) -> QuantRS2Result<Vec<MetricMeasurement>> {
1409 Ok(vec![])
1410 }
1411
1412 fn supported_metrics(&self) -> HashSet<MetricType> {
1413 HashSet::new()
1414 }
1415
1416 fn platform(&self) -> HardwarePlatform {
1417 HardwarePlatform::TrappedIon
1418 }
1419
1420 fn initialize(&mut self) -> QuantRS2Result<()> {
1421 self.connected = true;
1422 Ok(())
1423 }
1424
1425 fn is_connected(&self) -> bool {
1426 self.connected
1427 }
1428
1429 fn disconnect(&mut self) -> QuantRS2Result<()> {
1430 self.connected = false;
1431 Ok(())
1432 }
1433}
1434
1435#[derive(Debug)]
1436struct PhotonicCollector {
1437 config: PlatformMonitoringConfig,
1438 connected: bool,
1439}
1440
1441impl PhotonicCollector {
1442 const fn new(config: PlatformMonitoringConfig) -> Self {
1443 Self {
1444 config,
1445 connected: false,
1446 }
1447 }
1448}
1449
1450impl MetricCollector for PhotonicCollector {
1451 fn collect_metrics(&self) -> QuantRS2Result<Vec<MetricMeasurement>> {
1452 Ok(vec![])
1453 }
1454
1455 fn supported_metrics(&self) -> HashSet<MetricType> {
1456 HashSet::new()
1457 }
1458
1459 fn platform(&self) -> HardwarePlatform {
1460 HardwarePlatform::Photonic
1461 }
1462
1463 fn initialize(&mut self) -> QuantRS2Result<()> {
1464 self.connected = true;
1465 Ok(())
1466 }
1467
1468 fn is_connected(&self) -> bool {
1469 self.connected
1470 }
1471
1472 fn disconnect(&mut self) -> QuantRS2Result<()> {
1473 self.connected = false;
1474 Ok(())
1475 }
1476}
1477
1478#[derive(Debug)]
1479struct NeutralAtomCollector {
1480 config: PlatformMonitoringConfig,
1481 connected: bool,
1482}
1483
1484impl NeutralAtomCollector {
1485 const fn new(config: PlatformMonitoringConfig) -> Self {
1486 Self {
1487 config,
1488 connected: false,
1489 }
1490 }
1491}
1492
1493impl MetricCollector for NeutralAtomCollector {
1494 fn collect_metrics(&self) -> QuantRS2Result<Vec<MetricMeasurement>> {
1495 Ok(vec![])
1496 }
1497
1498 fn supported_metrics(&self) -> HashSet<MetricType> {
1499 HashSet::new()
1500 }
1501
1502 fn platform(&self) -> HardwarePlatform {
1503 HardwarePlatform::NeutralAtom
1504 }
1505
1506 fn initialize(&mut self) -> QuantRS2Result<()> {
1507 self.connected = true;
1508 Ok(())
1509 }
1510
1511 fn is_connected(&self) -> bool {
1512 self.connected
1513 }
1514
1515 fn disconnect(&mut self) -> QuantRS2Result<()> {
1516 self.connected = false;
1517 Ok(())
1518 }
1519}
1520
1521#[derive(Debug)]
1522struct GenericCollector {
1523 config: PlatformMonitoringConfig,
1524 connected: bool,
1525}
1526
1527impl GenericCollector {
1528 const fn new(config: PlatformMonitoringConfig) -> Self {
1529 Self {
1530 config,
1531 connected: false,
1532 }
1533 }
1534}
1535
1536impl MetricCollector for GenericCollector {
1537 fn collect_metrics(&self) -> QuantRS2Result<Vec<MetricMeasurement>> {
1538 Ok(vec![])
1539 }
1540
1541 fn supported_metrics(&self) -> HashSet<MetricType> {
1542 HashSet::new()
1543 }
1544
1545 fn platform(&self) -> HardwarePlatform {
1546 HardwarePlatform::Universal
1547 }
1548
1549 fn initialize(&mut self) -> QuantRS2Result<()> {
1550 self.connected = true;
1551 Ok(())
1552 }
1553
1554 fn is_connected(&self) -> bool {
1555 self.connected
1556 }
1557
1558 fn disconnect(&mut self) -> QuantRS2Result<()> {
1559 self.connected = false;
1560 Ok(())
1561 }
1562}
1563
1564impl RealtimeDataStore {
1566 fn new(_retention_period: Duration) -> Self {
1567 Self {
1568 time_series: HashMap::new(),
1569 aggregated_stats: HashMap::new(),
1570 retention_settings: HashMap::new(),
1571 current_data_size: 0,
1572 max_data_size: 1_000_000, }
1574 }
1575
1576 fn add_measurement(&mut self, measurement: MetricMeasurement) {
1577 let metric_type = measurement.metric_type.clone();
1578
1579 let time_series = self
1581 .time_series
1582 .entry(metric_type.clone())
1583 .or_insert_with(VecDeque::new);
1584 time_series.push_back(measurement.clone());
1585
1586 self.update_aggregated_stats(metric_type, &measurement);
1588
1589 self.cleanup_old_data();
1591 }
1592
1593 fn update_aggregated_stats(
1594 &mut self,
1595 metric_type: MetricType,
1596 measurement: &MetricMeasurement,
1597 ) {
1598 let stats = self
1600 .aggregated_stats
1601 .entry(metric_type)
1602 .or_insert_with(|| AggregatedStats {
1603 mean: 0.0,
1604 std_dev: 0.0,
1605 min: f64::INFINITY,
1606 max: f64::NEG_INFINITY,
1607 median: 0.0,
1608 p95: 0.0,
1609 p99: 0.0,
1610 sample_count: 0,
1611 last_updated: SystemTime::now(),
1612 });
1613
1614 if let MetricValue::Float(value) = measurement.value {
1615 stats.sample_count += 1;
1616 stats.min = stats.min.min(value);
1617 stats.max = stats.max.max(value);
1618 stats.last_updated = SystemTime::now();
1619
1620 stats.mean = stats.mean.mul_add((stats.sample_count - 1) as f64, value)
1622 / stats.sample_count as f64;
1623 }
1624 }
1625
1626 const fn cleanup_old_data(&self) {
1627 }
1630}
1631
1632impl AnalyticsEngine {
1633 fn new() -> Self {
1634 Self {
1635 trend_analyzers: HashMap::new(),
1636 anomaly_detectors: HashMap::new(),
1637 correlation_analyzers: Vec::new(),
1638 predictive_models: HashMap::new(),
1639 analysis_cache: HashMap::new(),
1640 }
1641 }
1642}
1643
1644impl AlertManager {
1645 fn new(_thresholds: AlertThresholds) -> Self {
1646 Self {
1647 active_alerts: HashMap::new(),
1648 alert_rules: Vec::new(),
1649 alert_handlers: Vec::new(),
1650 alert_history: VecDeque::new(),
1651 suppression_rules: Vec::new(),
1652 }
1653 }
1654}
1655
1656impl OptimizationAdvisor {
1657 fn new() -> Self {
1658 Self {
1659 optimization_strategies: HashMap::new(),
1660 recommendation_engine: RecommendationEngine::new(),
1661 active_recommendations: Vec::new(),
1662 recommendation_history: VecDeque::new(),
1663 }
1664 }
1665}
1666
1667impl RecommendationEngine {
1668 fn new() -> Self {
1669 Self {
1670 ml_models: HashMap::new(),
1671 rule_based_rules: Vec::new(),
1672 knowledge_base: KnowledgeBase::new(),
1673 }
1674 }
1675}
1676
1677impl KnowledgeBase {
1678 fn new() -> Self {
1679 Self {
1680 best_practices: HashMap::new(),
1681 issue_solutions: HashMap::new(),
1682 platform_knowledge: HashMap::new(),
1683 }
1684 }
1685}
1686
1687impl PerformanceDashboard {
1688 fn new() -> Self {
1689 Self {
1690 widgets: HashMap::new(),
1691 layout: DashboardLayout {
1692 layout_type: LayoutType::Grid,
1693 grid_dimensions: (4, 3),
1694 widget_positions: HashMap::new(),
1695 },
1696 update_frequency: Duration::from_secs(1),
1697 dashboard_state: DashboardState {
1698 active_widgets: HashSet::new(),
1699 last_update: SystemTime::now(),
1700 mode: DashboardMode::Monitoring,
1701 },
1702 }
1703 }
1704}
1705
1706impl ExportManager {
1707 fn new(_settings: ExportSettings) -> Self {
1708 Self {
1709 exporters: HashMap::new(),
1710 export_queue: VecDeque::new(),
1711 export_stats: ExportStatistics {
1712 total_exports: 0,
1713 failed_exports: 0,
1714 average_export_time: Duration::from_millis(0),
1715 total_data_volume: 0,
1716 last_export_time: SystemTime::now(),
1717 },
1718 }
1719 }
1720}
1721
1722impl MonitoringStatus {
1723 fn new() -> Self {
1724 Self {
1725 overall_status: SystemStatus::Offline,
1726 platform_statuses: HashMap::new(),
1727 active_collectors: 0,
1728 total_data_points: 0,
1729 active_alerts: 0,
1730 uptime: Duration::from_secs(0),
1731 }
1732 }
1733}
1734
1735impl Default for MonitoringConfig {
1737 fn default() -> Self {
1738 Self {
1739 monitoring_interval: Duration::from_secs(1),
1740 data_retention_period: Duration::from_secs(24 * 3600), alert_thresholds: AlertThresholds::default(),
1742 enabled_metrics: HashSet::new(),
1743 platform_configs: HashMap::new(),
1744 export_settings: ExportSettings::default(),
1745 }
1746 }
1747}
1748
1749impl Default for AlertThresholds {
1750 fn default() -> Self {
1751 Self {
1752 max_gate_error_rate: 0.01,
1753 max_readout_error_rate: 0.05,
1754 min_coherence_time: Duration::from_micros(50),
1755 max_calibration_drift: 0.1,
1756 max_temperature: 300.0, max_queue_depth: 1000,
1758 max_execution_time: Duration::from_secs(300),
1759 }
1760 }
1761}
1762
1763impl Default for ExportSettings {
1764 fn default() -> Self {
1765 Self {
1766 enable_export: false,
1767 export_formats: vec![ExportFormat::JSON],
1768 export_destinations: vec![],
1769 export_frequency: Duration::from_secs(3600), compression_enabled: true,
1771 }
1772 }
1773}
1774
1775impl fmt::Display for MetricType {
1777 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1778 match self {
1779 Self::GateErrorRate => write!(f, "Gate Error Rate"),
1780 Self::QubitCoherenceTime => write!(f, "Qubit Coherence Time"),
1781 Self::SystemUptime => write!(f, "System Uptime"),
1782 Self::Custom(name) => write!(f, "Custom: {name}"),
1783 _ => write!(f, "{self:?}"),
1784 }
1785 }
1786}
1787
1788impl fmt::Display for AlertLevel {
1789 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1790 match self {
1791 Self::Info => write!(f, "INFO"),
1792 Self::Warning => write!(f, "WARNING"),
1793 Self::Critical => write!(f, "CRITICAL"),
1794 Self::Emergency => write!(f, "EMERGENCY"),
1795 }
1796 }
1797}
1798
1799#[cfg(test)]
1800mod tests {
1801 use super::*;
1802
1803 #[test]
1804 fn test_realtime_monitor_creation() {
1805 let config = MonitoringConfig::default();
1806 let monitor = RealtimeMonitor::new(config);
1807 assert!(monitor.is_ok());
1808 }
1809
1810 #[test]
1811 fn test_metric_measurement() {
1812 let measurement = MetricMeasurement {
1813 metric_type: MetricType::GateErrorRate,
1814 value: MetricValue::Float(0.001),
1815 timestamp: SystemTime::now(),
1816 qubit: Some(QubitId::new(0)),
1817 gate_type: Some(NativeGateType::CNOT),
1818 metadata: HashMap::new(),
1819 uncertainty: Some(0.0001),
1820 };
1821
1822 assert_eq!(measurement.metric_type, MetricType::GateErrorRate);
1823 assert!(matches!(measurement.value, MetricValue::Float(0.001)));
1824 }
1825
1826 #[test]
1827 fn test_superconducting_collector() {
1828 let config = PlatformMonitoringConfig {
1829 platform: HardwarePlatform::Superconducting,
1830 monitored_metrics: HashSet::new(),
1831 sampling_rates: HashMap::new(),
1832 custom_thresholds: HashMap::new(),
1833 connection_settings: HashMap::new(),
1834 };
1835
1836 let mut collector = SuperconductingCollector::new(config);
1837 assert_eq!(collector.platform(), HardwarePlatform::Superconducting);
1838 assert!(!collector.is_connected());
1839
1840 assert!(collector.initialize().is_ok());
1841 assert!(collector.is_connected());
1842
1843 let metrics = collector.collect_metrics();
1844 assert!(metrics.is_ok());
1845 assert!(!metrics
1846 .expect("Metrics collection should succeed")
1847 .is_empty());
1848 }
1849
1850 #[test]
1851 fn test_data_store() {
1852 let mut store = RealtimeDataStore::new(Duration::from_secs(3600));
1853
1854 let measurement = MetricMeasurement {
1855 metric_type: MetricType::GateErrorRate,
1856 value: MetricValue::Float(0.001),
1857 timestamp: SystemTime::now(),
1858 qubit: None,
1859 gate_type: None,
1860 metadata: HashMap::new(),
1861 uncertainty: None,
1862 };
1863
1864 store.add_measurement(measurement);
1865
1866 assert!(store.time_series.contains_key(&MetricType::GateErrorRate));
1867 assert!(store
1868 .aggregated_stats
1869 .contains_key(&MetricType::GateErrorRate));
1870
1871 let stats = store
1872 .aggregated_stats
1873 .get(&MetricType::GateErrorRate)
1874 .expect("GateErrorRate stats should exist after adding measurement");
1875 assert_eq!(stats.sample_count, 1);
1876 assert_eq!(stats.mean, 0.001);
1877 }
1878
1879 #[test]
1880 fn test_alert_creation() {
1881 let alert = Alert {
1882 id: "test_alert".to_string(),
1883 level: AlertLevel::Warning,
1884 message: "Test alert message".to_string(),
1885 affected_metrics: vec![MetricType::GateErrorRate],
1886 timestamp: SystemTime::now(),
1887 source: "test".to_string(),
1888 suggested_actions: vec!["Check calibration".to_string()],
1889 status: AlertStatus::Active,
1890 };
1891
1892 assert_eq!(alert.level, AlertLevel::Warning);
1893 assert_eq!(alert.status, AlertStatus::Active);
1894 assert!(alert.affected_metrics.contains(&MetricType::GateErrorRate));
1895 }
1896
1897 #[test]
1898 fn test_monitoring_config() {
1899 let config = MonitoringConfig::default();
1900 assert_eq!(config.monitoring_interval, Duration::from_secs(1));
1901 assert_eq!(config.data_retention_period, Duration::from_secs(24 * 3600));
1902 assert!(!config.export_settings.enable_export);
1903 }
1904
1905 #[test]
1906 fn test_metric_value_types() {
1907 let float_value = MetricValue::Float(1.23);
1908 let int_value = MetricValue::Integer(42);
1909 let bool_value = MetricValue::Boolean(true);
1910 let duration_value = MetricValue::Duration(Duration::from_millis(100));
1911
1912 assert!(matches!(float_value, MetricValue::Float(1.23)));
1913 assert!(matches!(int_value, MetricValue::Integer(42)));
1914 assert!(matches!(bool_value, MetricValue::Boolean(true)));
1915 assert!(matches!(duration_value, MetricValue::Duration(_)));
1916 }
1917
1918 #[test]
1919 fn test_alert_thresholds() {
1920 let thresholds = AlertThresholds::default();
1921 assert_eq!(thresholds.max_gate_error_rate, 0.01);
1922 assert_eq!(thresholds.max_readout_error_rate, 0.05);
1923 assert_eq!(thresholds.min_coherence_time, Duration::from_micros(50));
1924 }
1925
1926 #[test]
1927 fn test_optimization_recommendation() {
1928 let recommendation = OptimizationRecommendation {
1929 id: "test_rec".to_string(),
1930 recommendation_type: RecommendationType::GateOptimization,
1931 description: "Optimize gate sequence".to_string(),
1932 affected_components: vec!["qubit_0".to_string()],
1933 expected_improvement: ExpectedImprovement {
1934 fidelity_improvement: Some(0.001),
1935 speed_improvement: Some(0.1),
1936 error_rate_reduction: Some(0.0005),
1937 resource_savings: None,
1938 },
1939 implementation_difficulty: DifficultyLevel::Medium,
1940 priority: RecommendationPriority::High,
1941 timestamp: SystemTime::now(),
1942 };
1943
1944 assert_eq!(
1945 recommendation.recommendation_type,
1946 RecommendationType::GateOptimization
1947 );
1948 assert_eq!(
1949 recommendation.implementation_difficulty,
1950 DifficultyLevel::Medium
1951 );
1952 assert_eq!(recommendation.priority, RecommendationPriority::High);
1953 }
1954
1955 #[test]
1956 fn test_export_settings() {
1957 let settings = ExportSettings {
1958 enable_export: true,
1959 export_formats: vec![ExportFormat::JSON, ExportFormat::CSV],
1960 export_destinations: vec![],
1961 export_frequency: Duration::from_secs(1800),
1962 compression_enabled: true,
1963 };
1964
1965 assert!(settings.enable_export);
1966 assert_eq!(settings.export_formats.len(), 2);
1967 assert!(settings.compression_enabled);
1968 }
1969
1970 #[test]
1971 fn test_monitoring_status() {
1972 let status = MonitoringStatus::new();
1973 assert_eq!(status.overall_status, SystemStatus::Offline);
1974 assert_eq!(status.active_collectors, 0);
1975 assert_eq!(status.total_data_points, 0);
1976 }
1977}