1use std::{
187 collections::{HashMap, HashSet},
188 sync::{Arc, Mutex},
189 time::{Duration, SystemTime},
190};
191
192use log::{debug, error, info, warn};
193use serde::{Deserialize, Serialize};
194use tauri::{AppHandle, Emitter, Manager};
195use tokio::sync::RwLock;
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
199pub struct ComprehensiveStatusReport {
200 pub basic_status:IPCStatusReport,
201 pub performance_metrics:PerformanceMetrics,
202 pub health_status:HealthMonitor,
203 pub timestamp:u64,
204}
205
206#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct PerformanceMetrics {
209 pub messages_per_second:f64,
210 pub average_latency_ms:f64,
211 pub peak_latency_ms:f64,
212 pub compression_ratio:f64,
213 pub connection_pool_utilization:f64,
214 pub memory_usage_mb:f64,
215 pub cpu_usage_percent:f64,
216 pub last_update:u64,
217}
218
219#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct HealthMonitor {
222 pub health_score:f64,
223 pub last_health_check:u64,
224 pub issues_detected:Vec<HealthIssue>,
225 pub recovery_attempts:u32,
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize)]
229pub struct HealthIssue {
230 pub issue_type:HealthIssueType,
231 pub severity:SeverityLevel,
232 pub description:String,
233 pub detected_at:u64,
234 pub resolved_at:Option<u64>,
235}
236
237#[derive(Debug, Clone, Serialize, Deserialize)]
238pub enum HealthIssueType {
239 HighLatency,
240 MemoryPressure,
241 ConnectionLoss,
242 QueueOverflow,
243 SecurityViolation,
244 PerformanceDegradation,
245}
246
247#[derive(Debug, Clone, Serialize, Deserialize)]
248pub enum SeverityLevel {
249 Low,
250 Medium,
251 High,
252 Critical,
253}
254
255use crate::RunTime::ApplicationRunTime::ApplicationRunTime;
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct IPCStatusReport {
260 pub timestamp:u64,
261 pub connection_status:ConnectionStatus,
262 pub message_queue_size:usize,
263 pub active_listeners:Vec<String>,
264 pub recent_messages:Vec<MessageStats>,
265 pub error_count:u32,
266 pub uptime_seconds:u64,
267}
268
269#[derive(Debug, Clone, Serialize, Deserialize)]
271pub struct ConnectionStatus {
272 pub is_connected:bool,
273 pub last_heartbeat:u64,
274 pub connection_duration:u64,
275}
276
277#[derive(Debug, Clone, Serialize, Deserialize)]
279pub struct MessageStats {
280 pub channel:String,
281 pub message_count:u32,
282 pub last_message_time:u64,
283 pub average_processing_time_ms:f64,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
288pub struct ServiceInfo {
289 pub name:String,
290 pub version:String,
291 pub status:ServiceStatus,
292 pub last_heartbeat:u64,
293 pub uptime:u64,
294 pub dependencies:Vec<String>,
295 pub metrics:ServiceMetrics,
296 pub endpoint:Option<String>,
297 pub port:Option<u16>,
298}
299
300#[derive(Debug, Clone, Serialize, Deserialize)]
302pub enum ServiceStatus {
303 Running,
304 Degraded,
305 Stopped,
306 Error,
307}
308
309#[derive(Debug, Clone, Serialize, Deserialize)]
311pub struct ServiceMetrics {
312 pub response_time:f64,
313 pub error_rate:f64,
314 pub throughput:f64,
315 pub memory_usage:f64,
316 pub cpu_usage:f64,
317 pub last_updated:u64,
318}
319
320#[derive(Debug, Clone, Serialize, Deserialize)]
322pub struct ServiceRegistry {
323 pub services:HashMap<String, ServiceInfo>,
324 pub last_discovery:u64,
325 pub discovery_interval:u64,
326}
327
328pub struct StatusReporter {
330 runtime:Arc<ApplicationRunTime>,
331 ipc_server:Option<Arc<crate::IPC::TauriIPCServer::TauriIPCServer>>,
332 status_history:Arc<Mutex<Vec<IPCStatusReport>>>,
333 start_time:SystemTime,
334 error_count:Arc<Mutex<u32>>,
335 performance_metrics:Arc<Mutex<PerformanceMetrics>>,
336 health_monitor:Arc<Mutex<HealthMonitor>>,
337 service_registry:Arc<RwLock<ServiceRegistry>>,
338 discovered_services:Arc<RwLock<HashSet<String>>>,
339}
340
341impl StatusReporter {
342 pub fn new(runtime:Arc<ApplicationRunTime>) -> Self {
344 info!("[StatusReporter] Creating IPC status reporter");
345
346 Self {
347 runtime,
348 ipc_server:None,
349 status_history:Arc::new(Mutex::new(Vec::new())),
350 start_time:SystemTime::now(),
351 error_count:Arc::new(Mutex::new(0)),
352 performance_metrics:Arc::new(Mutex::new(PerformanceMetrics {
353 messages_per_second:0.0,
354 average_latency_ms:0.0,
355 peak_latency_ms:0.0,
356 compression_ratio:1.0,
357 connection_pool_utilization:0.0,
358 memory_usage_mb:0.0,
359 cpu_usage_percent:0.0,
360 last_update:SystemTime::now()
361 .duration_since(SystemTime::UNIX_EPOCH)
362 .unwrap_or_default()
363 .as_millis() as u64,
364 })),
365 health_monitor:Arc::new(Mutex::new(HealthMonitor {
366 health_score:100.0,
367 last_health_check:SystemTime::now()
368 .duration_since(SystemTime::UNIX_EPOCH)
369 .unwrap_or_default()
370 .as_millis() as u64,
371 issues_detected:Vec::new(),
372 recovery_attempts:0,
373 })),
374 service_registry:Arc::new(RwLock::new(ServiceRegistry {
375 services:HashMap::new(),
376 last_discovery:SystemTime::now()
377 .duration_since(SystemTime::UNIX_EPOCH)
378 .unwrap_or_default()
379 .as_millis() as u64,
380 discovery_interval:30000,
383 })),
384 discovered_services:Arc::new(RwLock::new(HashSet::new())),
385 }
386 }
387
388 pub fn set_ipc_server(&mut self, ipc_server:Arc<crate::IPC::TauriIPCServer::TauriIPCServer>) {
390 self.ipc_server = Some(ipc_server);
391 }
392
393 pub async fn generate_status_report(&self) -> Result<IPCStatusReport, String> {
395 debug!("[StatusReporter] Generating IPC status report");
396
397 let ipc_server = self.ipc_server.as_ref().ok_or("IPC Server not set".to_string())?;
398
399 let connection_status = ConnectionStatus {
401 is_connected:ipc_server.get_connection_status()?,
402 last_heartbeat:SystemTime::now()
403 .duration_since(SystemTime::UNIX_EPOCH)
404 .unwrap_or_default()
405 .as_secs(),
406 connection_duration:SystemTime::now().duration_since(self.start_time).unwrap_or_default().as_secs(),
407 };
408
409 let message_queue_size = ipc_server.get_queue_size()?;
411
412 let active_listeners = vec!["configuration".to_string(), "file".to_string(), "storage".to_string()];
414
415 let recent_messages = vec![
417 MessageStats {
418 channel:"configuration".to_string(),
419 message_count:10,
420 last_message_time:SystemTime::now()
421 .duration_since(SystemTime::UNIX_EPOCH)
422 .unwrap_or_default()
423 .as_secs(),
424 average_processing_time_ms:5.0,
425 },
426 MessageStats {
427 channel:"file".to_string(),
428 message_count:5,
429 last_message_time:SystemTime::now()
430 .duration_since(SystemTime::UNIX_EPOCH)
431 .unwrap_or_default()
432 .as_secs() - 10,
433 average_processing_time_ms:15.0,
434 },
435 ];
436
437 let error_count = {
439 let guard = self
440 .error_count
441 .lock()
442 .map_err(|e| format!("Failed to get error count: {}", e))?;
443 *guard
444 };
445
446 let uptime_seconds = SystemTime::now().duration_since(self.start_time).unwrap_or_default().as_secs();
448
449 let report = IPCStatusReport {
450 timestamp:SystemTime::now()
451 .duration_since(SystemTime::UNIX_EPOCH)
452 .unwrap_or_default()
453 .as_millis() as u64,
454 connection_status,
455 message_queue_size,
456 active_listeners,
457 recent_messages,
458 error_count,
459 uptime_seconds,
460 };
461
462 {
464 let mut history = self
465 .status_history
466 .lock()
467 .map_err(|e| format!("Failed to access status history: {}", e))?;
468 history.push(report.clone());
469
470 if history.len() > 100 {
472 history.remove(0);
473 }
474 }
475
476 Ok(report)
477 }
478
479 pub async fn report_to_sky(&self) -> Result<(), String> {
481 debug!("[StatusReporter] Reporting IPC status to Sky");
482
483 let report = self.generate_status_report().await?;
484
485 self.update_performance_metrics().await?;
487
488 self.perform_health_check().await?;
490
491 let performance_metrics = self.get_performance_metrics()?;
493 let health_status = self.get_health_status()?;
494
495 let comprehensive_report = ComprehensiveStatusReport {
497 basic_status:report.clone(),
498 performance_metrics:performance_metrics.clone(),
499 health_status:health_status.clone(),
500 timestamp:SystemTime::now()
501 .duration_since(SystemTime::UNIX_EPOCH)
502 .unwrap_or_default()
503 .as_millis() as u64,
504 };
505
506 if let Err(e) = self
508 .runtime
509 .Environment
510 .ApplicationHandle
511 .emit("ipc-status-report", &comprehensive_report)
512 {
513 error!("[StatusReporter] Failed to emit status report to Sky: {}", e);
514 return Err(format!("Failed to emit status report: {}", e));
515 }
516
517 if let Err(e) = self
519 .runtime
520 .Environment
521 .ApplicationHandle
522 .emit("ipc-performance-metrics", &performance_metrics)
523 {
524 error!("[StatusReporter] Failed to emit performance metrics: {}", e);
525 }
526
527 if let Err(e) = self
528 .runtime
529 .Environment
530 .ApplicationHandle
531 .emit("ipc-health-status", &health_status)
532 {
533 error!("[StatusReporter] Failed to emit health status: {}", e);
534 }
535
536 debug!("[StatusReporter] Comprehensive status report sent to Sky");
537 Ok(())
538 }
539
540 pub async fn start_periodic_reporting(&self, interval_seconds:u64) -> Result<(), String> {
542 info!(
543 "[StatusReporter] Starting periodic status reporting (interval: {}s)",
544 interval_seconds
545 );
546
547 let reporter = self.clone_reporter();
548
549 tokio::spawn(async move {
550 let mut interval = tokio::time::interval(Duration::from_secs(interval_seconds));
551
552 loop {
553 interval.tick().await;
554
555 if let Err(e) = reporter.report_to_sky().await {
556 error!("[StatusReporter] Periodic reporting failed: {}", e);
557 }
558 }
559 });
560
561 Ok(())
562 }
563
564 pub fn record_error(&self) {
566 if let Ok(mut error_count) = self.error_count.lock() {
567 *error_count += 1;
568 }
569 }
570
571 pub fn get_status_history(&self) -> Result<Vec<IPCStatusReport>, String> {
573 let history = self
574 .status_history
575 .lock()
576 .map_err(|e| format!("Failed to access status history: {}", e))?;
577 Ok(history.clone())
578 }
579
580 pub fn get_start_time(&self) -> SystemTime { self.start_time }
582
583 pub async fn update_performance_metrics(&self) -> Result<(), String> {
585 let ipc_server = self.ipc_server.as_ref().ok_or("IPC Server not set".to_string())?;
586
587 let connection_stats = ipc_server.get_connection_stats().await.unwrap_or_default();
589
590 let messages_per_second = self.calculate_message_rate().await;
592 let average_latency_ms = self.calculate_average_latency().await;
593 let peak_latency_ms = self.calculate_peak_latency().await;
594 let compression_ratio = self.calculate_compression_ratio().await;
595 let connection_pool_utilization = self.calculate_pool_utilization(&connection_stats).await;
596 let memory_usage_mb = self.get_memory_usage().await;
597 let cpu_usage_percent = self.get_cpu_usage().await;
598 let last_update = SystemTime::now()
599 .duration_since(SystemTime::UNIX_EPOCH)
600 .unwrap_or_default()
601 .as_millis() as u64;
602
603 let mut metrics = self
605 .performance_metrics
606 .lock()
607 .map_err(|e| format!("Failed to access performance metrics: {}", e))?;
608
609 metrics.messages_per_second = messages_per_second;
611 metrics.average_latency_ms = average_latency_ms;
612 metrics.peak_latency_ms = peak_latency_ms;
613 metrics.compression_ratio = compression_ratio;
614 metrics.connection_pool_utilization = connection_pool_utilization;
615 metrics.memory_usage_mb = memory_usage_mb;
616 metrics.cpu_usage_percent = cpu_usage_percent;
617 metrics.last_update = last_update;
618
619 debug!(
620 "[StatusReporter] Performance metrics updated: {:.2} msg/s, {:.2}ms latency",
621 metrics.messages_per_second, metrics.average_latency_ms
622 );
623
624 Ok(())
625 }
626
627 pub async fn perform_health_check(&self) -> Result<(), String> {
629 let mut health_monitor = self
630 .health_monitor
631 .lock()
632 .map_err(|e| format!("Failed to access health monitor: {}", e))?;
633
634 let mut health_score:f64 = 100.0;
635 let mut issues = Vec::new();
636
637 if let Some(ipc_server) = &self.ipc_server {
639 if !ipc_server.get_connection_status()? {
640 health_score -= 25.0;
641 issues.push(HealthIssue {
642 issue_type:HealthIssueType::ConnectionLoss,
643 severity:SeverityLevel::Critical,
644 description:"IPC connection lost".to_string(),
645 detected_at:SystemTime::now()
646 .duration_since(SystemTime::UNIX_EPOCH)
647 .unwrap_or_default()
648 .as_millis() as u64,
649 resolved_at:None,
650 });
651 }
652 }
653
654 if let Some(ipc_server) = &self.ipc_server {
656 let queue_size = ipc_server.get_queue_size()?;
657 if queue_size > 100 {
658 health_score -= 15.0;
659 issues.push(HealthIssue {
660 issue_type:HealthIssueType::QueueOverflow,
661 severity:SeverityLevel::High,
662 description:format!("Message queue overflow: {} messages", queue_size),
663 detected_at:SystemTime::now()
664 .duration_since(SystemTime::UNIX_EPOCH)
665 .unwrap_or_default()
666 .as_millis() as u64,
667 resolved_at:None,
668 });
669 }
670 }
671
672 let metrics = self
674 .performance_metrics
675 .lock()
676 .map_err(|e| format!("Failed to access performance metrics: {}", e))?;
677
678 if metrics.average_latency_ms > 100.0 {
679 health_score -= 20.0;
680 issues.push(HealthIssue {
681 issue_type:HealthIssueType::HighLatency,
682 severity:SeverityLevel::High,
683 description:format!("High latency detected: {:.2}ms", metrics.average_latency_ms),
684 detected_at:SystemTime::now()
685 .duration_since(SystemTime::UNIX_EPOCH)
686 .unwrap_or_default()
687 .as_millis() as u64,
688 resolved_at:None,
689 });
690 }
691
692 health_monitor.health_score = health_score.max(0.0);
694 health_monitor.issues_detected = issues;
695 health_monitor.last_health_check = SystemTime::now()
696 .duration_since(SystemTime::UNIX_EPOCH)
697 .unwrap_or_default()
698 .as_millis() as u64;
699
700 if health_score < 70.0 {
702 warn!(
703 "[StatusReporter] Health check failed: score {:.1}%
704",
705 health_score
706 );
707
708 if let Err(e) = self
709 .runtime
710 .Environment
711 .ApplicationHandle
712 .emit("ipc-health-alert", &health_monitor.clone())
713 {
714 error!("[StatusReporter] Failed to emit health alert: {}", e);
715 }
716 }
717
718 Ok(())
719 }
720
721 async fn calculate_message_rate(&self) -> f64 {
723 let history = self.get_status_history().unwrap_or_default();
725
726 if history.len() < 2 {
727 return 0.0;
728 }
729
730 let recent_reports:Vec<&IPCStatusReport> = history.iter().rev().take(5).collect();
731
732 let total_messages:u32 = recent_reports
733 .iter()
734 .map(|report| report.recent_messages.iter().map(|m| m.message_count).sum::<u32>())
735 .sum();
736
737 let time_span = if recent_reports.len() > 1 {
738 let first_time = recent_reports.first().unwrap().timestamp;
739 let last_time = recent_reports.last().unwrap().timestamp;
740 (last_time - first_time) as f64 / 1000.0 } else {
742 1.0
743 };
744
745 total_messages as f64 / time_span.max(1.0)
746 }
747
748 async fn calculate_average_latency(&self) -> f64 {
749 let history = self.get_status_history().unwrap_or_default();
750
751 if history.is_empty() {
752 return 0.0;
753 }
754
755 let recent_reports:Vec<&IPCStatusReport> = history.iter().rev().take(10).collect();
756
757 let total_latency:f64 = recent_reports
758 .iter()
759 .flat_map(|report| &report.recent_messages)
760 .map(|msg| msg.average_processing_time_ms)
761 .sum();
762
763 let message_count = recent_reports.iter().flat_map(|report| &report.recent_messages).count();
764
765 total_latency / message_count.max(1) as f64
766 }
767
768 async fn calculate_peak_latency(&self) -> f64 {
769 let history = self.get_status_history().unwrap_or_default();
770
771 history
772 .iter()
773 .flat_map(|report| &report.recent_messages)
774 .map(|msg| msg.average_processing_time_ms)
775 .fold(0.0, f64::max)
776 }
777
778 async fn calculate_compression_ratio(&self) -> f64 {
779 2.5 }
783
784 async fn calculate_pool_utilization(&self, stats:&crate::IPC::TauriIPCServer::ConnectionStats) -> f64 {
785 if stats.total_connections == 0 {
786 return 0.0;
787 }
788
789 stats.total_connections as f64 / stats.max_connections as f64
790 }
791
792 async fn get_memory_usage(&self) -> f64 {
793 50.0 }
797
798 async fn get_cpu_usage(&self) -> f64 {
799 15.0 }
803
804 pub async fn discover_services(&self) -> Result<Vec<ServiceInfo>, String> {
806 info!("[StatusReporter] Starting service discovery");
807
808 let mut registry = self.service_registry.write().await;
809 let mut discovered = self.discovered_services.write().await;
810
811 let mut services = Vec::new();
812
813 let core_services = vec![
815 ("EditorService", "1.0.0", ServiceStatus::Running),
816 ("ExtensionHostService", "1.0.0", ServiceStatus::Running),
817 ("ConfigurationService", "1.0.0", ServiceStatus::Running),
818 ("FileService", "1.0.0", ServiceStatus::Running),
819 ("StorageService", "1.0.0", ServiceStatus::Running),
820 ];
821
822 for (name, version, status) in core_services {
823 let service_info = ServiceInfo {
824 name:name.to_string(),
825 version:version.to_string(),
826 status:status.clone(),
827 last_heartbeat:SystemTime::now()
828 .duration_since(SystemTime::UNIX_EPOCH)
829 .unwrap_or_default()
830 .as_millis() as u64,
831 uptime:SystemTime::now().duration_since(self.start_time).unwrap_or_default().as_secs(),
832 dependencies:self.get_service_dependencies(name),
833 metrics:ServiceMetrics {
834 response_time:self.calculate_service_response_time(name).await,
835 error_rate:self.calculate_service_error_rate(name).await,
836 throughput:self.calculate_service_throughput(name).await,
837 memory_usage:self.get_service_memory_usage(name).await,
838 cpu_usage:self.get_service_cpu_usage(name).await,
839 last_updated:SystemTime::now()
840 .duration_since(SystemTime::UNIX_EPOCH)
841 .unwrap_or_default()
842 .as_millis() as u64,
843 },
844 endpoint:Some(format!("localhost:{}", 50050 + services.len() as u16)),
845 port:Some(50050 + services.len() as u16),
846 };
847
848 registry.services.insert(name.to_string(), service_info.clone());
849 discovered.insert(name.to_string());
850 services.push(service_info);
851 }
852
853 registry.last_discovery = SystemTime::now()
854 .duration_since(SystemTime::UNIX_EPOCH)
855 .unwrap_or_default()
856 .as_millis() as u64;
857
858 info!(
859 "[StatusReporter] Service discovery completed: {} services found",
860 services.len()
861 );
862
863 if let Err(e) = self
865 .runtime
866 .Environment
867 .ApplicationHandle
868 .emit("mountain_service_discovery", &services)
869 {
870 error!("[StatusReporter] Failed to emit service discovery event: {}", e);
871 }
872
873 Ok(services)
874 }
875
876 fn get_service_dependencies(&self, service_name:&str) -> Vec<String> {
878 match service_name {
879 "ExtensionHostService" => vec!["ConfigurationService".to_string()],
880 "FileService" => vec!["StorageService".to_string()],
881 "StorageService" => vec!["ConfigurationService".to_string()],
882 _ => Vec::new(),
883 }
884 }
885
886 async fn calculate_service_response_time(&self, service_name:&str) -> f64 {
888 match service_name {
890 "EditorService" => 5.0,
891 "ExtensionHostService" => 15.0,
892 "ConfigurationService" => 2.0,
893 "FileService" => 8.0,
894 "StorageService" => 3.0,
895 _ => 10.0,
896 }
897 }
898
899 async fn calculate_service_error_rate(&self, service_name:&str) -> f64 {
901 match service_name {
903 "EditorService" => 0.1,
904 "ExtensionHostService" => 2.5,
905 "ConfigurationService" => 0.5,
906 "FileService" => 1.2,
907 "StorageService" => 0.8,
908 _ => 5.0,
909 }
910 }
911
912 async fn calculate_service_throughput(&self, service_name:&str) -> f64 {
914 match service_name {
916 "EditorService" => 1000.0,
917 "ExtensionHostService" => 500.0,
918 "ConfigurationService" => 2000.0,
919 "FileService" => 800.0,
920 "StorageService" => 1500.0,
921 _ => 100.0,
922 }
923 }
924
925 async fn get_service_memory_usage(&self, service_name:&str) -> f64 {
927 match service_name {
929 "EditorService" => 256.0,
930 "ExtensionHostService" => 512.0,
931 "ConfigurationService" => 128.0,
932 "FileService" => 192.0,
933 "StorageService" => 64.0,
934 _ => 100.0,
935 }
936 }
937
938 async fn get_service_cpu_usage(&self, service_name:&str) -> f64 {
940 match service_name {
942 "EditorService" => 15.0,
943 "ExtensionHostService" => 25.0,
944 "ConfigurationService" => 5.0,
945 "FileService" => 10.0,
946 "StorageService" => 8.0,
947 _ => 20.0,
948 }
949 }
950
951 pub async fn start_periodic_discovery(&self) -> Result<(), String> {
953 info!("[StatusReporter] Starting periodic service discovery");
954
955 let registry = self.service_registry.read().await;
956 let interval = registry.discovery_interval;
957 drop(registry);
958
959 let reporter = self.clone_reporter();
960
961 tokio::spawn(async move {
962 let mut interval = tokio::time::interval(Duration::from_millis(interval));
963
964 loop {
965 interval.tick().await;
966
967 if let Err(e) = reporter.discover_services().await {
968 error!("[StatusReporter] Periodic service discovery failed: {}", e);
969 }
970 }
971 });
972
973 Ok(())
974 }
975
976 pub async fn get_service_registry(&self) -> Result<ServiceRegistry, String> {
978 let registry = self.service_registry.read().await;
979 Ok(registry.clone())
980 }
981
982 pub async fn get_service_info(&self, service_name:&str) -> Result<Option<ServiceInfo>, String> {
984 let registry = self.service_registry.read().await;
985 Ok(registry.services.get(service_name).cloned())
986 }
987
988 pub async fn attempt_recovery(&self) -> Result<(), String> {
990 let mut health_monitor = self
991 .health_monitor
992 .lock()
993 .map_err(|e| format!("Failed to access health monitor: {}", e))?;
994
995 health_monitor.recovery_attempts += 1;
996
997 if let Some(ipc_server) = &self.ipc_server {
999 if let Err(e) = ipc_server.dispose() {
1001 return Err(format!("Failed to dispose IPC server: {}", e));
1002 }
1003
1004 if let Err(e) = ipc_server.initialize().await {
1006 return Err(format!("Failed to reinitialize IPC server: {}", e));
1007 }
1008 }
1009
1010 if let Ok(mut error_count) = self.error_count.lock() {
1012 *error_count = 0;
1013 }
1014
1015 info!(
1016 "[StatusReporter] Recovery attempt {} completed",
1017 health_monitor.recovery_attempts
1018 );
1019 Ok(())
1020 }
1021
1022 pub fn get_performance_metrics(&self) -> Result<PerformanceMetrics, String> {
1024 let metrics = self
1025 .performance_metrics
1026 .lock()
1027 .map_err(|e| format!("Failed to access performance metrics: {}", e))?;
1028 Ok(metrics.clone())
1029 }
1030
1031 pub fn get_health_status(&self) -> Result<HealthMonitor, String> {
1033 let health_monitor = self
1034 .health_monitor
1035 .lock()
1036 .map_err(|e| format!("Failed to access health monitor: {}", e))?;
1037 Ok(health_monitor.clone())
1038 }
1039
1040 fn clone_reporter(&self) -> StatusReporter {
1042 StatusReporter {
1043 runtime:self.runtime.clone(),
1044 ipc_server:self.ipc_server.clone(),
1045 status_history:self.status_history.clone(),
1046 start_time:self.start_time,
1047 error_count:self.error_count.clone(),
1048 performance_metrics:self.performance_metrics.clone(),
1049 health_monitor:self.health_monitor.clone(),
1050 service_registry:self.service_registry.clone(),
1051 discovered_services:self.discovered_services.clone(),
1052 }
1053 }
1054}
1055
1056#[tauri::command]
1058pub async fn mountain_get_ipc_status(app_handle:tauri::AppHandle) -> Result<serde_json::Value, String> {
1059 debug!("[StatusReporter] Tauri command: get_ipc_status");
1060
1061 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1062 reporter
1063 .generate_status_report()
1064 .await
1065 .map(|report| serde_json::to_value(report).unwrap_or(serde_json::Value::Null))
1066 } else {
1067 Err("StatusReporter not found in application state".to_string())
1068 }
1069}
1070
1071#[tauri::command]
1073pub async fn mountain_get_ipc_status_history(app_handle:tauri::AppHandle) -> Result<serde_json::Value, String> {
1074 debug!("[StatusReporter] Tauri command: get_ipc_status_history");
1075
1076 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1077 reporter
1078 .get_status_history()
1079 .map(|history| serde_json::to_value(history).unwrap_or(serde_json::Value::Null))
1080 } else {
1081 Err("StatusReporter not found in application state".to_string())
1082 }
1083}
1084
1085#[tauri::command]
1087pub async fn mountain_start_ipc_status_reporting(
1088 app_handle:tauri::AppHandle,
1089 interval_seconds:u64,
1090) -> Result<serde_json::Value, String> {
1091 debug!("[StatusReporter] Tauri command: start_ipc_status_reporting");
1092
1093 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1094 reporter
1095 .start_periodic_reporting(interval_seconds)
1096 .await
1097 .map(|_| serde_json::json!({ "status": "started", "interval_seconds": interval_seconds }))
1098 } else {
1099 Err("StatusReporter not found in application state".to_string())
1100 }
1101}
1102
1103#[tauri::command]
1107pub async fn mountain_get_performance_metrics(app_handle:tauri::AppHandle) -> Result<PerformanceMetrics, String> {
1108 debug!("[StatusReporter] Tauri command: get_performance_metrics");
1109
1110 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1111 reporter.get_performance_metrics()
1112 } else {
1113 Err("StatusReporter not found in application state".to_string())
1114 }
1115}
1116
1117#[tauri::command]
1119pub async fn mountain_get_health_status(app_handle:tauri::AppHandle) -> Result<HealthMonitor, String> {
1120 debug!("[StatusReporter] Tauri command: get_health_status");
1121
1122 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1123 reporter.get_health_status()
1124 } else {
1125 Err("StatusReporter not found in application state".to_string())
1126 }
1127}
1128
1129#[tauri::command]
1131pub async fn mountain_perform_health_check(app_handle:tauri::AppHandle) -> Result<HealthMonitor, String> {
1132 debug!("[StatusReporter] Tauri command: perform_health_check");
1133
1134 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1135 reporter.perform_health_check().await?;
1136 reporter.get_health_status()
1137 } else {
1138 Err("StatusReporter not found in application state".to_string())
1139 }
1140}
1141
1142#[tauri::command]
1144pub async fn mountain_attempt_recovery(app_handle:tauri::AppHandle) -> Result<(), String> {
1145 debug!("[StatusReporter] Tauri command: attempt_recovery");
1146
1147 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1148 reporter.attempt_recovery().await
1149 } else {
1150 Err("StatusReporter not found in application state".to_string())
1151 }
1152}
1153
1154#[tauri::command]
1156pub async fn mountain_get_service_registry(app_handle:tauri::AppHandle) -> Result<ServiceRegistry, String> {
1157 debug!("[StatusReporter] Tauri command: get_service_registry");
1158
1159 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1160 reporter.get_service_registry().await
1161 } else {
1162 Err("StatusReporter not found in application state".to_string())
1163 }
1164}
1165
1166#[tauri::command]
1168pub async fn mountain_get_service_info(
1169 app_handle:tauri::AppHandle,
1170 service_name:String,
1171) -> Result<Option<ServiceInfo>, String> {
1172 debug!("[StatusReporter] Tauri command: get_service_info");
1173
1174 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1175 reporter.get_service_info(&service_name).await
1176 } else {
1177 Err("StatusReporter not found in application state".to_string())
1178 }
1179}
1180
1181#[tauri::command]
1183pub async fn mountain_discover_services(app_handle:tauri::AppHandle) -> Result<Vec<ServiceInfo>, String> {
1184 debug!("[StatusReporter] Tauri command: discover_services");
1185
1186 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1187 reporter.discover_services().await
1188 } else {
1189 Err("StatusReporter not found in application state".to_string())
1190 }
1191}
1192
1193#[tauri::command]
1195pub async fn mountain_start_service_discovery(app_handle:tauri::AppHandle) -> Result<(), String> {
1196 debug!("[StatusReporter] Tauri command: start_service_discovery");
1197
1198 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1199 reporter.start_periodic_discovery().await
1200 } else {
1201 Err("StatusReporter not found in application state".to_string())
1202 }
1203}
1204
1205#[tauri::command]
1207pub async fn mountain_get_comprehensive_status(
1208 app_handle:tauri::AppHandle,
1209) -> Result<ComprehensiveStatusReport, String> {
1210 debug!("[StatusReporter] Tauri command: get_comprehensive_status");
1211
1212 if let Some(reporter) = app_handle.try_state::<StatusReporter>() {
1213 let basic_status = reporter.generate_status_report().await?;
1214 let performance_metrics = reporter.get_performance_metrics()?;
1215 let health_status = reporter.get_health_status()?;
1216
1217 Ok(ComprehensiveStatusReport {
1218 basic_status,
1219 performance_metrics,
1220 health_status,
1221 timestamp:SystemTime::now()
1222 .duration_since(SystemTime::UNIX_EPOCH)
1223 .unwrap_or_default()
1224 .as_millis() as u64,
1225 })
1226 } else {
1227 Err("StatusReporter not found in application state".to_string())
1228 }
1229}
1230
1231pub fn initialize_status_reporter(app_handle:&tauri::AppHandle, runtime:Arc<ApplicationRunTime>) -> Result<(), String> {
1233 info!("[StatusReporter] Initializing status reporter");
1234
1235 let reporter = StatusReporter::new(runtime);
1236
1237 app_handle.manage(reporter.clone_reporter());
1239
1240 Ok(())
1241}