nautilus_common/logging/
mod.rs1pub mod headers;
19pub mod logger;
20pub mod writer;
21
22use std::{
23 collections::HashMap,
24 env,
25 str::FromStr,
26 sync::atomic::{AtomicBool, Ordering},
27};
28
29use log::LevelFilter;
30use nautilus_core::{UUID4, time::get_atomic_clock_static};
31use nautilus_model::identifiers::TraderId;
32use tracing_subscriber::EnvFilter;
33use ustr::Ustr;
34
35use self::{
36 logger::{LogGuard, Logger, LoggerConfig},
37 writer::FileWriterConfig,
38};
39use crate::enums::LogLevel;
40
41pub const RECV: &str = "<--";
42pub const SEND: &str = "-->";
43pub const CMD: &str = "[CMD]";
44pub const EVT: &str = "[EVT]";
45pub const DOC: &str = "[DOC]";
46pub const RPT: &str = "[RPT]";
47pub const REQ: &str = "[REQ]";
48pub const RES: &str = "[RES]";
49
50static LOGGING_INITIALIZED: AtomicBool = AtomicBool::new(false);
51static LOGGING_BYPASSED: AtomicBool = AtomicBool::new(false);
52static LOGGING_REALTIME: AtomicBool = AtomicBool::new(true);
53static LOGGING_COLORED: AtomicBool = AtomicBool::new(true);
54
55pub fn logging_is_initialized() -> bool {
57 LOGGING_INITIALIZED.load(Ordering::Relaxed)
58}
59
60pub fn logging_set_bypass() {
62 LOGGING_BYPASSED.store(true, Ordering::Relaxed);
63}
64
65pub fn logging_shutdown() {
67 log::logger().flush();
69 LOGGING_INITIALIZED.store(false, Ordering::Relaxed);
70}
71
72pub fn logging_is_colored() -> bool {
74 LOGGING_COLORED.load(Ordering::Relaxed)
75}
76
77pub fn logging_clock_set_realtime_mode() {
79 LOGGING_REALTIME.store(true, Ordering::Relaxed);
80}
81
82pub fn logging_clock_set_static_mode() {
84 LOGGING_REALTIME.store(false, Ordering::Relaxed);
85}
86
87pub fn logging_clock_set_static_time(time_ns: u64) {
89 let clock = get_atomic_clock_static();
90 clock.set_time(time_ns.into());
91}
92
93pub fn init_tracing() -> anyhow::Result<()> {
108 if let Ok(v) = env::var("RUST_LOG") {
110 let env_filter = EnvFilter::new(v.clone());
111
112 tracing_subscriber::fmt()
113 .with_env_filter(env_filter)
114 .try_init()
115 .map_err(|e| anyhow::anyhow!("Failed to initialize tracing subscriber: {e}"))?;
116
117 println!("Initialized tracing logs with RUST_LOG={v}");
118 }
119 Ok(())
120}
121
122pub fn init_logging(
143 trader_id: TraderId,
144 instance_id: UUID4,
145 config: LoggerConfig,
146 file_config: FileWriterConfig,
147) -> anyhow::Result<LogGuard> {
148 LOGGING_INITIALIZED.store(true, Ordering::Relaxed);
149 LOGGING_COLORED.store(config.is_colored, Ordering::Relaxed);
150 Logger::init_with_config(trader_id, instance_id, config, file_config)
151}
152
153#[must_use]
154pub const fn map_log_level_to_filter(log_level: LogLevel) -> LevelFilter {
155 match log_level {
156 LogLevel::Off => LevelFilter::Off,
157 LogLevel::Trace => LevelFilter::Trace,
158 LogLevel::Debug => LevelFilter::Debug,
159 LogLevel::Info => LevelFilter::Info,
160 LogLevel::Warning => LevelFilter::Warn,
161 LogLevel::Error => LevelFilter::Error,
162 }
163}
164
165#[must_use]
171pub fn parse_level_filter_str(s: &str) -> LevelFilter {
172 let mut log_level_str = s.to_string().to_uppercase();
173 if log_level_str == "WARNING" {
174 log_level_str = "WARN".to_string();
175 }
176 LevelFilter::from_str(&log_level_str)
177 .unwrap_or_else(|_| panic!("Invalid `LevelFilter` string, was {log_level_str}"))
178}
179
180#[must_use]
181pub fn parse_component_levels(
187 original_map: Option<HashMap<String, serde_json::Value>>,
188) -> HashMap<Ustr, LevelFilter> {
189 match original_map {
190 Some(map) => {
191 let mut new_map = HashMap::new();
192 for (key, value) in map {
193 let ustr_key = Ustr::from(&key);
194 let s = value
196 .as_str()
197 .expect("Invalid component log level: expected string");
198 let lvl = parse_level_filter_str(s);
199 new_map.insert(ustr_key, lvl);
200 }
201 new_map
202 }
203 None => HashMap::new(),
204 }
205}
206
207pub fn log_task_started(task_name: &str) {
209 tracing::debug!("Started task '{task_name}'");
210}
211
212pub fn log_task_stopped(task_name: &str) {
214 tracing::debug!("Stopped task '{task_name}'");
215}
216
217pub fn log_task_awaiting(task_name: &str) {
219 tracing::debug!("Awaiting task '{task_name}'");
220}
221
222pub fn log_task_aborted(task_name: &str) {
224 tracing::debug!("Aborted task '{task_name}'");
225}
226
227pub fn log_task_error(task_name: &str, e: &anyhow::Error) {
229 tracing::error!("Error in task '{task_name}': {e}");
230}