balius_runtime/logging/
mod.rs

1use std::sync::Arc;
2
3use async_trait::async_trait;
4use tokio::sync::Mutex;
5
6use crate::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}
35impl LoggerHost {
36    pub fn new(worker_id: &str, provider: &Logger) -> Self {
37        Self {
38            worker_id: worker_id.to_string(),
39            provider: provider.clone(),
40        }
41    }
42}
43
44#[async_trait]
45pub trait LoggerProvider {
46    async fn log(&mut self, worker_id: &str, level: wit::Level, context: String, message: String);
47}
48
49#[async_trait]
50impl wit::Host for LoggerHost {
51    async fn log(&mut self, level: wit::Level, context: String, message: String) {
52        match &mut self.provider {
53            Logger::Silent => {}
54            Logger::Tracing => {
55                let level = match level {
56                    wit::Level::Trace => tracing::Level::TRACE,
57                    wit::Level::Debug => tracing::Level::DEBUG,
58                    wit::Level::Info => tracing::Level::INFO,
59                    wit::Level::Warn => tracing::Level::WARN,
60                    wit::Level::Error => tracing::Level::ERROR,
61                    wit::Level::Critical => tracing::Level::ERROR,
62                };
63                dyn_event!(level, worker_id = self.worker_id, context, message);
64            }
65            Logger::File(logger) => {
66                let mut lock = logger.lock().await;
67                lock.log(&self.worker_id, level, context, message).await
68            }
69            Logger::Custom(logger) => {
70                let mut lock = logger.lock().await;
71                lock.log(&self.worker_id, level, context, message).await
72            }
73        }
74    }
75}
76
77pub fn level_to_string(level: &wit::Level) -> String {
78    match level {
79        wit::Level::Info => "INFO".to_string(),
80        wit::Level::Trace => "TRACE".to_string(),
81        wit::Level::Debug => "DEBUG".to_string(),
82        wit::Level::Error => "ERROR".to_string(),
83        wit::Level::Warn => "WARN".to_string(),
84        wit::Level::Critical => "CRITICAL".to_string(),
85    }
86}