1use nautilus_core::UUID4;
17use nautilus_model::identifiers::TraderId;
18use sysinfo::System;
19use ustr::Ustr;
20
21use crate::{
22 enums::{LogColor, LogLevel},
23 logging::logger::log,
24};
25
26#[rustfmt::skip]
27pub fn log_header(trader_id: TraderId, machine_id: &str, instance_id: UUID4, component: Ustr) {
28 let mut sys = System::new_all();
29 sys.refresh_all();
30
31 let c = component;
32
33 let kernel_version = System::kernel_version().map_or(String::new(), |v| format!("kernel-{v} "));
34 let os_version = System::long_os_version().unwrap_or_default();
35 let pid = std::process::id();
36
37 header_sepr(c, "=================================================================");
38 header_sepr(c, " NAUTILUS TRADER - Automated Algorithmic Trading Platform");
39 header_sepr(c, " by Posei Systems Pty Ltd.");
40 header_sepr(c, " Copyright (C) 2015-2025. All rights reserved.");
41 header_sepr(c, "=================================================================");
42 header_line(c, "");
43 header_line(c, "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣶⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀");
44 header_line(c, "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣾⣿⣿⣿⠀⢸⣿⣿⣿⣿⣶⣶⣤⣀⠀⠀⠀⠀⠀");
45 header_line(c, "⠀⠀⠀⠀⠀⠀⢀⣴⡇⢀⣾⣿⣿⣿⣿⣿⠀⣾⣿⣿⣿⣿⣿⣿⣿⠿⠓⠀⠀⠀⠀");
46 header_line(c, "⠀⠀⠀⠀⠀⣰⣿⣿⡀⢸⣿⣿⣿⣿⣿⣿⠀⣿⣿⣿⣿⣿⣿⠟⠁⣠⣄⠀⠀⠀⠀");
47 header_line(c, "⠀⠀⠀⠀⢠⣿⣿⣿⣇⠀⢿⣿⣿⣿⣿⣿⠀⢻⣿⣿⣿⡿⢃⣠⣾⣿⣿⣧⡀⠀⠀");
48 header_line(c, "⠀⠀⠀⠠⣾⣿⣿⣿⣿⣿⣧⠈⠋⢀⣴⣧⠀⣿⡏⢠⡀⢸⣿⣿⣿⣿⣿⣿⣿⡇⠀");
49 header_line(c, "⠀⠀⠀⣀⠙⢿⣿⣿⣿⣿⣿⠇⢠⣿⣿⣿⡄⠹⠃⠼⠃⠈⠉⠛⠛⠛⠛⠛⠻⠇⠀");
50 header_line(c, "⠀⠀⢸⡟⢠⣤⠉⠛⠿⢿⣿⠀⢸⣿⡿⠋⣠⣤⣄⠀⣾⣿⣿⣶⣶⣶⣦⡄⠀⠀⠀");
51 header_line(c, "⠀⠀⠸⠀⣾⠏⣸⣷⠂⣠⣤⠀⠘⢁⣴⣾⣿⣿⣿⡆⠘⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀");
52 header_line(c, "⠀⠀⠀⠀⠛⠀⣿⡟⠀⢻⣿⡄⠸⣿⣿⣿⣿⣿⣿⣿⡀⠘⣿⣿⣿⣿⠟⠀⠀⠀⠀");
53 header_line(c, "⠀⠀⠀⠀⠀⠀⣿⠇⠀⠀⢻⡿⠀⠈⠻⣿⣿⣿⣿⣿⡇⠀⢹⣿⠿⠋⠀⠀⠀⠀⠀");
54 header_line(c, "⠀⠀⠀⠀⠀⠀⠋⠀⠀⠀⡘⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠁⠀⠀⠀⠀⠀⠀⠀");
55 header_line(c, "");
56 header_sepr(c, "=================================================================");
57 header_sepr(c, " SYSTEM SPECIFICATION");
58 header_sepr(c, "=================================================================");
59 header_line(c, &format!("CPU architecture: {}", sys.cpus()[0].brand()));
60 header_line(c, &format!("CPU(s): {} @ {} Mhz", sys.cpus().len(), sys.cpus()[0].frequency()));
61 header_line(c, &format!("OS: {kernel_version}{os_version}"));
62
63 log_sysinfo(component);
64
65 header_sepr(c, "=================================================================");
66 header_sepr(c, " IDENTIFIERS");
67 header_sepr(c, "=================================================================");
68 header_line(c, &format!("trader_id: {trader_id}"));
69 header_line(c, &format!("machine_id: {machine_id}"));
70 header_line(c, &format!("instance_id: {instance_id}"));
71 header_line(c, &format!("PID: {pid}"));
72
73 header_sepr(c, "=================================================================");
74 header_sepr(c, " VERSIONING");
75 header_sepr(c, "=================================================================");
76
77 #[cfg(not(feature = "python"))]
78 log_rust_versioning(c);
79
80 #[cfg(feature = "python")]
81 log_python_versioning(c);
82}
83
84#[cfg(not(feature = "python"))]
85#[rustfmt::skip]
86fn log_rust_versioning(c: Ustr) {
87 use nautilus_core::consts::NAUTILUS_VERSION;
88 header_line(c, &format!("posei_trader: {NAUTILUS_VERSION}"));
89}
90
91#[cfg(feature = "python")]
92#[rustfmt::skip]
93fn log_python_versioning(c: Ustr) {
94 let package = "posei_trader";
95 header_line(c, &format!("{package}: {}", python_package_version(package)));
96 header_line(c, &format!("python: {}", python_version()));
97 let package = "numpy";
98 header_line(c, &format!("{package}: {}", python_package_version(package)));
99 let package = "pandas";
100 header_line(c, &format!("{package}: {}", python_package_version(package)));
101 let package = "msgspec";
102 header_line(c, &format!("{package}: {}", python_package_version(package)));
103 let package = "pyarrow";
104 header_line(c, &format!("{package}: {}", python_package_version(package)));
105 let package = "pytz";
106 header_line(c, &format!("{package}: {}", python_package_version(package)));
107 let package = "uvloop";
108 header_line(c, &format!("{package}: {}", python_package_version(package)));
109 header_sepr(c, "=================================================================");
110}
111
112#[rustfmt::skip]
113pub fn log_sysinfo(component: Ustr) {
114 let mut sys = System::new_all();
115 sys.refresh_all();
116
117 let c = component;
118
119 let ram_total = sys.total_memory();
120 let ram_used = sys.used_memory();
121 let ram_used_p = (ram_used as f64 / ram_total as f64) * 100.0;
122 let ram_avail = ram_total - ram_used;
123 let ram_avail_p = (ram_avail as f64 / ram_total as f64) * 100.0;
124
125 let swap_total = sys.total_swap();
126 let swap_used = sys.used_swap();
127 let swap_used_p = (swap_used as f64 / swap_total as f64) * 100.0;
128 let swap_avail = swap_total - swap_used;
129 let swap_avail_p = (swap_avail as f64 / swap_total as f64) * 100.0;
130
131 header_sepr(c, "=================================================================");
132 header_sepr(c, " MEMORY USAGE");
133 header_sepr(c, "=================================================================");
134 header_line(c, &format!("RAM-Total: {:.2} GiB", bytes_to_gib(ram_total)));
135 header_line(c, &format!("RAM-Used: {:.2} GiB ({:.2}%)", bytes_to_gib(ram_used), ram_used_p));
136 header_line(c, &format!("RAM-Avail: {:.2} GiB ({:.2}%)", bytes_to_gib(ram_avail), ram_avail_p));
137 header_line(c, &format!("Swap-Total: {:.2} GiB", bytes_to_gib(swap_total)));
138 header_line(c, &format!("Swap-Used: {:.2} GiB ({:.2}%)", bytes_to_gib(swap_used), swap_used_p));
139 header_line(c, &format!("Swap-Avail: {:.2} GiB ({:.2}%)", bytes_to_gib(swap_avail), swap_avail_p));
140}
141
142fn header_sepr(c: Ustr, s: &str) {
143 log(LogLevel::Info, LogColor::Cyan, c, s);
144}
145
146fn header_line(c: Ustr, s: &str) {
147 log(LogLevel::Info, LogColor::Normal, c, s);
148}
149
150fn bytes_to_gib(b: u64) -> f64 {
151 b as f64 / (2u64.pow(30) as f64)
152}
153
154#[cfg(feature = "python")]
155fn python_package_version(package: &str) -> String {
156 use nautilus_core::python::version::get_python_package_version;
157
158 get_python_package_version(package)
159}
160
161#[cfg(not(feature = "python"))]
162fn python_package_version(_package: &str) -> &str {
166 panic!("`python` feature is not enabled");
167}
168
169#[cfg(feature = "python")]
170fn python_version() -> String {
171 use nautilus_core::python::version::get_python_version;
172
173 get_python_version()
174}
175
176#[cfg(not(feature = "python"))]
177fn python_version() -> String {
181 panic!("`python` feature is not enabled");
182}