pub mod docker;
pub mod export;
pub mod file;
pub mod log_registry;
pub mod process;
pub mod script;
pub mod systemd;
use crate::models::{LogEntry, LogSource, Service};
use anyhow::Result;
use std::collections::VecDeque;
use tokio::sync::mpsc;
#[async_trait::async_trait]
pub trait LogStreamer: Send + Sync {
async fn stream_logs(
&self,
service: &Service,
tx: mpsc::UnboundedSender<LogEntry>,
) -> Result<()>;
fn can_handle(&self, service: &Service) -> bool;
fn source_type(&self) -> LogSource;
}
pub struct LogStreamManager {
registry: log_registry::LogStreamerRegistry,
}
impl LogStreamManager {
pub fn new() -> Self {
let mut registry = log_registry::LogStreamerRegistry::new();
registry.register("docker".to_string(), Box::new(docker::DockerLogStreamer::new()));
registry.register("systemd".to_string(), Box::new(systemd::SystemdLogStreamer::new()));
registry.register("file".to_string(), Box::new(file::FileLogStreamer::new()));
registry.register("process".to_string(), Box::new(process::ProcessLogStreamer::new()));
Self { registry }
}
pub async fn start_streaming(
&self,
service: &Service,
) -> Result<mpsc::UnboundedReceiver<LogEntry>> {
self.registry.start_streaming(service).await
}
pub fn registry_mut(&mut self) -> &mut log_registry::LogStreamerRegistry {
&mut self.registry
}
}
pub struct LogBuffer {
entries: VecDeque<LogEntry>,
max_size: usize,
}
impl LogBuffer {
pub fn new(max_size: usize) -> Self {
Self {
entries: VecDeque::with_capacity(max_size),
max_size,
}
}
pub fn push(&mut self, entry: LogEntry) {
if self.entries.len() >= self.max_size {
self.entries.pop_front();
}
self.entries.push_back(entry);
}
pub fn entries(&self) -> &VecDeque<LogEntry> {
&self.entries
}
pub fn clear(&mut self) {
self.entries.clear();
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
}