use crate::{AppConfig, SinkConfig, UnifiedLogEntry}; use async_trait::async_trait; use std::sync::Arc; #[cfg(feature = "file")] mod file; #[cfg(all(feature = "kafka", target_os = "linux"))] mod kafka; #[cfg(feature = "webhook")] mod webhook; /// Sink Trait definition, asynchronously write logs #[async_trait] pub trait Sink: Send + Sync { async fn write(&self, entry: &UnifiedLogEntry); } /// Create a list of Sink instances pub async fn create_sinks(config: &AppConfig) -> Vec> { let mut sinks: Vec> = Vec::new(); for sink_config in &config.sinks { match sink_config { #[cfg(all(feature = "kafka", target_os = "linux"))] SinkConfig::Kafka(kafka_config) => { match rdkafka::config::ClientConfig::new() .set("bootstrap.servers", &kafka_config.brokers) .set("message.timeout.ms", "5000") .create() { Ok(producer) => { sinks.push(Arc::new(kafka::KafkaSink::new( producer, kafka_config.topic.clone(), kafka_config.batch_size.unwrap_or(100), kafka_config.batch_timeout_ms.unwrap_or(1000), ))); tracing::info!("Kafka sink created for topic: {}", kafka_config.topic); } Err(e) => { tracing::error!("Failed to create Kafka producer: {}", e); } } } #[cfg(feature = "webhook")] SinkConfig::Webhook(webhook_config) => { sinks.push(Arc::new(webhook::WebhookSink::new( webhook_config.endpoint.clone(), webhook_config.auth_token.clone(), webhook_config.max_retries.unwrap_or(3), webhook_config.retry_delay_ms.unwrap_or(100), ))); tracing::info!("Webhook sink created for endpoint: {}", webhook_config.endpoint); } #[cfg(feature = "file")] SinkConfig::File(file_config) => { tracing::debug!("FileSink: Using path: {}", file_config.path); match file::FileSink::new( file_config.path.clone(), file_config.buffer_size.unwrap_or(8192), file_config.flush_interval_ms.unwrap_or(1000), file_config.flush_threshold.unwrap_or(100), ) .await { Ok(sink) => { sinks.push(Arc::new(sink)); tracing::info!("File sink created for path: {}", file_config.path); } Err(e) => { tracing::error!("Failed to create File sink: {}", e); } } } #[cfg(any(not(feature = "kafka"), not(target_os = "linux")))] SinkConfig::Kafka(_) => { tracing::warn!("Kafka sink is configured but the 'kafka' feature is not enabled"); } #[cfg(not(feature = "webhook"))] SinkConfig::Webhook(_) => { tracing::warn!("Webhook sink is configured but the 'webhook' feature is not enabled"); } #[cfg(not(feature = "file"))] SinkConfig::File(_) => { tracing::warn!("File sink is configured but the 'file' feature is not enabled"); } } } sinks }