1use sklears_core::error::Result as SklResult;
8use std::collections::{HashMap, VecDeque};
9use std::sync::{Arc, Mutex, RwLock};
10use std::time::{Duration, SystemTime};
11
12use crate::fault_core::{FailureDetectionConfig, FaultSeverity, StatisticalMethod};
13
14use super::statistics_tracking::RequestResult;
15
16#[derive(Debug)]
18pub struct CircuitBreakerFailureDetector {
19 config: FailureDetectionConfig,
21 sliding_window: Arc<Mutex<SlidingWindow>>,
23 statistical_analyzer: Arc<StatisticalAnalyzer>,
25 pattern_detector: Arc<PatternDetector>,
27 threshold_manager: Arc<ThresholdManager>,
29}
30
31#[derive(Debug)]
33pub struct SlidingWindow {
34 pub entries: VecDeque<WindowEntry>,
36 pub size: usize,
38 pub duration: Duration,
40 pub success_count: u64,
42 pub failure_count: u64,
44}
45
46#[derive(Debug, Clone)]
48pub struct WindowEntry {
49 pub timestamp: SystemTime,
51 pub result: RequestResult,
53 pub response_time: Duration,
55 pub error_details: Option<String>,
57}
58
59#[derive(Debug)]
61pub struct StatisticalAnalyzer {
62 method: StatisticalMethod,
64 confidence_level: f64,
66 historical_data: Arc<Mutex<Vec<DataPoint>>>,
68 analysis_cache: Arc<Mutex<AnalysisCache>>,
70}
71
72#[derive(Debug, Clone)]
74pub struct DataPoint {
75 pub timestamp: SystemTime,
77 pub value: f64,
79 pub data_type: DataType,
81 pub metadata: HashMap<String, String>,
83}
84
85#[derive(Debug, Clone, PartialEq)]
87pub enum DataType {
88 ErrorRate,
90 ResponseTime,
92 Throughput,
94 ResourceUtilization,
96 Custom(String),
98}
99
100#[derive(Debug)]
102pub struct AnalysisCache {
103 pub results: HashMap<String, AnalysisResult>,
105 pub timestamps: HashMap<String, SystemTime>,
107 pub ttl: Duration,
109}
110
111#[derive(Debug, Clone)]
113pub struct AnalysisResult {
114 pub id: String,
116 pub analysis_type: String,
118 pub value: f64,
120 pub confidence: f64,
122 pub timestamp: SystemTime,
124 pub metadata: HashMap<String, String>,
126}
127
128#[derive(Debug)]
130pub struct PatternDetector {
131 patterns: Arc<RwLock<Vec<FailurePattern>>>,
133 matching_engine: Arc<PatternMatchingEngine>,
135 learning_system: Arc<PatternLearningSystem>,
137}
138
139#[derive(Debug, Clone)]
141pub struct FailurePattern {
142 pub id: String,
144 pub name: String,
146 pub description: String,
148 pub signature: PatternSignature,
150 pub confidence_threshold: f64,
152 pub severity: FaultSeverity,
154 pub metadata: HashMap<String, String>,
156}
157
158#[derive(Debug, Clone)]
160pub struct PatternSignature {
161 pub error_rate_threshold: Option<f64>,
163 pub response_time_threshold: Option<Duration>,
165 pub error_message_patterns: Vec<String>,
167 pub temporal_patterns: Vec<TemporalPattern>,
169 pub resource_patterns: Vec<ResourcePattern>,
171}
172
173#[derive(Debug, Clone)]
175pub struct TemporalPattern {
176 pub pattern_type: TemporalPatternType,
178 pub time_window: Duration,
180 pub frequency_threshold: f64,
182 pub parameters: HashMap<String, f64>,
184}
185
186#[derive(Debug, Clone, PartialEq)]
188pub enum TemporalPatternType {
189 Periodic,
191 Burst,
193 Gradual,
195 Spike,
197 Custom(String),
199}
200
201#[derive(Debug, Clone)]
203pub struct ResourcePattern {
204 pub resource_type: String,
206 pub utilization_threshold: f64,
208 pub duration: Duration,
210 pub correlation_strength: f64,
212}
213
214pub struct PatternMatchingEngine {
216 algorithms: HashMap<String, Box<dyn PatternMatchingAlgorithm + Send + Sync>>,
218 cache: Arc<Mutex<MatchingCache>>,
220 metrics: Arc<Mutex<MatchingMetrics>>,
222}
223
224impl std::fmt::Debug for PatternMatchingEngine {
225 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
226 f.debug_struct("PatternMatchingEngine")
227 .field(
228 "algorithms",
229 &format!("<{} algorithms>", self.algorithms.len()),
230 )
231 .field("cache", &"<matching cache>")
232 .field("metrics", &"<matching metrics>")
233 .finish()
234 }
235}
236
237pub trait PatternMatchingAlgorithm: Send + Sync {
239 fn match_pattern(&self, pattern: &FailurePattern, data: &[DataPoint]) -> PatternMatch;
241
242 fn name(&self) -> &str;
244
245 fn parameters(&self) -> HashMap<String, String>;
247}
248
249#[derive(Debug, Clone)]
251pub struct PatternMatch {
252 pub pattern_id: String,
254 pub confidence: f64,
256 pub timestamp: SystemTime,
258 pub matching_points: Vec<usize>,
260 pub metadata: HashMap<String, String>,
262}
263
264#[derive(Debug, Default)]
266pub struct MatchingCache {
267 pub matches: HashMap<String, Vec<PatternMatch>>,
269 pub timestamps: HashMap<String, SystemTime>,
271 pub statistics: CacheStatistics,
273}
274
275#[derive(Debug, Default)]
277pub struct CacheStatistics {
278 pub hits: u64,
280 pub misses: u64,
282 pub evictions: u64,
284 pub memory_usage: u64,
286}
287
288#[derive(Debug, Default)]
290pub struct MatchingMetrics {
291 pub total_attempts: u64,
293 pub successful_matches: u64,
295 pub avg_matching_time: Duration,
297 pub pattern_accuracy: HashMap<String, f64>,
299}
300
301pub struct PatternLearningSystem {
303 algorithm: Box<dyn PatternLearningAlgorithm + Send + Sync>,
305 training_data: Arc<Mutex<Vec<TrainingExample>>>,
307 performance: Arc<Mutex<ModelPerformance>>,
309 config: LearningConfig,
311}
312
313impl std::fmt::Debug for PatternLearningSystem {
314 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
315 f.debug_struct("PatternLearningSystem")
316 .field("algorithm", &"<learning algorithm>")
317 .field("training_data", &"<training data>")
318 .field("performance", &"<model performance>")
319 .field("config", &self.config)
320 .finish()
321 }
322}
323
324pub trait PatternLearningAlgorithm: Send + Sync {
326 fn train(&mut self, examples: &[TrainingExample]) -> SklResult<()>;
328
329 fn predict(&self, data: &[DataPoint]) -> SklResult<Vec<PatternPrediction>>;
331
332 fn metadata(&self) -> HashMap<String, String>;
334}
335
336#[derive(Debug, Clone)]
338pub struct TrainingExample {
339 pub input: Vec<DataPoint>,
341 pub expected_pattern: Option<String>,
343 pub weight: f64,
345 pub metadata: HashMap<String, String>,
347}
348
349#[derive(Debug, Clone)]
351pub struct PatternPrediction {
352 pub pattern_id: String,
354 pub confidence: f64,
356 pub timestamp: SystemTime,
358 pub evidence: Vec<String>,
360}
361
362#[derive(Debug)]
364pub struct ModelPerformance {
365 pub accuracy: f64,
367 pub precision: f64,
369 pub recall: f64,
371 pub f1_score: f64,
373 pub training_examples: u64,
375 pub last_training: SystemTime,
377}
378
379impl Default for ModelPerformance {
380 fn default() -> Self {
381 Self {
382 accuracy: 0.0,
383 precision: 0.0,
384 recall: 0.0,
385 f1_score: 0.0,
386 training_examples: 0,
387 last_training: SystemTime::UNIX_EPOCH,
388 }
389 }
390}
391
392#[derive(Debug, Clone)]
394pub struct LearningConfig {
395 pub online_learning: bool,
397 pub batch_size: usize,
399 pub learning_rate: f64,
401 pub update_frequency: Duration,
403 pub retrain_threshold: f64,
405}
406
407#[derive(Debug)]
409pub struct ThresholdManager {
410 static_thresholds: HashMap<String, f64>,
412 dynamic_thresholds: Arc<RwLock<HashMap<String, DynamicThreshold>>>,
414 adaptive_calculator: Arc<AdaptiveThresholdCalculator>,
416 optimization_engine: Arc<ThresholdOptimizationEngine>,
418}
419
420#[derive(Debug, Clone)]
422pub struct DynamicThreshold {
423 pub value: f64,
425 pub range: ThresholdRange,
427 pub adjustment_factor: f64,
429 pub last_updated: SystemTime,
431 pub update_frequency: Duration,
433 pub metadata: HashMap<String, String>,
435}
436
437#[derive(Debug, Clone)]
439pub struct ThresholdRange {
440 pub min: f64,
442 pub max: f64,
444 pub default: f64,
446}
447
448pub struct AdaptiveThresholdCalculator {
450 performance_data: Arc<Mutex<Vec<PerformanceDataPoint>>>,
452 algorithms: HashMap<String, Box<dyn ThresholdCalculationAlgorithm + Send + Sync>>,
454 config: AdaptiveThresholdConfig,
456}
457
458impl std::fmt::Debug for AdaptiveThresholdCalculator {
459 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
460 f.debug_struct("AdaptiveThresholdCalculator")
461 .field("performance_data", &"<performance data>")
462 .field(
463 "algorithms",
464 &format!("<{} algorithms>", self.algorithms.len()),
465 )
466 .field("config", &self.config)
467 .finish()
468 }
469}
470
471#[derive(Debug, Clone)]
473pub struct PerformanceDataPoint {
474 pub timestamp: SystemTime,
476 pub metric: String,
478 pub value: f64,
480 pub context: SystemContext,
482}
483
484#[derive(Debug, Clone)]
486pub struct SystemContext {
487 pub cpu_utilization: f64,
489 pub memory_utilization: f64,
491 pub network_utilization: f64,
493 pub load_average: f64,
495 pub custom_metrics: HashMap<String, f64>,
497}
498
499pub trait ThresholdCalculationAlgorithm: Send + Sync {
501 fn calculate_threshold(&self, data: &[PerformanceDataPoint]) -> f64;
503
504 fn name(&self) -> &str;
506
507 fn config(&self) -> HashMap<String, String>;
509}
510
511#[derive(Debug, Clone)]
513pub struct AdaptiveThresholdConfig {
514 pub enabled: bool,
516 pub data_retention: Duration,
518 pub min_data_points: usize,
520 pub update_interval: Duration,
522 pub sensitivity: f64,
524}
525
526pub struct ThresholdOptimizationEngine {
528 objectives: Vec<OptimizationObjective>,
530 algorithms: HashMap<String, Box<dyn OptimizationAlgorithm + Send + Sync>>,
532 history: Arc<Mutex<Vec<OptimizationRun>>>,
534 config: OptimizationConfig,
536}
537
538impl std::fmt::Debug for ThresholdOptimizationEngine {
539 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
540 f.debug_struct("ThresholdOptimizationEngine")
541 .field("objectives", &self.objectives)
542 .field(
543 "algorithms",
544 &format!("<{} algorithms>", self.algorithms.len()),
545 )
546 .field("history", &"<optimization history>")
547 .field("config", &self.config)
548 .finish()
549 }
550}
551
552#[derive(Debug, Clone)]
554pub struct OptimizationObjective {
555 pub name: String,
557 pub objective_type: ObjectiveType,
559 pub target_value: f64,
561 pub weight: f64,
563 pub constraints: Vec<OptimizationConstraint>,
565}
566
567#[derive(Debug, Clone, PartialEq)]
569pub enum ObjectiveType {
570 Minimize,
572 Maximize,
574 Target,
576}
577
578#[derive(Debug, Clone)]
580pub struct OptimizationConstraint {
581 pub name: String,
583 pub constraint_type: ConstraintType,
585 pub value: f64,
587 pub tolerance: f64,
589}
590
591#[derive(Debug, Clone, PartialEq)]
593pub enum ConstraintType {
594 LessThan,
596 GreaterThan,
598 Equal,
600 Range,
602}
603
604pub trait OptimizationAlgorithm: Send + Sync {
606 fn optimize(
608 &self,
609 current_thresholds: &HashMap<String, f64>,
610 objectives: &[OptimizationObjective],
611 ) -> OptimizationResult;
612
613 fn name(&self) -> &str;
615
616 fn parameters(&self) -> HashMap<String, String>;
618}
619
620#[derive(Debug, Clone)]
622pub struct OptimizationResult {
623 pub thresholds: HashMap<String, f64>,
625 pub objective_values: HashMap<String, f64>,
627 pub score: f64,
629 pub convergence: ConvergenceInfo,
631 pub metadata: HashMap<String, String>,
633}
634
635#[derive(Debug, Clone)]
637pub struct ConvergenceInfo {
638 pub converged: bool,
640 pub iterations: u32,
642 pub final_error: f64,
644 pub convergence_time: Duration,
646}
647
648#[derive(Debug, Clone)]
650pub struct OptimizationRun {
651 pub id: String,
653 pub timestamp: SystemTime,
655 pub algorithm: String,
657 pub initial_thresholds: HashMap<String, f64>,
659 pub result: OptimizationResult,
661 pub duration: Duration,
663}
664
665#[derive(Debug, Clone)]
667pub struct OptimizationConfig {
668 pub enabled: bool,
670 pub interval: Duration,
672 pub max_time: Duration,
674 pub convergence_tolerance: f64,
676 pub performance_threshold: f64,
678}
679
680impl CircuitBreakerFailureDetector {
681 #[must_use]
683 pub fn new(config: FailureDetectionConfig) -> Self {
684 Self {
685 config,
686 sliding_window: Arc::new(Mutex::new(SlidingWindow {
687 entries: VecDeque::new(),
688 size: 100,
689 duration: Duration::from_secs(60),
690 success_count: 0,
691 failure_count: 0,
692 })),
693 statistical_analyzer: Arc::new(StatisticalAnalyzer {
694 method: StatisticalMethod::Simple,
695 confidence_level: 0.95,
696 historical_data: Arc::new(Mutex::new(Vec::new())),
697 analysis_cache: Arc::new(Mutex::new(AnalysisCache::default())),
698 }),
699 pattern_detector: Arc::new(PatternDetector {
700 patterns: Arc::new(RwLock::new(Vec::new())),
701 matching_engine: Arc::new(PatternMatchingEngine {
702 algorithms: HashMap::new(),
703 cache: Arc::new(Mutex::new(MatchingCache::default())),
704 metrics: Arc::new(Mutex::new(MatchingMetrics::default())),
705 }),
706 learning_system: Arc::new(PatternLearningSystem {
707 algorithm: Box::new(DummyLearningAlgorithm),
708 training_data: Arc::new(Mutex::new(Vec::new())),
709 performance: Arc::new(Mutex::new(ModelPerformance::default())),
710 config: LearningConfig {
711 online_learning: false,
712 batch_size: 100,
713 learning_rate: 0.01,
714 update_frequency: Duration::from_secs(3600),
715 retrain_threshold: 0.8,
716 },
717 }),
718 }),
719 threshold_manager: Arc::new(ThresholdManager {
720 static_thresholds: HashMap::new(),
721 dynamic_thresholds: Arc::new(RwLock::new(HashMap::new())),
722 adaptive_calculator: Arc::new(AdaptiveThresholdCalculator {
723 performance_data: Arc::new(Mutex::new(Vec::new())),
724 algorithms: HashMap::new(),
725 config: AdaptiveThresholdConfig {
726 enabled: true,
727 data_retention: Duration::from_secs(86400),
728 min_data_points: 50,
729 update_interval: Duration::from_secs(300),
730 sensitivity: 0.5,
731 },
732 }),
733 optimization_engine: Arc::new(ThresholdOptimizationEngine {
734 objectives: Vec::new(),
735 algorithms: HashMap::new(),
736 history: Arc::new(Mutex::new(Vec::new())),
737 config: OptimizationConfig {
738 enabled: false,
739 interval: Duration::from_secs(3600),
740 max_time: Duration::from_secs(300),
741 convergence_tolerance: 0.001,
742 performance_threshold: 0.8,
743 },
744 }),
745 }),
746 }
747 }
748
749 #[must_use]
751 pub fn should_trip(&self) -> bool {
752 let window = self.sliding_window.lock().unwrap();
754 window.failure_count > 5 }
756
757 pub fn record_request(
759 &self,
760 result: RequestResult,
761 response_time: Duration,
762 error_details: Option<String>,
763 ) {
764 let mut window = self.sliding_window.lock().unwrap();
765
766 let entry = WindowEntry {
767 timestamp: SystemTime::now(),
768 result: result.clone(),
769 response_time,
770 error_details,
771 };
772
773 window.entries.push_back(entry);
774
775 match result {
777 RequestResult::Success => {
778 window.success_count += 1;
779 }
780 RequestResult::Failure | RequestResult::Timeout => {
781 window.failure_count += 1;
782 }
783 _ => {}
784 }
785
786 if window.entries.len() > window.size {
788 if let Some(removed) = window.entries.pop_front() {
789 match removed.result {
790 RequestResult::Success => {
791 window.success_count = window.success_count.saturating_sub(1);
792 }
793 RequestResult::Failure | RequestResult::Timeout => {
794 window.failure_count = window.failure_count.saturating_sub(1);
795 }
796 _ => {}
797 }
798 }
799 }
800 }
801
802 #[must_use]
804 pub fn get_failure_rate(&self) -> f64 {
805 let window = self.sliding_window.lock().unwrap();
806 let total = window.success_count + window.failure_count;
807 if total > 0 {
808 window.failure_count as f64 / total as f64
809 } else {
810 0.0
811 }
812 }
813
814 #[must_use]
816 pub fn analyze_patterns(&self) -> Vec<PatternMatch> {
817 Vec::new()
819 }
820
821 pub fn update_thresholds(&self, performance_data: Vec<PerformanceDataPoint>) {
823 }
825
826 #[must_use]
828 pub fn get_config(&self) -> &FailureDetectionConfig {
829 &self.config
830 }
831
832 pub fn reset(&self) {
834 let mut window = self.sliding_window.lock().unwrap();
835 window.entries.clear();
836 window.success_count = 0;
837 window.failure_count = 0;
838 }
839}
840
841impl SlidingWindow {
842 #[must_use]
844 pub fn new(size: usize, duration: Duration) -> Self {
845 Self {
846 entries: VecDeque::new(),
847 size,
848 duration,
849 success_count: 0,
850 failure_count: 0,
851 }
852 }
853
854 #[must_use]
856 pub fn get_stats(&self) -> WindowStats {
857 WindowStats {
859 total_requests: self.entries.len() as u64,
860 success_count: self.success_count,
861 failure_count: self.failure_count,
862 failure_rate: if self.success_count + self.failure_count > 0 {
863 self.failure_count as f64 / (self.success_count + self.failure_count) as f64
864 } else {
865 0.0
866 },
867 }
868 }
869}
870
871#[derive(Debug, Clone)]
873pub struct WindowStats {
874 pub total_requests: u64,
876 pub success_count: u64,
878 pub failure_count: u64,
880 pub failure_rate: f64,
882}
883
884struct DummyLearningAlgorithm;
886
887impl PatternLearningAlgorithm for DummyLearningAlgorithm {
888 fn train(&mut self, _examples: &[TrainingExample]) -> SklResult<()> {
889 Ok(())
890 }
891
892 fn predict(&self, _data: &[DataPoint]) -> SklResult<Vec<PatternPrediction>> {
893 Ok(Vec::new())
894 }
895
896 fn metadata(&self) -> HashMap<String, String> {
897 HashMap::new()
898 }
899}
900
901impl Default for AnalysisCache {
902 fn default() -> Self {
903 Self {
904 results: HashMap::new(),
905 timestamps: HashMap::new(),
906 ttl: Duration::from_secs(300), }
908 }
909}
910
911impl Default for AdaptiveThresholdConfig {
912 fn default() -> Self {
913 Self {
914 enabled: true,
915 data_retention: Duration::from_secs(86400), min_data_points: 50,
917 update_interval: Duration::from_secs(300), sensitivity: 0.5,
919 }
920 }
921}
922
923impl Default for OptimizationConfig {
924 fn default() -> Self {
925 Self {
926 enabled: false,
927 interval: Duration::from_secs(3600), max_time: Duration::from_secs(300), convergence_tolerance: 0.001,
930 performance_threshold: 0.8,
931 }
932 }
933}
934
935impl Default for LearningConfig {
936 fn default() -> Self {
937 Self {
938 online_learning: false,
939 batch_size: 100,
940 learning_rate: 0.01,
941 update_frequency: Duration::from_secs(3600),
942 retrain_threshold: 0.8,
943 }
944 }
945}