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