1use std::sync::OnceLock;
4
5use clap::ValueEnum;
6use tracing::{level_filters::LevelFilter, log::error};
7use tracing_subscriber::{
8 fmt::{self, format::FmtSpan, time},
9 prelude::*,
10 reload::{self, Handle},
11 Registry,
12};
13
14use crate::settings::Settings;
15pub(crate) const LOG_LEVEL_DEFAULT: &str = "info";
17
18#[derive(ValueEnum, Clone, Copy, Debug)]
20pub(crate) enum LogLevel {
21 Debug,
23 Info,
25 Warn,
27 Error,
29}
30
31impl From<LogLevel> for tracing::Level {
32 fn from(val: LogLevel) -> Self {
33 match val {
34 LogLevel::Debug => Self::DEBUG,
35 LogLevel::Info => Self::INFO,
36 LogLevel::Warn => Self::WARN,
37 LogLevel::Error => Self::ERROR,
38 }
39 }
40}
41
42impl From<LogLevel> for tracing::log::LevelFilter {
43 fn from(val: LogLevel) -> Self {
44 match val {
45 LogLevel::Debug => Self::Debug,
46 LogLevel::Info => Self::Info,
47 LogLevel::Warn => Self::Warn,
48 LogLevel::Error => Self::Error,
49 }
50 }
51}
52
53static LOGGER_HANDLE: OnceLock<LoggerHandle> = OnceLock::new();
55
56static GLOBAL_SPAN: OnceLock<tracing::span::Span> = OnceLock::new();
58
59static SPAN_GUARD: OnceLock<tracing::span::Entered> = OnceLock::new();
61
62pub(crate) type LoggerHandle = Handle<LevelFilter, Registry>;
64
65fn set_default_span() {
67 let server_id = Settings::service_id();
68 let global_span = tracing::info_span!("Global", ServerID = server_id);
71 if GLOBAL_SPAN.set(global_span).is_err() {
72 error!("Failed to set default span. Is it already set?");
73 }
74
75 if let Some(global_span) = GLOBAL_SPAN.get() {
77 let span_guard = global_span.enter();
78 if SPAN_GUARD.set(span_guard).is_err() {
79 error!("Failed to set default span. Is it already set?");
80 }
81 }
82}
83
84pub(crate) fn init(log_level: LogLevel) {
86 let layer = fmt::layer()
88 .json()
89 .with_timer(time::UtcTime::rfc_3339())
90 .with_span_events(FmtSpan::CLOSE)
91 .with_current_span(true)
92 .with_span_list(true)
93 .with_target(true)
94 .with_file(true)
95 .with_line_number(true)
96 .with_level(true)
97 .with_thread_names(true)
98 .with_thread_ids(true)
99 .flatten_event(true);
100
101 let filter = LevelFilter::from_level(log_level.into());
103 let (filter, logger_handle) = reload::Layer::new(filter);
104 tracing_subscriber::registry()
105 .with(filter)
106 .with(layer)
107 .with(
108 tracing_subscriber::EnvFilter::builder()
109 .with_default_directive(LevelFilter::INFO.into())
110 .from_env_lossy(),
111 )
112 .init();
113
114 tracing::log::set_max_level(log_level.into());
116
117 if LOGGER_HANDLE.set(logger_handle).is_err() {
118 error!("Failed to initialize logger handle. Called multiple times?");
119 }
120
121 set_default_span();
122}
123
124pub(crate) fn modify_logger_level(level: LogLevel) {
127 if let Some(logger_handle) = LOGGER_HANDLE.get() {
128 if let Err(error) = logger_handle.modify(|f| *f = LevelFilter::from_level(level.into())) {
129 error!("Failed to modify log level to {:?} : {}", level, error);
130 }
131 } else {
132 error!(
134 "Failed to modify log level to {:?} : Logger handle not available.",
135 level
136 );
137 }
138}