balius_runtime/logging/
mod.rs

1use std::sync::Arc;
2
3use async_trait::async_trait;
4use tokio::sync::Mutex;
5
6use crate::{metrics::Metrics, wit::balius::app::logging as wit};
7
8pub mod file;
9
10#[derive(Clone)]
11pub enum Logger {
12    Silent,
13    Tracing,
14    File(Arc<Mutex<file::FileLogger>>),
15    Custom(Arc<Mutex<dyn LoggerProvider + Send + Sync>>),
16}
17
18// need this to set the trace level at runtime
19macro_rules! dyn_event {
20    ($lvl:ident, $($arg:tt)+) => {
21        match $lvl {
22            ::tracing::Level::TRACE => ::tracing::trace!($($arg)+),
23            ::tracing::Level::DEBUG => ::tracing::debug!($($arg)+),
24            ::tracing::Level::INFO => ::tracing::info!($($arg)+),
25            ::tracing::Level::WARN => ::tracing::warn!($($arg)+),
26            ::tracing::Level::ERROR => ::tracing::error!($($arg)+),
27        }
28    };
29}
30
31pub struct LoggerHost {
32    worker_id: String,
33    provider: Logger,
34    metrics: Arc<Metrics>,
35}
36impl LoggerHost {
37    pub fn new(worker_id: &str, provider: &Logger, metrics: &Arc<Metrics>) -> Self {
38        Self {
39            worker_id: worker_id.to_string(),
40            provider: provider.clone(),
41            metrics: metrics.clone(),
42        }
43    }
44}
45
46#[async_trait]
47pub trait LoggerProvider {
48    async fn log(&mut self, worker_id: &str, level: wit::Level, context: String, message: String);
49}
50
51impl wit::Host for LoggerHost {
52    async fn log(&mut self, level: wit::Level, context: String, message: String) {
53        self.metrics.log(&self.worker_id, &level);
54        match &mut self.provider {
55            Logger::Silent => {}
56            Logger::Tracing => {
57                let level = match level {
58                    wit::Level::Trace => tracing::Level::TRACE,
59                    wit::Level::Debug => tracing::Level::DEBUG,
60                    wit::Level::Info => tracing::Level::INFO,
61                    wit::Level::Warn => tracing::Level::WARN,
62                    wit::Level::Error => tracing::Level::ERROR,
63                    wit::Level::Critical => tracing::Level::ERROR,
64                };
65                dyn_event!(level, worker_id = self.worker_id, context, message);
66            }
67            Logger::File(logger) => {
68                let mut lock = logger.lock().await;
69                lock.log(&self.worker_id, level, context, message).await
70            }
71            Logger::Custom(logger) => {
72                let mut lock = logger.lock().await;
73                lock.log(&self.worker_id, level, context, message).await
74            }
75        }
76    }
77}
78
79pub fn level_to_string(level: &wit::Level) -> String {
80    match level {
81        wit::Level::Info => "INFO".to_string(),
82        wit::Level::Trace => "TRACE".to_string(),
83        wit::Level::Debug => "DEBUG".to_string(),
84        wit::Level::Error => "ERROR".to_string(),
85        wit::Level::Warn => "WARN".to_string(),
86        wit::Level::Critical => "CRITICAL".to_string(),
87    }
88}