use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum HealthStatus {
Healthy,
Degraded,
Unhealthy,
Unknown,
NotRunning,
}
impl HealthStatus {
pub fn symbol(&self) -> &str {
match self {
HealthStatus::Healthy => "✓",
HealthStatus::Degraded => "⚠",
HealthStatus::Unhealthy => "✗",
HealthStatus::Unknown => "?",
HealthStatus::NotRunning => "✗",
}
}
pub fn color(&self) -> &str {
match self {
HealthStatus::Healthy => "green",
HealthStatus::Degraded => "yellow",
HealthStatus::Unhealthy => "red",
HealthStatus::Unknown => "gray",
HealthStatus::NotRunning => "red",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthResult {
pub status: HealthStatus,
pub response_time_ms: u64,
pub last_checked: DateTime<Utc>,
pub details: Option<String>,
pub suggestion: Option<String>,
}
impl HealthResult {
pub fn healthy(response_time_ms: u64) -> Self {
Self {
status: HealthStatus::Healthy,
response_time_ms,
last_checked: Utc::now(),
details: None,
suggestion: None,
}
}
pub fn unhealthy(reason: String, suggestion: Option<String>) -> Self {
Self {
status: HealthStatus::Unhealthy,
response_time_ms: 0,
last_checked: Utc::now(),
details: Some(reason),
suggestion,
}
}
pub fn not_running(suggestion: Option<String>) -> Self {
Self {
status: HealthStatus::NotRunning,
response_time_ms: 0,
last_checked: Utc::now(),
details: Some("Process not found".to_string()),
suggestion,
}
}
pub fn degraded(response_time_ms: u64, reason: String) -> Self {
Self {
status: HealthStatus::Degraded,
response_time_ms,
last_checked: Utc::now(),
details: Some(reason),
suggestion: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthCheckConfig {
pub check_type: HealthCheckType,
pub interval: Duration,
pub timeout: Duration,
pub retry_count: u32,
}
impl Default for HealthCheckConfig {
fn default() -> Self {
Self {
check_type: HealthCheckType::Port,
interval: Duration::from_secs(30),
timeout: Duration::from_secs(3),
retry_count: 2,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum HealthCheckType {
Port,
Process,
Http {
path: String,
expected_status: Option<u16>,
},
Postgres {
database: Option<String>,
},
Redis,
MySQL {
database: Option<String>,
},
MongoDB {
database: Option<String>,
},
Custom {
script: String,
},
}