1pub mod structured;
15pub mod config;
16pub mod wrapper;
17pub mod middleware;
18
19use log::{debug, error, info, trace, warn, LevelFilter};
20use std::sync::Once;
21use std::sync::atomic::{AtomicBool, Ordering};
22use crate::logging::config::LoggingConfig;
23use crate::logging::structured::{LoggerGuard, init_global_logger};
24
25static INIT: Once = Once::new();
26static USING_STRUCTURED: AtomicBool = AtomicBool::new(false);
27static mut LOGGER_GUARD: Option<LoggerGuard> = None;
28
29pub fn init_with_config(level: LevelFilter, config: &LoggingConfig) {
33 INIT.call_once(|| {
34 log::set_max_level(level);
35
36 if config.structured {
37 let logger_config = config.to_logger_config();
38 let guard = init_global_logger(&logger_config);
39
40 unsafe { LOGGER_GUARD = Some(guard); }
42 USING_STRUCTURED.store(true, Ordering::SeqCst);
43 } else {
44 let env = env_logger::Env::default().filter_or("RUST_LOG", level.as_str());
47 env_logger::Builder::from_env(env)
48 .format_timestamp_millis()
49 .format_target(true)
50 .init();
51 }
52
53 info!("Logging initialized at level: {}", log::max_level());
54 });
55}
56
57pub fn is_structured_logging() -> bool {
59 USING_STRUCTURED.load(Ordering::SeqCst)
60}
61
62pub fn log_error<E: std::fmt::Display>(context: &str, err: E) -> E {
66 if is_structured_logging() {
67 slog_scope::error!("{}", err; "context" => context);
68 } else {
69 error!("{}: {}", context, err);
70 }
71 err
72}
73
74pub fn log_warning<E: std::fmt::Display>(context: &str, err: E) {
76 if is_structured_logging() {
77 slog_scope::warn!("{}", err; "context" => context);
78 } else {
79 warn!("{}: {}", context, err);
80 }
81}
82
83pub fn log_debug<M: std::fmt::Display>(context: &str, msg: M) {
85 if is_structured_logging() {
86 slog_scope::debug!("{}", msg; "context" => context);
87 } else {
88 debug!("{}: {}", context, msg);
89 }
90}
91
92pub fn log_trace<M: std::fmt::Display>(context: &str, msg: M) {
94 if is_structured_logging() {
95 slog_scope::trace!("{}", msg; "context" => context);
96 } else {
97 trace!("{}: {}", context, msg);
98 }
99}
100
101pub fn log_info<M: std::fmt::Display>(context: &str, msg: M) {
103 if is_structured_logging() {
104 slog_scope::info!("{}", msg; "context" => context);
105 } else {
106 info!("{}: {}", context, msg);
107 }
108}
109
110pub fn log_with_context(
112 level: log::Level,
113 message: impl std::fmt::Display,
114 context: &str,
115 fields: &[(&'static str, String)]
116) {
117 if is_structured_logging() {
118 match level {
119 log::Level::Error => {
120 let logger = slog_scope::logger();
121 let context_str = context.to_string(); let logger = logger.new(slog::o!("context" => context_str));
123 let logger = add_fields_to_logger(logger, fields);
124 slog::error!(logger, "{}", message);
125 },
126 log::Level::Warn => {
127 let logger = slog_scope::logger();
128 let context_str = context.to_string(); let logger = logger.new(slog::o!("context" => context_str));
130 let logger = add_fields_to_logger(logger, fields);
131 slog::warn!(logger, "{}", message);
132 },
133 log::Level::Info => {
134 let logger = slog_scope::logger();
135 let context_str = context.to_string(); let logger = logger.new(slog::o!("context" => context_str));
137 let logger = add_fields_to_logger(logger, fields);
138 slog::info!(logger, "{}", message);
139 },
140 log::Level::Debug => {
141 let logger = slog_scope::logger();
142 let context_str = context.to_string(); let logger = logger.new(slog::o!("context" => context_str));
144 let logger = add_fields_to_logger(logger, fields);
145 slog::debug!(logger, "{}", message);
146 },
147 log::Level::Trace => {
148 let logger = slog_scope::logger();
149 let context_str = context.to_string(); let logger = logger.new(slog::o!("context" => context_str));
151 let logger = add_fields_to_logger(logger, fields);
152 slog::trace!(logger, "{}", message);
153 },
154 }
155 } else {
156 match level {
158 log::Level::Error => crate::error!("{}: {}", context, message),
159 log::Level::Warn => crate::warn!("{}: {}", context, message),
160 log::Level::Info => crate::info!("{}: {}", context, message),
161 log::Level::Debug => crate::debug!("{}: {}", context, message),
162 log::Level::Trace => crate::trace!("{}: {}", context, message),
163 }
164 }
165}
166
167fn add_fields_to_logger(logger: slog::Logger, fields: &[(&'static str, String)]) -> slog::Logger {
169 let mut result = logger;
170 for (k, v) in fields {
171 let v_clone = v.clone(); result = result.new(slog::o!(*k => v_clone));
173 }
174 result
175}