nautilus_common/logging/
mod.rspub mod headers;
pub mod logger;
pub mod writer;
use std::{
collections::HashMap,
env,
str::FromStr,
sync::atomic::{AtomicBool, Ordering},
};
use log::LevelFilter;
use nautilus_core::{time::get_atomic_clock_static, uuid::UUID4};
use nautilus_model::identifiers::TraderId;
use tracing_subscriber::EnvFilter;
use ustr::Ustr;
use self::{
logger::{LogGuard, Logger, LoggerConfig},
writer::FileWriterConfig,
};
use crate::enums::LogLevel;
pub const RECV: &str = "<--";
pub const SENT: &str = "-->";
pub const CMD: &str = "[CMD]";
pub const EVT: &str = "[EVT]";
pub const DOC: &str = "[DOC]";
pub const RPT: &str = "[RPT]";
pub const REQ: &str = "[REQ]";
pub const RES: &str = "[RES]";
static LOGGING_INITIALIZED: AtomicBool = AtomicBool::new(false);
static LOGGING_BYPASSED: AtomicBool = AtomicBool::new(false);
static LOGGING_REALTIME: AtomicBool = AtomicBool::new(true);
static LOGGING_COLORED: AtomicBool = AtomicBool::new(true);
#[no_mangle]
pub extern "C" fn logging_is_initialized() -> u8 {
u8::from(LOGGING_INITIALIZED.load(Ordering::Relaxed))
}
#[no_mangle]
pub extern "C" fn logging_set_bypass() {
LOGGING_BYPASSED.store(true, Ordering::Relaxed);
}
#[no_mangle]
pub extern "C" fn logging_shutdown() {
todo!()
}
#[no_mangle]
pub extern "C" fn logging_is_colored() -> u8 {
u8::from(LOGGING_COLORED.load(Ordering::Relaxed))
}
#[no_mangle]
pub extern "C" fn logging_clock_set_realtime_mode() {
LOGGING_REALTIME.store(true, Ordering::Relaxed);
}
#[no_mangle]
pub extern "C" fn logging_clock_set_static_mode() {
LOGGING_REALTIME.store(false, Ordering::Relaxed);
}
#[no_mangle]
pub extern "C" fn logging_clock_set_static_time(time_ns: u64) {
let clock = get_atomic_clock_static();
clock.set_time(time_ns.into());
}
pub fn init_tracing() {
if let Ok(v) = env::var("RUST_LOG") {
let env_filter = EnvFilter::new(v.clone());
tracing_subscriber::fmt()
.with_env_filter(env_filter)
.try_init()
.unwrap_or_else(|e| {
tracing::error!("Cannot set tracing subscriber because of error: {e}");
});
println!("Initialized tracing logs with RUST_LOG={v}");
}
}
pub fn init_logging(
trader_id: TraderId,
instance_id: UUID4,
config: LoggerConfig,
file_config: FileWriterConfig,
) -> LogGuard {
LOGGING_INITIALIZED.store(true, Ordering::Relaxed);
LOGGING_COLORED.store(config.is_colored, Ordering::Relaxed);
Logger::init_with_config(trader_id, instance_id, config, file_config)
}
#[must_use]
pub const fn map_log_level_to_filter(log_level: LogLevel) -> LevelFilter {
match log_level {
LogLevel::Off => LevelFilter::Off,
LogLevel::Trace => LevelFilter::Trace,
LogLevel::Debug => LevelFilter::Debug,
LogLevel::Info => LevelFilter::Info,
LogLevel::Warning => LevelFilter::Warn,
LogLevel::Error => LevelFilter::Error,
}
}
#[must_use]
pub fn parse_level_filter_str(s: &str) -> LevelFilter {
let mut log_level_str = s.to_string().to_uppercase();
if log_level_str == "WARNING" {
log_level_str = "WARN".to_string();
}
LevelFilter::from_str(&log_level_str)
.unwrap_or_else(|_| panic!("Invalid `LevelFilter` string, was {log_level_str}"))
}
#[must_use]
pub fn parse_component_levels(
original_map: Option<HashMap<String, serde_json::Value>>,
) -> HashMap<Ustr, LevelFilter> {
match original_map {
Some(map) => {
let mut new_map = HashMap::new();
for (key, value) in map {
let ustr_key = Ustr::from(&key);
let value = parse_level_filter_str(value.as_str().unwrap());
new_map.insert(ustr_key, value);
}
new_map
}
None => HashMap::new(),
}
}