1#![allow(dead_code)]
13use chrono::Timelike;
14use clap::ValueEnum;
15use serde::{Deserialize, Serialize};
16use std::collections::HashMap;
17use std::path::PathBuf;
18use std::time::{Duration, SystemTime, UNIX_EPOCH};
19use torsh_core::error::{Result, TorshError};
20
21pub struct AnalyticsManager {
23 usage_tracker: UsageTracker,
24 performance_profiler: PerformanceProfiler,
25 user_analytics: UserAnalytics,
26 ab_testing: ABTestingFramework,
27 recommendation_engine: RecommendationEngine,
28 storage_path: PathBuf,
29}
30
31pub struct UsageTracker {
33 model_usage: HashMap<String, ModelUsageStats>,
34 session_data: Vec<SessionData>,
35 real_time_metrics: RealTimeMetrics,
36}
37
38pub struct PerformanceProfiler {
40 profiling_data: HashMap<String, ModelPerformanceData>,
41 benchmark_results: Vec<BenchmarkResult>,
42 system_metrics: SystemMetrics,
43}
44
45pub struct UserAnalytics {
47 user_sessions: HashMap<String, Vec<UserSession>>,
48 interaction_patterns: InteractionPatterns,
49 user_preferences: HashMap<String, UserPreferences>,
50}
51
52pub struct ABTestingFramework {
54 active_tests: HashMap<String, ABTest>,
55 test_results: HashMap<String, ABTestResult>,
56 test_configurations: HashMap<String, ABTestConfig>,
57}
58
59pub struct RecommendationEngine {
61 model_similarities: HashMap<String, Vec<ModelSimilarity>>,
62 user_model_matrix: HashMap<String, HashMap<String, f32>>,
63 trending_models: Vec<TrendingModel>,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct ModelUsageStats {
69 pub model_id: String,
70 pub total_loads: u64,
71 pub total_inferences: u64,
72 pub total_runtime: Duration,
73 pub average_inference_time: Duration,
74 pub memory_usage: MemoryUsage,
75 pub error_rate: f32,
76 pub last_used: SystemTime,
77 pub popularity_score: f32,
78 pub daily_usage: HashMap<String, u64>, pub hourly_patterns: [u64; 24], }
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct RealTimeMetrics {
85 pub active_models: u32,
86 pub total_active_sessions: u32,
87 pub current_memory_usage: u64,
88 pub current_cpu_usage: f32,
89 pub requests_per_second: f32,
90 pub average_response_time: Duration,
91 pub error_rate_last_minute: f32,
92 pub timestamp: SystemTime,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct SessionData {
98 pub session_id: String,
99 pub user_id: Option<String>,
100 pub start_time: SystemTime,
101 pub end_time: Option<SystemTime>,
102 pub models_used: Vec<String>,
103 pub total_inferences: u32,
104 pub errors_encountered: u32,
105 pub user_agent: Option<String>,
106 pub ip_address: Option<String>,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct MemoryUsage {
112 pub peak_memory: u64,
113 pub average_memory: u64,
114 pub memory_efficiency: f32,
115 pub gc_pressure: f32,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct ModelPerformanceData {
121 pub model_id: String,
122 pub inference_times: Vec<Duration>,
123 pub throughput_data: Vec<ThroughputMeasurement>,
124 pub resource_utilization: ResourceUtilization,
125 pub bottlenecks: Vec<PerformanceBottleneck>,
126 pub optimization_suggestions: Vec<OptimizationSuggestion>,
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct ThroughputMeasurement {
132 pub timestamp: SystemTime,
133 pub requests_per_second: f32,
134 pub batch_size: u32,
135 pub concurrent_requests: u32,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize, Default)]
140pub struct ResourceUtilization {
141 pub cpu_usage: Vec<f32>,
142 pub memory_usage: Vec<u64>,
143 pub gpu_usage: Option<Vec<f32>>,
144 pub io_usage: IOMetrics,
145 pub network_usage: NetworkMetrics,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct PerformanceBottleneck {
151 pub bottleneck_type: BottleneckType,
152 pub severity: BottleneckSeverity,
153 pub description: String,
154 pub impact_percentage: f32,
155 pub suggestions: Vec<String>,
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize)]
159pub enum BottleneckType {
160 CPU,
161 Memory,
162 IO,
163 Network,
164 ModelComputation,
165 DataLoading,
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
169pub enum BottleneckSeverity {
170 Low,
171 Medium,
172 High,
173 Critical,
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct OptimizationSuggestion {
179 pub suggestion_type: OptimizationType,
180 pub description: String,
181 pub expected_improvement: f32,
182 pub implementation_difficulty: DifficultyLevel,
183 pub estimated_cost: EstimatedCost,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
187pub enum OptimizationType {
188 ModelQuantization,
189 BatchSizeOptimization,
190 CachingStrategy,
191 HardwareUpgrade,
192 AlgorithmicOptimization,
193 DataPipeline,
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize)]
197pub enum DifficultyLevel {
198 Easy,
199 Medium,
200 Hard,
201 Expert,
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize)]
205pub enum EstimatedCost {
206 Free,
207 Low,
208 Medium,
209 High,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct SystemMetrics {
215 pub cpu_info: CPUInfo,
216 pub memory_info: MemoryInfo,
217 pub disk_info: DiskInfo,
218 pub network_info: NetworkInfo,
219 pub gpu_info: Option<GPUInfo>,
220}
221
222#[derive(Debug, Clone, Serialize, Deserialize)]
224pub struct BenchmarkResult {
225 pub model_id: String,
226 pub benchmark_type: BenchmarkType,
227 pub score: f32,
228 pub details: HashMap<String, f32>,
229 pub timestamp: SystemTime,
230 pub environment: BenchmarkEnvironment,
231}
232
233#[derive(Debug, Clone, Serialize, Deserialize)]
234pub enum BenchmarkType {
235 Latency,
236 Throughput,
237 Accuracy,
238 MemoryEfficiency,
239 EnergyEfficiency,
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize)]
244pub struct UserSession {
245 pub session_id: String,
246 pub start_time: SystemTime,
247 pub duration: Duration,
248 pub actions: Vec<UserAction>,
249 pub models_accessed: Vec<String>,
250 pub success_rate: f32,
251}
252
253#[derive(Debug, Clone, Serialize, Deserialize)]
255pub struct UserAction {
256 pub action_type: ActionType,
257 pub timestamp: SystemTime,
258 pub model_id: Option<String>,
259 pub parameters: HashMap<String, String>,
260 pub success: bool,
261 pub error_message: Option<String>,
262}
263
264#[derive(Debug, Clone, Serialize, Deserialize)]
265pub enum ActionType {
266 ModelLoad,
267 ModelInference,
268 ModelDownload,
269 ModelSearch,
270 ModelRate,
271 ModelShare,
272 ProfileView,
273 SettingsChange,
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize, Default)]
278pub struct InteractionPatterns {
279 pub most_popular_models: Vec<String>,
280 pub common_workflows: Vec<Workflow>,
281 pub usage_patterns_by_time: HashMap<String, Vec<u32>>,
282 pub model_transition_matrix: HashMap<String, HashMap<String, f32>>,
283}
284
285#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct Workflow {
288 pub name: String,
289 pub steps: Vec<WorkflowStep>,
290 pub frequency: u32,
291 pub success_rate: f32,
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct WorkflowStep {
296 pub action: ActionType,
297 pub model_category: Option<String>,
298 pub typical_duration: Duration,
299}
300
301#[derive(Debug, Clone, Serialize, Deserialize)]
303pub struct UserPreferences {
304 pub preferred_model_types: Vec<String>,
305 pub performance_vs_accuracy_preference: f32, pub preferred_model_size: ModelSizePreference,
307 pub usage_patterns: HashMap<String, f32>,
308}
309
310#[derive(Debug, Clone, Serialize, Deserialize)]
311pub enum ModelSizePreference {
312 Small,
313 Medium,
314 Large,
315 Any,
316}
317
318#[derive(Debug, Clone, Serialize, Deserialize)]
320pub struct ABTestConfig {
321 pub test_name: String,
322 pub description: String,
323 pub models_to_test: Vec<String>,
324 pub traffic_split: HashMap<String, f32>,
325 pub success_metrics: Vec<String>,
326 pub min_sample_size: u32,
327 pub max_duration: Duration,
328 pub confidence_level: f32,
329}
330
331#[derive(Debug, Clone, Serialize, Deserialize)]
333pub struct ABTest {
334 pub config: ABTestConfig,
335 pub start_time: SystemTime,
336 pub current_assignments: HashMap<String, String>, pub metrics: HashMap<String, ABTestMetrics>,
338 pub status: ABTestStatus,
339}
340
341#[derive(Debug, Clone, Serialize, Deserialize)]
342pub enum ABTestStatus {
343 Running,
344 Completed,
345 Stopped,
346 Failed,
347}
348
349#[derive(Debug, Clone, Serialize, Deserialize)]
351pub struct ABTestMetrics {
352 pub model_id: String,
353 pub sample_size: u32,
354 pub conversion_rate: f32,
355 pub average_satisfaction: f32,
356 pub error_rate: f32,
357 pub performance_metrics: HashMap<String, f32>,
358}
359
360#[derive(Debug, Clone, Serialize, Deserialize)]
362pub struct ABTestResult {
363 pub test_name: String,
364 pub winner: Option<String>,
365 pub confidence: f32,
366 pub effect_size: f32,
367 pub p_value: f32,
368 pub metrics_comparison: HashMap<String, ABTestMetrics>,
369 pub recommendation: String,
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize)]
374pub struct ModelSimilarity {
375 pub model_id: String,
376 pub similarity_score: f32,
377 pub similarity_type: SimilarityType,
378}
379
380#[derive(Debug, Clone, Serialize, Deserialize)]
381pub enum SimilarityType {
382 ContentBased, Collaborative, Hybrid, }
386
387#[derive(Debug, Clone, Serialize, Deserialize)]
389pub struct TrendingModel {
390 pub model_id: String,
391 pub trend_score: f32,
392 pub growth_rate: f32,
393 pub velocity: f32, pub reasons: Vec<TrendReason>,
395}
396
397#[derive(Debug, Clone, Serialize, Deserialize)]
398pub enum TrendReason {
399 HighAccuracy,
400 FastInference,
401 RecentRelease,
402 CommunityRecommendation,
403 MediaCoverage,
404 ResearchBreakthrough,
405}
406
407#[derive(Debug, Clone, Serialize, Deserialize)]
409pub struct CPUInfo {
410 pub cores: u32,
411 pub threads: u32,
412 pub model: String,
413 pub frequency: f32,
414}
415
416#[derive(Debug, Clone, Serialize, Deserialize)]
417pub struct MemoryInfo {
418 pub total: u64,
419 pub available: u64,
420 pub used: u64,
421}
422
423#[derive(Debug, Clone, Serialize, Deserialize)]
424pub struct DiskInfo {
425 pub total: u64,
426 pub available: u64,
427 pub read_speed: f32,
428 pub write_speed: f32,
429}
430
431#[derive(Debug, Clone, Serialize, Deserialize)]
432pub struct NetworkInfo {
433 pub bandwidth: f32,
434 pub latency: Duration,
435}
436
437#[derive(Debug, Clone, Serialize, Deserialize)]
438pub struct GPUInfo {
439 pub model: String,
440 pub memory: u64,
441 pub compute_capability: String,
442}
443
444#[derive(Debug, Clone, Serialize, Deserialize)]
445pub struct IOMetrics {
446 pub read_bytes_per_sec: f32,
447 pub write_bytes_per_sec: f32,
448 pub read_ops_per_sec: f32,
449 pub write_ops_per_sec: f32,
450}
451
452#[derive(Debug, Clone, Serialize, Deserialize)]
453pub struct NetworkMetrics {
454 pub bytes_sent_per_sec: f32,
455 pub bytes_received_per_sec: f32,
456 pub packets_sent_per_sec: f32,
457 pub packets_received_per_sec: f32,
458}
459
460#[derive(Debug, Clone, Serialize, Deserialize)]
461pub struct BenchmarkEnvironment {
462 pub hardware: SystemMetrics,
463 pub software_versions: HashMap<String, String>,
464 pub configuration: HashMap<String, String>,
465}
466
467impl AnalyticsManager {
468 pub fn new(storage_path: PathBuf) -> Result<Self> {
470 std::fs::create_dir_all(&storage_path).map_err(|e| TorshError::IoError(e.to_string()))?;
471
472 Ok(Self {
473 usage_tracker: UsageTracker::new(),
474 performance_profiler: PerformanceProfiler::new(),
475 user_analytics: UserAnalytics::new(),
476 ab_testing: ABTestingFramework::new(),
477 recommendation_engine: RecommendationEngine::new(),
478 storage_path,
479 })
480 }
481
482 pub fn track_model_usage(&mut self, model_id: &str, inference_time: Duration) -> Result<()> {
484 self.usage_tracker.track_usage(model_id, inference_time)
485 }
486
487 pub fn start_profiling(&mut self, model_id: &str) -> Result<String> {
489 self.performance_profiler.start_profiling(model_id)
490 }
491
492 pub fn stop_profiling(&mut self, profile_id: &str) -> Result<ModelPerformanceData> {
494 self.performance_profiler.stop_profiling(profile_id)
495 }
496
497 pub fn record_user_action(&mut self, user_id: &str, action: UserAction) -> Result<()> {
499 self.user_analytics.record_action(user_id, action)
500 }
501
502 pub fn start_ab_test(&mut self, config: ABTestConfig) -> Result<String> {
504 self.ab_testing.start_test(config)
505 }
506
507 pub fn get_recommendations(&self, user_id: &str, count: usize) -> Result<Vec<String>> {
509 self.recommendation_engine
510 .get_recommendations(user_id, count)
511 }
512
513 pub fn get_real_time_metrics(&self) -> RealTimeMetrics {
515 self.usage_tracker.get_real_time_metrics()
516 }
517
518 pub fn generate_report(&self, model_id: Option<&str>) -> Result<AnalyticsReport> {
520 let usage_stats = if let Some(id) = model_id {
521 self.usage_tracker.get_model_stats(id).cloned()
522 } else {
523 None
524 };
525
526 let performance_data = if let Some(id) = model_id {
527 self.performance_profiler.get_performance_data(id).cloned()
528 } else {
529 None
530 };
531
532 Ok(AnalyticsReport {
533 timestamp: SystemTime::now(),
534 model_id: model_id.map(String::from),
535 usage_stats,
536 performance_data,
537 real_time_metrics: self.get_real_time_metrics(),
538 trending_models: self.recommendation_engine.get_trending_models(10),
539 system_health: self.get_system_health(),
540 })
541 }
542
543 pub fn export_data(
545 &self,
546 format: ExportFormat,
547 start_date: SystemTime,
548 end_date: SystemTime,
549 ) -> Result<String> {
550 let data = self.collect_data_for_period(start_date, end_date)?;
551
552 match format {
553 ExportFormat::JSON => Ok(serde_json::to_string_pretty(&data)?),
554 ExportFormat::CSV => self.export_to_csv(&data),
555 ExportFormat::Excel => self.export_to_excel(&data),
556 }
557 }
558
559 fn get_system_health(&self) -> SystemHealth {
561 SystemHealth {
562 overall_status: HealthStatus::Healthy,
563 cpu_health: HealthStatus::Healthy,
564 memory_health: HealthStatus::Healthy,
565 disk_health: HealthStatus::Healthy,
566 network_health: HealthStatus::Healthy,
567 alerts: vec![],
568 recommendations: vec![],
569 }
570 }
571
572 fn collect_data_for_period(
573 &self,
574 _start: SystemTime,
575 _end: SystemTime,
576 ) -> Result<AnalyticsExportData> {
577 Ok(AnalyticsExportData {
579 usage_data: HashMap::new(),
580 performance_data: HashMap::new(),
581 user_data: HashMap::new(),
582 ab_test_data: HashMap::new(),
583 })
584 }
585
586 fn export_to_csv(&self, _data: &AnalyticsExportData) -> Result<String> {
587 Ok("CSV data here".to_string())
589 }
590
591 fn export_to_excel(&self, _data: &AnalyticsExportData) -> Result<String> {
592 Ok("Excel data here".to_string())
594 }
595}
596
597impl UsageTracker {
598 fn new() -> Self {
599 Self {
600 model_usage: HashMap::new(),
601 session_data: Vec::new(),
602 real_time_metrics: RealTimeMetrics::default(),
603 }
604 }
605
606 fn track_usage(&mut self, model_id: &str, inference_time: Duration) -> Result<()> {
607 let stats = self
608 .model_usage
609 .entry(model_id.to_string())
610 .or_insert_with(|| ModelUsageStats {
611 model_id: model_id.to_string(),
612 total_loads: 0,
613 total_inferences: 0,
614 total_runtime: Duration::from_secs(0),
615 average_inference_time: Duration::from_secs(0),
616 memory_usage: MemoryUsage::default(),
617 error_rate: 0.0,
618 last_used: SystemTime::now(),
619 popularity_score: 0.0,
620 daily_usage: HashMap::new(),
621 hourly_patterns: [0; 24],
622 });
623
624 stats.total_inferences += 1;
625 stats.total_runtime += inference_time;
626 stats.average_inference_time = stats.total_runtime / stats.total_inferences as u32;
627 stats.last_used = SystemTime::now();
628
629 let today = chrono::Utc::now().format("%Y-%m-%d").to_string();
631 *stats.daily_usage.entry(today).or_insert(0) += 1;
632
633 let hour = chrono::Utc::now().hour() as usize;
635 stats.hourly_patterns[hour] += 1;
636
637 Ok(())
638 }
639
640 fn get_model_stats(&self, model_id: &str) -> Option<&ModelUsageStats> {
641 self.model_usage.get(model_id)
642 }
643
644 fn get_real_time_metrics(&self) -> RealTimeMetrics {
645 self.real_time_metrics.clone()
646 }
647}
648
649impl PerformanceProfiler {
650 fn new() -> Self {
651 Self {
652 profiling_data: HashMap::new(),
653 benchmark_results: Vec::new(),
654 system_metrics: SystemMetrics::default(),
655 }
656 }
657
658 fn start_profiling(&mut self, model_id: &str) -> Result<String> {
659 let profile_id = format!(
660 "{}_{}",
661 model_id,
662 SystemTime::now()
663 .duration_since(UNIX_EPOCH)
664 .expect("system time should be after UNIX epoch")
665 .as_secs()
666 );
667 Ok(profile_id)
669 }
670
671 fn stop_profiling(&mut self, _profile_id: &str) -> Result<ModelPerformanceData> {
672 Ok(ModelPerformanceData {
674 model_id: "test".to_string(),
675 inference_times: vec![],
676 throughput_data: vec![],
677 resource_utilization: ResourceUtilization::default(),
678 bottlenecks: vec![],
679 optimization_suggestions: vec![],
680 })
681 }
682
683 fn get_performance_data(&self, model_id: &str) -> Option<&ModelPerformanceData> {
684 self.profiling_data.get(model_id)
685 }
686}
687
688impl UserAnalytics {
689 fn new() -> Self {
690 Self {
691 user_sessions: HashMap::new(),
692 interaction_patterns: InteractionPatterns::default(),
693 user_preferences: HashMap::new(),
694 }
695 }
696
697 fn record_action(&mut self, user_id: &str, action: UserAction) -> Result<()> {
698 let _sessions = self.user_sessions.entry(user_id.to_string()).or_default();
699
700 println!(
702 "Recording action for user {}: {:?}",
703 user_id, action.action_type
704 );
705
706 Ok(())
707 }
708}
709
710impl ABTestingFramework {
711 fn new() -> Self {
712 Self {
713 active_tests: HashMap::new(),
714 test_results: HashMap::new(),
715 test_configurations: HashMap::new(),
716 }
717 }
718
719 fn start_test(&mut self, config: ABTestConfig) -> Result<String> {
720 let test_id = format!(
721 "test_{}",
722 SystemTime::now()
723 .duration_since(UNIX_EPOCH)
724 .expect("system time should be after UNIX epoch")
725 .as_secs()
726 );
727
728 let test = ABTest {
729 config: config.clone(),
730 start_time: SystemTime::now(),
731 current_assignments: HashMap::new(),
732 metrics: HashMap::new(),
733 status: ABTestStatus::Running,
734 };
735
736 self.active_tests.insert(test_id.clone(), test);
737 self.test_configurations.insert(test_id.clone(), config);
738
739 Ok(test_id)
740 }
741}
742
743impl RecommendationEngine {
744 fn new() -> Self {
745 Self {
746 model_similarities: HashMap::new(),
747 user_model_matrix: HashMap::new(),
748 trending_models: Vec::new(),
749 }
750 }
751
752 fn get_recommendations(&self, _user_id: &str, count: usize) -> Result<Vec<String>> {
753 Ok(self
755 .trending_models
756 .iter()
757 .take(count)
758 .map(|m| m.model_id.clone())
759 .collect())
760 }
761
762 fn get_trending_models(&self, count: usize) -> Vec<TrendingModel> {
763 self.trending_models.iter().take(count).cloned().collect()
764 }
765}
766
767#[derive(Debug, Clone, Serialize, Deserialize)]
769pub struct AnalyticsReport {
770 pub timestamp: SystemTime,
771 pub model_id: Option<String>,
772 pub usage_stats: Option<ModelUsageStats>,
773 pub performance_data: Option<ModelPerformanceData>,
774 pub real_time_metrics: RealTimeMetrics,
775 pub trending_models: Vec<TrendingModel>,
776 pub system_health: SystemHealth,
777}
778
779#[derive(Debug, Clone, Serialize, Deserialize)]
781pub struct SystemHealth {
782 pub overall_status: HealthStatus,
783 pub cpu_health: HealthStatus,
784 pub memory_health: HealthStatus,
785 pub disk_health: HealthStatus,
786 pub network_health: HealthStatus,
787 pub alerts: Vec<HealthAlert>,
788 pub recommendations: Vec<String>,
789}
790
791#[derive(Debug, Clone, Serialize, Deserialize)]
792pub enum HealthStatus {
793 Healthy,
794 Warning,
795 Critical,
796 Unknown,
797}
798
799#[derive(Debug, Clone, Serialize, Deserialize)]
800pub struct HealthAlert {
801 pub alert_type: AlertType,
802 pub severity: AlertSeverity,
803 pub message: String,
804 pub timestamp: SystemTime,
805}
806
807#[derive(Debug, Clone, Serialize, Deserialize)]
808pub enum AlertType {
809 HighCPUUsage,
810 LowMemory,
811 DiskSpaceLow,
812 NetworkLatency,
813 ModelError,
814 SystemError,
815}
816
817#[derive(Debug, Clone, Serialize, Deserialize)]
818pub enum AlertSeverity {
819 Info,
820 Warning,
821 Error,
822 Critical,
823}
824
825#[derive(Debug, Clone, ValueEnum)]
827pub enum ExportFormat {
828 JSON,
829 CSV,
830 Excel,
831}
832
833#[derive(Debug, Clone, Serialize, Deserialize)]
835pub struct AnalyticsExportData {
836 pub usage_data: HashMap<String, ModelUsageStats>,
837 pub performance_data: HashMap<String, ModelPerformanceData>,
838 pub user_data: HashMap<String, Vec<UserSession>>,
839 pub ab_test_data: HashMap<String, ABTestResult>,
840}
841
842impl Default for RealTimeMetrics {
844 fn default() -> Self {
845 Self {
846 active_models: 0,
847 total_active_sessions: 0,
848 current_memory_usage: 0,
849 current_cpu_usage: 0.0,
850 requests_per_second: 0.0,
851 average_response_time: Duration::from_millis(0),
852 error_rate_last_minute: 0.0,
853 timestamp: SystemTime::now(),
854 }
855 }
856}
857
858impl Default for MemoryUsage {
859 fn default() -> Self {
860 Self {
861 peak_memory: 0,
862 average_memory: 0,
863 memory_efficiency: 1.0,
864 gc_pressure: 0.0,
865 }
866 }
867}
868
869impl Default for IOMetrics {
870 fn default() -> Self {
871 Self {
872 read_bytes_per_sec: 0.0,
873 write_bytes_per_sec: 0.0,
874 read_ops_per_sec: 0.0,
875 write_ops_per_sec: 0.0,
876 }
877 }
878}
879
880impl Default for NetworkMetrics {
881 fn default() -> Self {
882 Self {
883 bytes_sent_per_sec: 0.0,
884 bytes_received_per_sec: 0.0,
885 packets_sent_per_sec: 0.0,
886 packets_received_per_sec: 0.0,
887 }
888 }
889}
890
891impl Default for SystemMetrics {
892 fn default() -> Self {
893 Self {
894 cpu_info: CPUInfo {
895 cores: 1,
896 threads: 1,
897 model: "Unknown".to_string(),
898 frequency: 0.0,
899 },
900 memory_info: MemoryInfo {
901 total: 0,
902 available: 0,
903 used: 0,
904 },
905 disk_info: DiskInfo {
906 total: 0,
907 available: 0,
908 read_speed: 0.0,
909 write_speed: 0.0,
910 },
911 network_info: NetworkInfo {
912 bandwidth: 0.0,
913 latency: Duration::from_millis(0),
914 },
915 gpu_info: None,
916 }
917 }
918}
919
920#[cfg(test)]
921mod tests {
922 use super::*;
923 use std::time::Duration;
924
925 #[test]
926 fn test_analytics_manager_creation() {
927 let temp_dir = std::env::temp_dir().join("torsh_analytics_test");
928 let manager = AnalyticsManager::new(temp_dir);
929 assert!(manager.is_ok());
930 }
931
932 #[test]
933 fn test_usage_tracking() {
934 let temp_dir = std::env::temp_dir().join("torsh_analytics_test2");
935 let mut manager = AnalyticsManager::new(temp_dir).unwrap();
936
937 let result = manager.track_model_usage("test_model", Duration::from_millis(100));
938 assert!(result.is_ok());
939
940 let stats = manager.usage_tracker.get_model_stats("test_model");
941 assert!(stats.is_some());
942 assert_eq!(stats.unwrap().total_inferences, 1);
943 }
944
945 #[test]
946 fn test_ab_test_creation() {
947 let temp_dir = std::env::temp_dir().join("torsh_analytics_test3");
948 let mut manager = AnalyticsManager::new(temp_dir).unwrap();
949
950 let config = ABTestConfig {
951 test_name: "test_comparison".to_string(),
952 description: "Testing model A vs B".to_string(),
953 models_to_test: vec!["model_a".to_string(), "model_b".to_string()],
954 traffic_split: [("model_a".to_string(), 0.5), ("model_b".to_string(), 0.5)]
955 .iter()
956 .cloned()
957 .collect(),
958 success_metrics: vec!["accuracy".to_string()],
959 min_sample_size: 100,
960 max_duration: Duration::from_secs(3600),
961 confidence_level: 0.95,
962 };
963
964 let test_id = manager.start_ab_test(config);
965 assert!(test_id.is_ok());
966 }
967
968 #[test]
969 fn test_real_time_metrics() {
970 let temp_dir = std::env::temp_dir().join("torsh_analytics_test4");
971 let manager = AnalyticsManager::new(temp_dir).unwrap();
972
973 let metrics = manager.get_real_time_metrics();
974 assert_eq!(metrics.active_models, 0);
975 assert_eq!(metrics.total_active_sessions, 0);
976 }
977}