1use scirs2_core::numeric::Float;
13use std::collections::{BTreeMap, HashMap};
14use std::time::{Duration, SystemTime, UNIX_EPOCH};
15
16use crate::error::Result;
17
18mod accumulator;
19mod aggregation;
20mod alerts;
21mod export;
22
23#[cfg(test)]
24mod regression_tests;
25
26pub use accumulator::{MetricsAccumulator, ResourceProbe, RobustnessProbe};
27pub use aggregation::AggregatedSeries;
28pub use alerts::KNOWN_METRIC_PATHS;
29
30pub(crate) fn unix_timestamp(time: SystemTime) -> u64 {
33 time.duration_since(UNIX_EPOCH)
34 .unwrap_or_default()
35 .as_secs()
36}
37
38pub(crate) const MICROS_PER_SEC: u64 = 1_000_000;
42
43pub(crate) fn unix_timestamp_micros(time: SystemTime) -> u64 {
51 let elapsed = time.duration_since(UNIX_EPOCH).unwrap_or_default();
52 elapsed
53 .as_secs()
54 .saturating_mul(MICROS_PER_SEC)
55 .saturating_add(u64::from(elapsed.subsec_micros()))
56}
57
58pub(crate) fn saturating_elapsed(later: SystemTime, earlier: SystemTime) -> Duration {
61 later.duration_since(earlier).unwrap_or_default()
62}
63
64#[derive(Debug)]
66pub struct StreamingMetricsCollector<A: Float + Send + Sync> {
67 performance_metrics: PerformanceMetrics<A>,
69
70 resource_metrics: ResourceMetrics,
72
73 quality_metrics: QualityMetrics<A>,
75
76 business_metrics: BusinessMetrics<A>,
78
79 historical_data: HistoricalMetrics<A>,
81
82 dashboards: Vec<Dashboard>,
84
85 alert_system: AlertSystem<A>,
87
88 aggregation_config: AggregationConfig,
90
91 export_config: ExportConfig,
93
94 accumulator: MetricsAccumulator<A>,
96
97 slo: Option<SloTargets>,
99
100 cost_model: Option<CostModel<A>>,
102
103 last_export: Option<SystemTime>,
105}
106
107#[derive(Debug, Clone, Default)]
109pub struct SloTargets {
110 pub max_processing_time: Option<Duration>,
112
113 pub max_loss: Option<f64>,
115
116 pub max_memory_bytes: Option<u64>,
118}
119
120impl SloTargets {
121 pub fn is_empty(&self) -> bool {
123 self.max_processing_time.is_none()
124 && self.max_loss.is_none()
125 && self.max_memory_bytes.is_none()
126 }
127}
128
129#[derive(Debug, Clone)]
132pub struct CostModel<A: Float + Send + Sync> {
133 pub compute_cost_per_second: A,
135
136 pub memory_cost_per_gb_hour: A,
138
139 pub energy_cost_per_joule: A,
141
142 pub value_per_loss_unit: A,
144}
145
146#[derive(Debug, Clone)]
148pub struct PerformanceMetrics<A: Float + Send + Sync> {
149 pub throughput: ThroughputMetrics,
151
152 pub latency: LatencyMetrics,
154
155 pub accuracy: AccuracyMetrics<A>,
157
158 pub stability: StabilityMetrics<A>,
160
161 pub efficiency: EfficiencyMetrics<A>,
163}
164
165#[derive(Debug, Clone)]
167pub struct ThroughputMetrics {
168 pub samples_per_second: f64,
170
171 pub updates_per_second: f64,
173
174 pub gradients_per_second: f64,
176
177 pub peak_throughput: f64,
179
180 pub min_throughput: f64,
182
183 pub throughput_variance: f64,
185
186 pub throughput_trend: f64,
188}
189
190#[derive(Debug, Clone)]
192pub struct LatencyMetrics {
193 pub end_to_end: LatencyStats,
195
196 pub gradient_computation: Option<LatencyStats>,
198
199 pub update_application: Option<LatencyStats>,
201
202 pub communication: Option<LatencyStats>,
204
205 pub queue_wait_time: Option<LatencyStats>,
207
208 pub jitter: f64,
210}
211
212#[derive(Debug, Clone)]
214pub struct LatencyStats {
215 pub mean: Duration,
217
218 pub median: Duration,
220
221 pub p95: Duration,
223
224 pub p99: Duration,
226
227 pub p999: Duration,
229
230 pub max: Duration,
232
233 pub min: Duration,
235
236 pub std_dev: Duration,
238}
239
240#[derive(Debug, Clone)]
242pub struct AccuracyMetrics<A: Float + Send + Sync> {
243 pub current_loss: A,
245
246 pub loss_reduction_rate: A,
248
249 pub convergence_rate: A,
251
252 pub prediction_accuracy: Option<A>,
254
255 pub gradient_magnitude: A,
257
258 pub parameter_stability: A,
260
261 pub learning_progress: A,
263}
264
265#[derive(Debug, Clone)]
267pub struct StabilityMetrics<A: Float + Send + Sync> {
268 pub loss_variance: A,
270
271 pub gradient_variance: A,
273
274 pub parameter_drift: A,
276
277 pub oscillation_score: A,
279
280 pub divergence_probability: A,
282
283 pub stability_confidence: A,
285}
286
287#[derive(Debug, Clone)]
289pub struct EfficiencyMetrics<A: Float + Send + Sync> {
290 pub computational_efficiency: Option<A>,
292
293 pub memory_efficiency: Option<A>,
295
296 pub communication_efficiency: Option<A>,
299
300 pub energy_efficiency: Option<A>,
302
303 pub resource_utilization: A,
305
306 pub cost_efficiency: Option<A>,
308}
309
310#[derive(Debug, Clone, Default)]
316pub struct ResourceMetrics {
317 pub cpu_utilization: Option<f64>,
319
320 pub memory_usage: MemoryUsage,
322
323 pub gpu_utilization: Option<f64>,
325
326 pub network_bandwidth: Option<f64>,
328
329 pub disk_io: Option<f64>,
331
332 pub thread_utilization: Option<f64>,
334}
335
336#[derive(Debug, Clone, Default)]
338pub struct MemoryUsage {
339 pub total_allocated: Option<u64>,
341
342 pub current_used: u64,
344
345 pub peak_usage: u64,
347
348 pub fragmentation_ratio: Option<f64>,
350
351 pub gc_overhead: Option<f64>,
354
355 pub efficiency: Option<f64>,
357}
358
359#[derive(Debug, Clone)]
361pub struct QualityMetrics<A: Float + Send + Sync> {
362 pub data_quality: A,
364
365 pub model_quality: ModelQuality<A>,
367
368 pub concept_drift: ConceptDriftMetrics<A>,
370
371 pub anomaly_detection: AnomalyMetrics<A>,
373
374 pub robustness: RobustnessMetrics<A>,
376}
377
378#[derive(Debug, Clone)]
380pub struct ModelQuality<A: Float + Send + Sync> {
381 pub training_quality: A,
383
384 pub generalization_score: Option<A>,
386
387 pub overfitting_score: Option<A>,
389
390 pub underfitting_score: Option<A>,
392
393 pub complexity_score: Option<A>,
395}
396
397#[derive(Debug, Clone)]
399pub struct ConceptDriftMetrics<A: Float + Send + Sync> {
400 pub drift_confidence: Option<A>,
402
403 pub drift_magnitude: Option<A>,
405
406 pub drift_frequency: f64,
408
409 pub adaptation_effectiveness: Option<A>,
411
412 pub detection_latency: Option<Duration>,
414}
415
416#[derive(Debug, Clone)]
418pub struct AnomalyMetrics<A: Float + Send + Sync> {
419 pub anomaly_score: A,
421
422 pub false_positive_rate: Option<A>,
424
425 pub false_negative_rate: Option<A>,
427
428 pub detection_accuracy: Option<A>,
430
431 pub anomaly_frequency: f64,
433}
434
435#[derive(Debug, Clone, Default)]
439pub struct RobustnessMetrics<A: Float + Send + Sync> {
440 pub noise_tolerance: Option<A>,
442
443 pub adversarial_robustness: Option<A>,
445
446 pub perturbation_sensitivity: Option<A>,
448
449 pub recovery_capability: Option<A>,
451
452 pub fault_tolerance: Option<A>,
454}
455
456#[derive(Debug, Clone)]
458pub struct BusinessMetrics<A: Float + Send + Sync> {
459 pub availability: Option<f64>,
461
462 pub slo_compliance: Option<f64>,
464
465 pub cost_metrics: CostMetrics<A>,
467
468 pub user_satisfaction: Option<A>,
470
471 pub business_value: Option<A>,
473}
474
475#[derive(Debug, Clone, Default)]
477pub struct CostMetrics<A: Float + Send + Sync> {
478 pub computational_cost: Option<A>,
480
481 pub infrastructure_cost: Option<A>,
483
484 pub energy_cost: Option<A>,
486
487 pub opportunity_cost: Option<A>,
489
490 pub total_cost: Option<A>,
492}
493
494#[derive(Debug)]
496pub struct HistoricalMetrics<A: Float + Send + Sync> {
497 pub(crate) time_series: BTreeMap<u64, MetricsSnapshot<A>>,
506
507 pub(crate) retention_policy: RetentionPolicy,
509
510 pub(crate) compression_config: CompressionConfig,
512}
513
514#[derive(Debug, Clone)]
516pub struct MetricsSnapshot<A: Float + Send + Sync> {
517 pub timestamp: u64,
523
524 pub timestamp_micros: u64,
528
529 pub performance: PerformanceMetrics<A>,
531
532 pub resource: ResourceMetrics,
534
535 pub quality: QualityMetrics<A>,
537
538 pub business: BusinessMetrics<A>,
540}
541
542#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
544pub enum AggregationPeriod {
545 Minute,
546 Hour,
547 Day,
548 Week,
549 Month,
550}
551
552impl AggregationPeriod {
553 pub fn seconds(self) -> u64 {
555 match self {
556 AggregationPeriod::Minute => 60,
557 AggregationPeriod::Hour => 3_600,
558 AggregationPeriod::Day => 86_400,
559 AggregationPeriod::Week => 604_800,
560 AggregationPeriod::Month => 2_592_000, }
562 }
563}
564
565#[derive(Debug, Clone)]
573pub struct AggregatedMetrics {
574 pub period: AggregationPeriod,
576
577 pub period_start: u64,
579
580 pub period_end: u64,
582
583 pub sample_count: usize,
585
586 pub series: BTreeMap<String, AggregatedSeries>,
588}
589
590#[derive(Debug, Clone)]
592pub struct RetentionPolicy {
593 pub raw_data_retention: u64,
595
596 pub aggregated_retention: HashMap<AggregationPeriod, u64>,
598
599 pub auto_cleanup: bool,
601
602 pub max_storage_size: u64,
604}
605
606#[derive(Debug, Clone)]
608pub struct CompressionConfig {
609 pub enabled: bool,
611
612 pub algorithm: CompressionAlgorithm,
614
615 pub target_ratio: f64,
617
618 pub lossy_tolerance: f64,
620}
621
622#[derive(Debug, Clone, Copy, PartialEq, Eq)]
630pub enum CompressionAlgorithm {
631 None,
632 Gzip,
633 Lz4,
634 Zstd,
635 Custom,
636}
637
638#[derive(Debug)]
640pub struct Dashboard {
641 pub name: String,
643
644 pub widgets: Vec<Widget>,
646
647 pub update_frequency: Duration,
649
650 pub auto_refresh: bool,
652}
653
654#[derive(Debug)]
656pub struct Widget {
657 pub widget_type: WidgetType,
659
660 pub metrics: Vec<String>,
662
663 pub config: WidgetConfig,
665}
666
667#[derive(Debug, Clone)]
669pub enum WidgetType {
670 LineChart,
671 BarChart,
672 Gauge,
673 Table,
674 Heatmap,
675 Histogram,
676 ScatterPlot,
677 TextDisplay,
678}
679
680#[derive(Debug, Clone)]
682pub struct WidgetConfig {
683 pub title: String,
685
686 pub time_range: Duration,
688
689 pub refresh_rate: Duration,
691
692 pub color_scheme: String,
694
695 pub layout: WidgetLayout,
697}
698
699#[derive(Debug, Clone)]
701pub struct WidgetLayout {
702 pub x: u32,
704
705 pub y: u32,
707
708 pub width: u32,
710
711 pub height: u32,
713}
714
715#[derive(Debug)]
717pub struct AlertSystem<A: Float + Send + Sync> {
718 pub rules: Vec<AlertRule<A>>,
720
721 pub active_alerts: Vec<Alert<A>>,
723
724 pub alert_history: Vec<Alert<A>>,
726
727 pub notification_channels: Vec<NotificationChannel>,
729
730 pub(crate) rule_state: HashMap<String, alerts::RuleState>,
732
733 pub(crate) next_alert_id: u64,
735
736 pub(crate) max_history: usize,
738}
739
740#[derive(Debug, Clone)]
742pub struct AlertRule<A: Float + Send + Sync> {
743 pub name: String,
745
746 pub metric_path: String,
748
749 pub condition: AlertCondition<A>,
751
752 pub severity: AlertSeverity,
754
755 pub evaluation_frequency: Duration,
757
758 pub notifications: Vec<String>,
760}
761
762#[derive(Debug, Clone)]
764pub enum AlertCondition<A: Float + Send + Sync> {
765 Threshold {
767 operator: ComparisonOperator,
768 value: A,
769 },
770
771 RateOfChange { threshold: A, time_window: Duration },
773
774 Anomaly { sensitivity: A },
776
777 Custom { expression: String },
779}
780
781#[derive(Debug, Clone, Copy)]
783pub enum ComparisonOperator {
784 GreaterThan,
785 LessThan,
786 GreaterThanOrEqual,
787 LessThanOrEqual,
788 Equal,
789 NotEqual,
790}
791
792#[derive(Debug, Clone, Copy, PartialEq, Eq)]
794pub enum AlertSeverity {
795 Critical,
796 Warning,
797 Info,
798}
799
800#[derive(Debug, Clone)]
802pub struct Alert<A: Float + Send + Sync> {
803 pub id: String,
805
806 pub rule_name: String,
808
809 pub triggered_at: SystemTime,
811
812 pub resolved_at: Option<SystemTime>,
814
815 pub current_value: A,
817
818 pub threshold: A,
820
821 pub severity: AlertSeverity,
823
824 pub message: String,
826}
827
828#[derive(Debug, Clone)]
830pub enum NotificationChannel {
831 Email {
832 addresses: Vec<String>,
833 },
834 Webhook {
835 url: String,
836 headers: HashMap<String, String>,
837 },
838 Slack {
839 webhook_url: String,
840 channel: String,
841 },
842 PagerDuty {
843 integration_key: String,
844 },
845 Custom {
846 config: HashMap<String, String>,
847 },
848}
849
850#[derive(Debug, Clone)]
852pub struct AggregationConfig {
853 pub default_functions: Vec<AggregationFunction>,
855
856 pub custom_aggregations: HashMap<String, Vec<AggregationFunction>>,
858
859 pub intervals: Vec<Duration>,
861
862 pub max_window: Duration,
864}
865
866#[derive(Debug, Clone, Copy, PartialEq, Eq)]
868pub enum AggregationFunction {
869 Mean,
870 Median,
871 Min,
872 Max,
873 Sum,
874 Count,
875 StdDev,
876 Percentile(u8), }
878
879#[derive(Debug, Clone)]
881pub struct ExportConfig {
882 pub formats: Vec<ExportFormat>,
884
885 pub destinations: Vec<ExportDestination>,
887
888 pub frequency: Duration,
890
891 pub batch_size: usize,
893}
894
895#[derive(Debug, Clone, PartialEq, Eq)]
897pub enum ExportFormat {
898 Json,
899 Csv,
900 Parquet,
901 Prometheus,
902 InfluxDB,
903 Custom { format: String },
904}
905
906#[derive(Debug, Clone)]
908pub enum ExportDestination {
909 File {
910 path: String,
911 },
912 Database {
913 connection_string: String,
914 },
915 S3 {
916 bucket: String,
917 prefix: String,
918 },
919 Http {
920 endpoint: String,
921 headers: HashMap<String, String>,
922 },
923 Kafka {
924 topic: String,
925 brokers: Vec<String>,
926 },
927}
928
929impl<A: Float + Default + Clone + std::fmt::Debug + Send + Sync> StreamingMetricsCollector<A> {
930 pub fn new() -> Self {
932 Self::with_window(512)
933 }
934
935 pub fn with_window(window: usize) -> Self {
937 Self {
938 performance_metrics: PerformanceMetrics::default(),
939 resource_metrics: ResourceMetrics::default(),
940 quality_metrics: QualityMetrics::default(),
941 business_metrics: BusinessMetrics::default(),
942 historical_data: HistoricalMetrics::new(),
943 dashboards: Vec::new(),
944 alert_system: AlertSystem::new(),
945 aggregation_config: AggregationConfig::default(),
946 export_config: ExportConfig::default(),
947 accumulator: MetricsAccumulator::new(window),
948 slo: None,
949 cost_model: None,
950 last_export: None,
951 }
952 }
953
954 pub fn set_slo_targets(&mut self, targets: SloTargets) {
957 self.slo = if targets.is_empty() {
958 None
959 } else {
960 Some(targets)
961 };
962 }
963
964 pub fn set_cost_model(&mut self, model: CostModel<A>) {
966 self.cost_model = Some(model);
967 }
968
969 pub fn record_resource_probe(&mut self, probe: ResourceProbe) {
971 self.accumulator.record_resource_probe(probe);
972 }
973
974 pub fn record_robustness_probe(&mut self, probe: RobustnessProbe<A>) {
976 self.accumulator.record_robustness_probe(probe);
977 }
978
979 pub fn record_outage(&mut self, downtime: Duration) {
981 self.accumulator.record_outage(downtime);
982 }
983
984 pub fn record_drift_event(
986 &mut self,
987 magnitude: A,
988 confidence: A,
989 detection_latency: Duration,
990 adaptation_effectiveness: Option<A>,
991 ) {
992 self.accumulator.record_drift_event(
993 magnitude,
994 confidence,
995 detection_latency,
996 adaptation_effectiveness,
997 );
998 }
999
1000 pub fn record_energy(&mut self, joules: f64) {
1002 self.accumulator.record_energy(joules);
1003 }
1004
1005 pub fn record_sample(&mut self, sample: MetricsSample<A>) -> Result<()> {
1007 self.accumulator.ingest(&sample);
1008
1009 self.update_performance_metrics(&sample)?;
1011 self.update_resource_metrics(&sample)?;
1012 self.update_quality_metrics(&sample)?;
1013 self.update_business_metrics(&sample)?;
1014
1015 let timestamp = unix_timestamp(sample.timestamp);
1017 let timestamp_micros = unix_timestamp_micros(sample.timestamp);
1018
1019 let snapshot = MetricsSnapshot {
1020 timestamp,
1021 timestamp_micros,
1022 performance: self.performance_metrics.clone(),
1023 resource: self.resource_metrics.clone(),
1024 quality: self.quality_metrics.clone(),
1025 business: self.business_metrics.clone(),
1026 };
1027
1028 self.historical_data.store_snapshot(snapshot)?;
1029
1030 let summary = self.current_summary();
1032 self.alert_system.evaluate_rules(&sample, &summary)?;
1033
1034 Ok(())
1035 }
1036
1037 pub fn get_current_metrics(&self) -> MetricsSummary<A> {
1039 self.current_summary()
1040 }
1041
1042 pub(crate) fn current_summary(&self) -> MetricsSummary<A> {
1043 MetricsSummary {
1044 performance: self.performance_metrics.clone(),
1045 resource: self.resource_metrics.clone(),
1046 quality: self.quality_metrics.clone(),
1047 business: self.business_metrics.clone(),
1048 timestamp: SystemTime::now(),
1049 }
1050 }
1051
1052 pub fn get_historical_metrics(
1054 &self,
1055 start_time: SystemTime,
1056 end_time: SystemTime,
1057 ) -> Result<Vec<MetricsSnapshot<A>>> {
1058 self.historical_data.get_range(start_time, end_time)
1059 }
1060
1061 pub fn retained_snapshot_count(&self) -> usize {
1063 self.historical_data.time_series.len()
1064 }
1065
1066 pub fn add_alert_rule(&mut self, rule: AlertRule<A>) -> Result<()> {
1070 self.alert_system.add_rule(rule)
1071 }
1072
1073 pub fn active_alerts(&self) -> &[Alert<A>] {
1075 &self.alert_system.active_alerts
1076 }
1077
1078 pub fn alert_history(&self) -> &[Alert<A>] {
1080 &self.alert_system.alert_history
1081 }
1082
1083 pub fn add_dashboard(&mut self, dashboard: Dashboard) {
1085 self.dashboards.push(dashboard);
1086 }
1087
1088 pub fn render_dashboard(&self, name: &str) -> Option<Vec<(String, Option<f64>)>> {
1091 let dashboard = self.dashboards.iter().find(|d| d.name == name)?;
1092 let summary = self.current_summary();
1093 let mut resolved = Vec::new();
1094 for widget in &dashboard.widgets {
1095 for metric in &widget.metrics {
1096 resolved.push((metric.clone(), alerts::resolve_metric(&summary, metric)));
1097 }
1098 }
1099 Some(resolved)
1100 }
1101
1102 pub fn aggregation_config(&self) -> &AggregationConfig {
1104 &self.aggregation_config
1105 }
1106
1107 pub fn set_aggregation_config(&mut self, config: AggregationConfig) {
1109 self.aggregation_config = config;
1110 }
1111
1112 pub fn set_export_config(&mut self, config: ExportConfig) {
1114 self.export_config = config;
1115 }
1116
1117 pub fn set_retention_policy(&mut self, policy: RetentionPolicy) {
1124 self.historical_data.retention_policy = policy;
1125 self.historical_data.prune();
1126 }
1127
1128 pub fn set_compression_config(&mut self, config: CompressionConfig) {
1130 self.historical_data.compression_config = config;
1131 }
1132}
1133
1134impl<A: Float + Default + Clone + std::fmt::Debug + Send + Sync> Default
1135 for StreamingMetricsCollector<A>
1136{
1137 fn default() -> Self {
1138 Self::new()
1139 }
1140}
1141
1142#[derive(Debug, Clone)]
1144pub struct MetricsSample<A: Float + Send + Sync> {
1145 pub timestamp: SystemTime,
1147
1148 pub loss: A,
1150
1151 pub gradient_magnitude: A,
1153
1154 pub processing_time: Duration,
1156
1157 pub memory_usage: u64,
1159
1160 pub gradient_computation_time: Option<Duration>,
1162
1163 pub update_application_time: Option<Duration>,
1165
1166 pub communication_time: Option<Duration>,
1168
1169 pub queue_wait_time: Option<Duration>,
1171
1172 pub custom_metrics: HashMap<String, A>,
1174}
1175
1176impl<A: Float + Send + Sync> MetricsSample<A> {
1177 pub fn new(
1179 timestamp: SystemTime,
1180 loss: A,
1181 gradient_magnitude: A,
1182 processing_time: Duration,
1183 memory_usage: u64,
1184 ) -> Self {
1185 Self {
1186 timestamp,
1187 loss,
1188 gradient_magnitude,
1189 processing_time,
1190 memory_usage,
1191 gradient_computation_time: None,
1192 update_application_time: None,
1193 communication_time: None,
1194 queue_wait_time: None,
1195 custom_metrics: HashMap::new(),
1196 }
1197 }
1198}
1199
1200#[derive(Debug, Clone)]
1202pub struct MetricsSummary<A: Float + Send + Sync> {
1203 pub performance: PerformanceMetrics<A>,
1205
1206 pub resource: ResourceMetrics,
1208
1209 pub quality: QualityMetrics<A>,
1211
1212 pub business: BusinessMetrics<A>,
1214
1215 pub timestamp: SystemTime,
1217}
1218
1219impl<A: Float + Default + Send + Sync> Default for PerformanceMetrics<A> {
1221 fn default() -> Self {
1222 Self {
1223 throughput: ThroughputMetrics::default(),
1224 latency: LatencyMetrics::default(),
1225 accuracy: AccuracyMetrics::default(),
1226 stability: StabilityMetrics::default(),
1227 efficiency: EfficiencyMetrics::default(),
1228 }
1229 }
1230}
1231
1232impl Default for ThroughputMetrics {
1233 fn default() -> Self {
1234 Self {
1235 samples_per_second: 0.0,
1236 updates_per_second: 0.0,
1237 gradients_per_second: 0.0,
1238 peak_throughput: 0.0,
1239 min_throughput: f64::MAX,
1240 throughput_variance: 0.0,
1241 throughput_trend: 0.0,
1242 }
1243 }
1244}
1245
1246impl Default for LatencyMetrics {
1247 fn default() -> Self {
1248 Self {
1249 end_to_end: LatencyStats::default(),
1250 gradient_computation: None,
1251 update_application: None,
1252 communication: None,
1253 queue_wait_time: None,
1254 jitter: 0.0,
1255 }
1256 }
1257}
1258
1259impl Default for LatencyStats {
1260 fn default() -> Self {
1261 Self {
1262 mean: Duration::from_micros(0),
1263 median: Duration::from_micros(0),
1264 p95: Duration::from_micros(0),
1265 p99: Duration::from_micros(0),
1266 p999: Duration::from_micros(0),
1267 max: Duration::from_micros(0),
1268 min: Duration::from_micros(u64::MAX),
1269 std_dev: Duration::from_micros(0),
1270 }
1271 }
1272}
1273
1274impl<A: Float + Default + Send + Sync> Default for AccuracyMetrics<A> {
1275 fn default() -> Self {
1276 Self {
1277 current_loss: A::default(),
1278 loss_reduction_rate: A::default(),
1279 convergence_rate: A::default(),
1280 prediction_accuracy: None,
1281 gradient_magnitude: A::default(),
1282 parameter_stability: A::default(),
1283 learning_progress: A::default(),
1284 }
1285 }
1286}
1287
1288impl<A: Float + Default + Send + Sync> Default for StabilityMetrics<A> {
1289 fn default() -> Self {
1290 Self {
1291 loss_variance: A::default(),
1292 gradient_variance: A::default(),
1293 parameter_drift: A::default(),
1294 oscillation_score: A::default(),
1295 divergence_probability: A::default(),
1296 stability_confidence: A::default(),
1297 }
1298 }
1299}
1300
1301impl<A: Float + Default + Send + Sync> Default for EfficiencyMetrics<A> {
1302 fn default() -> Self {
1303 Self {
1304 computational_efficiency: None,
1305 memory_efficiency: None,
1306 communication_efficiency: None,
1307 energy_efficiency: None,
1308 resource_utilization: A::default(),
1309 cost_efficiency: None,
1310 }
1311 }
1312}
1313
1314impl<A: Float + Default + Send + Sync> Default for QualityMetrics<A> {
1315 fn default() -> Self {
1316 Self {
1317 data_quality: A::default(),
1318 model_quality: ModelQuality::default(),
1319 concept_drift: ConceptDriftMetrics::default(),
1320 anomaly_detection: AnomalyMetrics::default(),
1321 robustness: RobustnessMetrics::default(),
1322 }
1323 }
1324}
1325
1326impl<A: Float + Default + Send + Sync> Default for ModelQuality<A> {
1327 fn default() -> Self {
1328 Self {
1329 training_quality: A::default(),
1330 generalization_score: None,
1331 overfitting_score: None,
1332 underfitting_score: None,
1333 complexity_score: None,
1334 }
1335 }
1336}
1337
1338impl<A: Float + Default + Send + Sync> Default for ConceptDriftMetrics<A> {
1339 fn default() -> Self {
1340 Self {
1341 drift_confidence: None,
1342 drift_magnitude: None,
1343 drift_frequency: 0.0,
1344 adaptation_effectiveness: None,
1345 detection_latency: None,
1346 }
1347 }
1348}
1349
1350impl<A: Float + Default + Send + Sync> Default for AnomalyMetrics<A> {
1351 fn default() -> Self {
1352 Self {
1353 anomaly_score: A::default(),
1354 false_positive_rate: None,
1355 false_negative_rate: None,
1356 detection_accuracy: None,
1357 anomaly_frequency: 0.0,
1358 }
1359 }
1360}
1361
1362impl<A: Float + Default + Send + Sync> Default for BusinessMetrics<A> {
1363 fn default() -> Self {
1364 Self {
1365 availability: None,
1366 slo_compliance: None,
1367 cost_metrics: CostMetrics::default(),
1368 user_satisfaction: None,
1369 business_value: None,
1370 }
1371 }
1372}
1373
1374impl<A: Float + Send + Sync> HistoricalMetrics<A> {
1375 fn new() -> Self {
1376 Self {
1377 time_series: BTreeMap::new(),
1378 retention_policy: RetentionPolicy::default(),
1379 compression_config: CompressionConfig::default(),
1380 }
1381 }
1382}
1383
1384impl Default for RetentionPolicy {
1385 fn default() -> Self {
1386 let mut aggregated_retention = HashMap::new();
1387 aggregated_retention.insert(AggregationPeriod::Minute, 3600 * 24); aggregated_retention.insert(AggregationPeriod::Hour, 3600 * 24 * 7); aggregated_retention.insert(AggregationPeriod::Day, 3600 * 24 * 30); aggregated_retention.insert(AggregationPeriod::Week, 3600 * 24 * 365); aggregated_retention.insert(AggregationPeriod::Month, 3600 * 24 * 365 * 5); Self {
1394 raw_data_retention: 3600 * 24, aggregated_retention,
1396 auto_cleanup: true,
1397 max_storage_size: 1024 * 1024 * 1024 * 10, }
1399 }
1400}
1401
1402impl Default for CompressionConfig {
1403 fn default() -> Self {
1414 Self {
1415 enabled: false,
1416 algorithm: CompressionAlgorithm::None,
1417 target_ratio: 0.3,
1418 lossy_tolerance: 0.01,
1419 }
1420 }
1421}
1422
1423impl Default for AggregationConfig {
1424 fn default() -> Self {
1425 Self {
1426 default_functions: vec![
1427 AggregationFunction::Mean,
1428 AggregationFunction::Min,
1429 AggregationFunction::Max,
1430 AggregationFunction::StdDev,
1431 ],
1432 custom_aggregations: HashMap::new(),
1433 intervals: vec![
1434 Duration::from_secs(60), Duration::from_secs(3600), Duration::from_secs(86400), ],
1438 max_window: Duration::from_secs(86400 * 30), }
1440 }
1441}
1442
1443impl Default for ExportConfig {
1444 fn default() -> Self {
1445 Self {
1446 formats: vec![ExportFormat::Json],
1447 destinations: vec![ExportDestination::File {
1448 path: std::env::temp_dir()
1449 .join("streaming_metrics")
1450 .to_string_lossy()
1451 .into_owned(),
1452 }],
1453 frequency: Duration::from_secs(300), batch_size: 1000,
1455 }
1456 }
1457}
1458
1459#[cfg(test)]
1460mod tests {
1461 use super::*;
1462
1463 #[test]
1464 fn test_metrics_collector_creation() {
1465 let collector = StreamingMetricsCollector::<f64>::new();
1466 assert_eq!(
1467 collector.performance_metrics.throughput.samples_per_second,
1468 0.0
1469 );
1470 assert!(collector.dashboards.is_empty());
1471 }
1472
1473 #[test]
1474 fn test_metrics_sample() {
1475 let sample = MetricsSample::new(
1476 SystemTime::now(),
1477 0.5f64,
1478 0.1f64,
1479 Duration::from_millis(10),
1480 1024,
1481 );
1482
1483 assert_eq!(sample.loss, 0.5f64);
1484 assert_eq!(sample.gradient_magnitude, 0.1f64);
1485 }
1486
1487 #[test]
1488 fn test_latency_stats_default() {
1489 let stats = LatencyStats::default();
1490 assert_eq!(stats.mean, Duration::from_micros(0));
1491 assert_eq!(stats.min, Duration::from_micros(u64::MAX));
1492 }
1493
1494 #[test]
1495 fn test_aggregation_period() {
1496 let periods = [
1497 AggregationPeriod::Minute,
1498 AggregationPeriod::Hour,
1499 AggregationPeriod::Day,
1500 AggregationPeriod::Week,
1501 AggregationPeriod::Month,
1502 ];
1503
1504 assert_eq!(periods.len(), 5);
1505 }
1506
1507 #[test]
1508 fn test_alert_severity() {
1509 let severities = [
1510 AlertSeverity::Critical,
1511 AlertSeverity::Warning,
1512 AlertSeverity::Info,
1513 ];
1514
1515 assert_eq!(severities.len(), 3);
1516 }
1517}