rust_ethernet_ip/client/
diagnostics.rs1use super::EipClient;
2use tokio::time::Duration;
3
4impl EipClient {
5 pub async fn check_health(&self) -> bool {
11 self.session_handle() != 0
12 && self.last_activity.lock().await.elapsed() < Duration::from_secs(150)
13 }
14
15 pub async fn get_diagnostics_snapshot(&self) -> crate::DiagnosticsSnapshot {
17 self.build_diagnostics_snapshot(crate::HealthCheckMode::Passive, self.check_health().await)
18 .await
19 }
20
21 pub async fn check_health_detailed(&mut self) -> crate::error::Result<bool> {
27 if self.session_handle() == 0 {
28 return Ok(false);
29 }
30
31 match self.send_keep_alive().await {
33 Ok(()) => Ok(true),
34 Err(_) => {
35 match self.register_session().await {
38 Ok(()) => Ok(true),
39 Err(_) => Ok(false),
40 }
41 }
42 }
43 }
44
45 pub async fn get_diagnostics_snapshot_detailed(
47 &mut self,
48 ) -> crate::error::Result<crate::DiagnosticsSnapshot> {
49 let is_healthy = self.check_health_detailed().await?;
50 Ok(self
51 .build_diagnostics_snapshot(crate::HealthCheckMode::Verified, is_healthy)
52 .await)
53 }
54
55 async fn build_diagnostics_snapshot(
56 &self,
57 health_mode: crate::HealthCheckMode,
58 is_healthy: bool,
59 ) -> crate::DiagnosticsSnapshot {
60 let now = std::time::SystemTime::now();
61 let session_active = self.session_handle() != 0;
62 let last_activity_elapsed = self.last_activity.lock().await.elapsed();
63 let last_success_time = if is_healthy || session_active {
64 Some(
65 now.checked_sub(last_activity_elapsed)
66 .unwrap_or(std::time::SystemTime::UNIX_EPOCH),
67 )
68 } else {
69 None
70 };
71
72 let error_category = if session_active && !is_healthy {
73 Some(crate::ErrorCategory::Session)
74 } else {
75 None
76 };
77
78 let operations = self.diagnostic_counters.operation_metrics();
79 let mut errors = self.diagnostic_counters.error_metrics();
80 if error_category == Some(crate::ErrorCategory::Session) {
81 errors.session_errors += 1;
82 errors.retriable_errors += 1;
83 if errors.last_error_time.is_none() {
84 errors.last_error_time = Some(now);
85 errors.last_error_message = Some(
86 "Detailed health check reported session-level connectivity failure".to_string(),
87 );
88 errors.last_error_category = error_category;
89 errors.last_retriable_error_time = Some(now);
90 }
91 }
92
93 crate::DiagnosticsSnapshot {
94 captured_at: now,
95 connections: crate::ConnectionMetrics {
96 active_connections: if session_active { 1 } else { 0 },
97 total_connections: if session_active { 1 } else { 0 },
98 failed_connections: 0,
99 connection_uptime_avg: Duration::ZERO,
100 last_connection_time: last_success_time,
101 },
102 operations,
103 performance: crate::PerformanceMetrics {
104 avg_read_latency_ms: 0.0,
105 avg_write_latency_ms: 0.0,
106 max_read_latency_ms: 0.0,
107 max_write_latency_ms: 0.0,
108 reads_per_second: 0.0,
109 writes_per_second: 0.0,
110 memory_usage_mb: 0.0,
111 cpu_usage_percent: 0.0,
112 },
113 errors,
114 health: crate::HealthMetrics {
115 overall_health: if is_healthy {
116 crate::HealthStatus::Healthy
117 } else if session_active {
118 crate::HealthStatus::Critical
119 } else {
120 crate::HealthStatus::Unknown
121 },
122 last_health_check: now,
123 health_mode,
124 last_verified_health_check: if health_mode == crate::HealthCheckMode::Verified {
125 Some(now)
126 } else {
127 None
128 },
129 consecutive_failures: if is_healthy { 0 } else { 1 },
130 recovery_attempts: 0,
131 system_uptime: Duration::ZERO,
132 last_success_time,
133 last_failure_time: if session_active && !is_healthy {
134 Some(now)
135 } else {
136 None
137 },
138 },
139 system_metrics_are_placeholders: true,
140 }
141 }
142}