#![allow(async_fn_in_trait)]
use std::sync::Arc;
use tokio::sync::Mutex;
pub type CollectorResult<T> = Result<T, CollectorError>;
#[derive(Debug)]
pub enum CollectorError {
ConnectionError(String),
CollectionError(String),
ParseError(String),
Timeout,
Io(std::io::Error),
Other(String),
}
impl std::fmt::Display for CollectorError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ConnectionError(msg) => write!(f, "Failed to connect to remote host: {msg}"),
Self::CollectionError(msg) => write!(f, "Failed to collect data: {msg}"),
Self::ParseError(msg) => write!(f, "Failed to parse data: {msg}"),
Self::Timeout => write!(f, "Timeout while collecting data"),
Self::Io(err) => write!(f, "IO error: {err}"),
Self::Other(msg) => write!(f, "Other error: {msg}"),
}
}
}
impl std::error::Error for CollectorError {}
impl From<std::io::Error> for CollectorError {
fn from(err: std::io::Error) -> Self {
Self::Io(err)
}
}
#[derive(Debug, Clone, Default)]
pub struct SystemData<G, C, M, S> {
pub gpus: Vec<G>,
pub cpu: Option<C>,
pub memory: Option<M>,
pub storage: Vec<S>,
pub hostname: String,
pub timestamp: Option<chrono::DateTime<chrono::Utc>>,
}
pub trait DataCollector: Send + Sync {
type GpuInfo;
type CpuInfo;
type MemoryInfo;
type StorageInfo;
type Data: Default;
async fn initialize(&mut self) -> CollectorResult<()>;
async fn collect(&self) -> CollectorResult<Self::Data>;
async fn collect_gpus(&self) -> CollectorResult<Vec<Self::GpuInfo>>;
async fn collect_cpu(&self) -> CollectorResult<Option<Self::CpuInfo>>;
async fn collect_memory(&self) -> CollectorResult<Option<Self::MemoryInfo>>;
async fn collect_storage(&self) -> CollectorResult<Vec<Self::StorageInfo>>;
async fn is_healthy(&self) -> bool;
fn get_identifier(&self) -> String;
async fn shutdown(&mut self) -> CollectorResult<()> {
Ok(())
}
}
pub trait LocalCollector: DataCollector {
fn set_interval(&mut self, interval: std::time::Duration);
fn set_collect_gpu(&mut self, enabled: bool);
fn set_collect_cpu(&mut self, enabled: bool);
fn set_collect_memory(&mut self, enabled: bool);
fn set_collect_storage(&mut self, enabled: bool);
}
pub trait RemoteCollector: DataCollector {
async fn connect(&mut self, url: &str) -> CollectorResult<()>;
async fn disconnect(&mut self) -> CollectorResult<()>;
fn set_timeout(&mut self, timeout: std::time::Duration);
fn set_retry_policy(&mut self, max_retries: u32, backoff: std::time::Duration);
async fn is_connected(&self) -> bool;
fn get_url(&self) -> String;
}
pub trait CachedCollector: DataCollector {
async fn get_cached(&self) -> Option<Self::Data>;
async fn clear_cache(&mut self);
fn set_cache_ttl(&mut self, ttl: std::time::Duration);
async fn is_cache_valid(&self) -> bool;
}
pub trait AggregatedCollector: Send + Sync {
type Collector: DataCollector;
async fn add_collector(&mut self, collector_id: String);
async fn remove_collector(&mut self, identifier: &str) -> bool;
async fn collect_all<T>(&self) -> Vec<(String, CollectorResult<T>)>;
async fn collect_parallel<T>(&self) -> Vec<(String, CollectorResult<T>)>;
fn collector_count(&self) -> usize;
fn get_identifiers(&self) -> Vec<String>;
}
pub trait CollectorBuilder {
type Collector: DataCollector;
fn build(self) -> CollectorResult<Self::Collector>;
}
pub trait CollectorFactory {
type Local: LocalCollector;
type Remote: RemoteCollector;
type Aggregated: AggregatedCollector;
async fn create_local(&self) -> CollectorResult<Self::Local>;
async fn create_remote(&self, url: &str) -> CollectorResult<Self::Remote>;
async fn create_aggregated(&self) -> CollectorResult<Self::Aggregated>;
}
pub trait StreamingCollector: DataCollector {
async fn subscribe(&mut self) -> CollectorResult<tokio::sync::mpsc::Receiver<Self::Data>>;
async fn start_streaming(&mut self, interval: std::time::Duration) -> CollectorResult<()>;
async fn stop_streaming(&mut self) -> CollectorResult<()>;
fn is_streaming(&self) -> bool;
}
pub struct CollectorState<T> {
pub data: Arc<Mutex<T>>,
pub last_update: Arc<Mutex<Option<chrono::DateTime<chrono::Utc>>>>,
pub error_count: Arc<Mutex<u32>>,
pub is_running: Arc<Mutex<bool>>,
}