use std::{
ffi::c_char,
ops::{Deref, DerefMut},
};
use ahash::AHashMap;
use nautilus_core::{
UUID4,
ffi::{
parsing::{optional_bytes_to_json, u8_as_bool},
string::{cstr_as_str, cstr_to_ustr, optional_cstr_to_str},
},
};
use nautilus_model::identifiers::TraderId;
use crate::{
enums::{LogColor, LogLevel},
logging::{
headers, init_logging,
logger::{self, LogGuard, LoggerConfig},
map_log_level_to_filter, parse_component_levels,
writer::FileWriterConfig,
},
};
#[repr(C)]
#[derive(Debug)]
#[allow(non_camel_case_types)]
pub struct LogGuard_API(Box<LogGuard>);
impl Deref for LogGuard_API {
type Target = LogGuard;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for LogGuard_API {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn logging_init(
trader_id: TraderId,
instance_id: UUID4,
level_stdout: LogLevel,
level_file: LogLevel,
directory_ptr: *const c_char,
file_name_ptr: *const c_char,
file_format_ptr: *const c_char,
component_levels_ptr: *const c_char,
is_colored: u8,
is_bypassed: u8,
print_config: u8,
log_components_only: u8,
max_file_size: u64,
max_backup_count: u32,
) -> LogGuard_API {
let level_stdout = map_log_level_to_filter(level_stdout);
let level_file = map_log_level_to_filter(level_file);
let component_levels_json = unsafe { optional_bytes_to_json(component_levels_ptr) };
let component_levels = parse_component_levels(component_levels_json)
.expect("Failed to parse component log levels");
let config = LoggerConfig::new(
level_stdout,
level_file,
component_levels,
AHashMap::new(), u8_as_bool(log_components_only),
u8_as_bool(is_colored),
u8_as_bool(print_config),
false, u8_as_bool(is_bypassed),
None, false, );
let file_rotate = if max_file_size > 0 {
Some((max_file_size, max_backup_count))
} else {
None
};
let directory = unsafe { optional_cstr_to_str(directory_ptr).map(ToString::to_string) };
let file_name = unsafe { optional_cstr_to_str(file_name_ptr).map(ToString::to_string) };
let file_format = unsafe { optional_cstr_to_str(file_format_ptr).map(ToString::to_string) };
let file_config = FileWriterConfig::new(directory, file_name, file_format, file_rotate);
if u8_as_bool(is_bypassed) {
logging_set_bypass();
}
LogGuard_API(Box::new(
init_logging(trader_id, instance_id, config, file_config)
.expect("Failed to initialize logging"),
))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn logger_log(
level: LogLevel,
color: LogColor,
component_ptr: *const c_char,
message_ptr: *const c_char,
) {
let component = unsafe { cstr_to_ustr(component_ptr) };
let message = unsafe { cstr_as_str(message_ptr) };
logger::log(level, color, component, message);
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn logging_log_header(
trader_id: TraderId,
machine_id_ptr: *const c_char,
instance_id: UUID4,
component_ptr: *const c_char,
) {
let component = unsafe { cstr_to_ustr(component_ptr) };
let machine_id = unsafe { cstr_as_str(machine_id_ptr) };
headers::log_header(trader_id, machine_id, instance_id, component);
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn logging_log_sysinfo(component_ptr: *const c_char) {
let component = unsafe { cstr_to_ustr(component_ptr) };
headers::log_sysinfo(component);
}
#[unsafe(no_mangle)]
pub extern "C" fn logger_flush() {
log::logger().flush();
}
#[unsafe(no_mangle)]
pub extern "C" fn logger_drop(log_guard: LogGuard_API) {
drop(log_guard);
}
#[unsafe(no_mangle)]
pub extern "C" fn logging_is_initialized() -> u8 {
u8::from(crate::logging::logging_is_initialized())
}
#[unsafe(no_mangle)]
pub extern "C" fn logging_set_bypass() {
crate::logging::logging_set_bypass();
}
#[unsafe(no_mangle)]
pub extern "C" fn logging_shutdown() {
crate::logging::logging_shutdown();
}
#[unsafe(no_mangle)]
pub extern "C" fn logging_is_colored() -> u8 {
u8::from(crate::logging::logging_is_colored())
}
#[unsafe(no_mangle)]
pub extern "C" fn logging_clock_set_realtime_mode() {
crate::logging::logging_clock_set_realtime_mode();
}
#[unsafe(no_mangle)]
pub extern "C" fn logging_clock_set_static_mode() {
crate::logging::logging_clock_set_static_mode();
}
#[unsafe(no_mangle)]
pub extern "C" fn logging_clock_set_static_time(time_ns: u64) {
crate::logging::logging_clock_set_static_time(time_ns);
}