use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum HealthStatus {
Healthy,
Degraded,
Unhealthy,
}
impl HealthStatus {
pub fn is_healthy(&self) -> bool {
matches!(self, HealthStatus::Healthy)
}
pub fn is_operational(&self) -> bool {
matches!(self, HealthStatus::Healthy | HealthStatus::Degraded)
}
}
impl std::fmt::Display for HealthStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
HealthStatus::Healthy => write!(f, "healthy"),
HealthStatus::Degraded => write!(f, "degraded"),
HealthStatus::Unhealthy => write!(f, "unhealthy"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthCheckResponse {
pub status: HealthStatus,
pub broker_type: String,
pub connection: String,
pub latency_ms: Option<u64>,
pub details: HashMap<String, String>,
}
impl HealthCheckResponse {
pub fn healthy(broker_type: &str, connection: &str) -> Self {
Self {
status: HealthStatus::Healthy,
broker_type: broker_type.to_string(),
connection: connection.to_string(),
latency_ms: None,
details: HashMap::new(),
}
}
pub fn unhealthy(broker_type: &str, connection: &str, reason: &str) -> Self {
let mut details = HashMap::new();
details.insert("reason".to_string(), reason.to_string());
Self {
status: HealthStatus::Unhealthy,
broker_type: broker_type.to_string(),
connection: connection.to_string(),
latency_ms: None,
details,
}
}
pub fn with_latency(mut self, latency_ms: u64) -> Self {
self.latency_ms = Some(latency_ms);
self
}
pub fn with_detail(mut self, key: &str, value: &str) -> Self {
self.details.insert(key.to_string(), value.to_string());
self
}
}
#[async_trait]
pub trait HealthCheck: Send + Sync {
async fn health_check(&self) -> HealthCheckResponse;
async fn ping(&self) -> bool;
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BrokerMetrics {
pub messages_published: u64,
pub messages_consumed: u64,
pub messages_acknowledged: u64,
pub messages_rejected: u64,
pub publish_errors: u64,
pub consume_errors: u64,
pub active_connections: u32,
pub connection_attempts: u64,
pub connection_failures: u64,
}
impl BrokerMetrics {
pub fn new() -> Self {
Self::default()
}
pub fn inc_published(&mut self) {
self.messages_published += 1;
}
pub fn inc_consumed(&mut self) {
self.messages_consumed += 1;
}
pub fn inc_acknowledged(&mut self) {
self.messages_acknowledged += 1;
}
pub fn inc_rejected(&mut self) {
self.messages_rejected += 1;
}
pub fn inc_publish_error(&mut self) {
self.publish_errors += 1;
}
pub fn inc_consume_error(&mut self) {
self.consume_errors += 1;
}
pub fn inc_connection_attempt(&mut self) {
self.connection_attempts += 1;
}
pub fn inc_connection_failure(&mut self) {
self.connection_failures += 1;
}
}
#[async_trait]
pub trait MetricsProvider: Send + Sync {
async fn get_metrics(&self) -> BrokerMetrics;
async fn reset_metrics(&mut self);
}