1#[macro_export]
46macro_rules! log_trace {
47 ($msg:literal, color = $color:expr, component = $component:expr) => {
49 log::trace!(component = $component, color = $color as u8; $msg);
50 };
51 ($fmt:literal, $arg1:expr, color = $color:expr, component = $component:expr) => {
52 log::trace!(component = $component, color = $color as u8; $fmt, $arg1);
53 };
54 ($fmt:literal, $arg1:expr, $arg2:expr, color = $color:expr, component = $component:expr) => {
55 log::trace!(component = $component, color = $color as u8; $fmt, $arg1, $arg2);
56 };
57
58 ($msg:literal, component = $component:expr, color = $color:expr) => {
60 log::trace!(component = $component, color = $color as u8; $msg);
61 };
62 ($fmt:literal, $arg1:expr, component = $component:expr, color = $color:expr) => {
63 log::trace!(component = $component, color = $color as u8; $fmt, $arg1);
64 };
65 ($fmt:literal, $arg1:expr, $arg2:expr, component = $component:expr, color = $color:expr) => {
66 log::trace!(component = $component, color = $color as u8; $fmt, $arg1, $arg2);
67 };
68
69 ($msg:literal, component = $component:expr) => {
71 log::trace!(component = $component; $msg);
72 };
73 ($fmt:literal, $arg1:expr, component = $component:expr) => {
74 log::trace!(component = $component; $fmt, $arg1);
75 };
76 ($fmt:literal, $arg1:expr, $arg2:expr, component = $component:expr) => {
77 log::trace!(component = $component; $fmt, $arg1, $arg2);
78 };
79
80 ($msg:literal, color = $color:expr) => {
82 log::trace!(color = $color as u8; $msg);
83 };
84 ($fmt:literal, $arg1:expr, color = $color:expr) => {
85 log::trace!(color = $color as u8; $fmt, $arg1);
86 };
87 ($fmt:literal, $arg1:expr, $arg2:expr, color = $color:expr) => {
88 log::trace!(color = $color as u8; $fmt, $arg1, $arg2);
89 };
90 ($fmt:literal, $arg1:expr, $arg2:expr, $arg3:expr, color = $color:expr) => {
91 log::trace!(color = $color as u8; $fmt, $arg1, $arg2, $arg3);
92 };
93
94 ($msg:literal) => {
96 log::trace!(component = module_path!(), color = $crate::enums::LogColor::Normal as u8; $msg);
97 };
98 ($fmt:literal, $($args:expr),+) => {
99 log::trace!(component = module_path!(), color = $crate::enums::LogColor::Normal as u8; $fmt, $($args),+);
100 };
101}
102
103#[macro_export]
133macro_rules! log_debug {
134 ($msg:literal, color = $color:expr, component = $component:expr) => {
136 log::debug!(component = $component, color = $color as u8; $msg);
137 };
138 ($fmt:literal, $arg1:expr, color = $color:expr, component = $component:expr) => {
139 log::debug!(component = $component, color = $color as u8; $fmt, $arg1);
140 };
141 ($fmt:literal, $arg1:expr, $arg2:expr, color = $color:expr, component = $component:expr) => {
142 log::debug!(component = $component, color = $color as u8; $fmt, $arg1, $arg2);
143 };
144
145 ($msg:literal, component = $component:expr, color = $color:expr) => {
147 log::debug!(component = $component, color = $color as u8; $msg);
148 };
149 ($fmt:literal, $arg1:expr, component = $component:expr, color = $color:expr) => {
150 log::debug!(component = $component, color = $color as u8; $fmt, $arg1);
151 };
152 ($fmt:literal, $arg1:expr, $arg2:expr, component = $component:expr, color = $color:expr) => {
153 log::debug!(component = $component, color = $color as u8; $fmt, $arg1, $arg2);
154 };
155
156 ($msg:literal, component = $component:expr) => {
158 log::debug!(component = $component; $msg);
159 };
160 ($fmt:literal, $arg1:expr, component = $component:expr) => {
161 log::debug!(component = $component; $fmt, $arg1);
162 };
163 ($fmt:literal, $arg1:expr, $arg2:expr, component = $component:expr) => {
164 log::debug!(component = $component; $fmt, $arg1, $arg2);
165 };
166
167 ($msg:literal, color = $color:expr) => {
169 log::debug!(color = $color as u8; $msg);
170 };
171 ($fmt:literal, $arg1:expr, color = $color:expr) => {
172 log::debug!(color = $color as u8; $fmt, $arg1);
173 };
174 ($fmt:literal, $arg1:expr, $arg2:expr, color = $color:expr) => {
175 log::debug!(color = $color as u8; $fmt, $arg1, $arg2);
176 };
177 ($fmt:literal, $arg1:expr, $arg2:expr, $arg3:expr, color = $color:expr) => {
178 log::debug!(color = $color as u8; $fmt, $arg1, $arg2, $arg3);
179 };
180
181 ($msg:literal) => {
183 log::debug!(component = module_path!(), color = $crate::enums::LogColor::Normal as u8; $msg);
184 };
185 ($fmt:literal, $($args:expr),+) => {
186 log::debug!(component = module_path!(), color = $crate::enums::LogColor::Normal as u8; $fmt, $($args),+);
187 };
188}
189
190#[macro_export]
224macro_rules! log_info {
225 ($msg:literal, color = $color:expr, component = $component:expr) => {
227 log::info!(component = $component, color = $color as u8; $msg);
228 };
229 ($fmt:literal, $arg1:expr, color = $color:expr, component = $component:expr) => {
230 log::info!(component = $component, color = $color as u8; $fmt, $arg1);
231 };
232 ($fmt:literal, $arg1:expr, $arg2:expr, color = $color:expr, component = $component:expr) => {
233 log::info!(component = $component, color = $color as u8; $fmt, $arg1, $arg2);
234 };
235
236 ($msg:literal, component = $component:expr, color = $color:expr) => {
238 log::info!(component = $component, color = $color as u8; $msg);
239 };
240 ($fmt:literal, $arg1:expr, component = $component:expr, color = $color:expr) => {
241 log::info!(component = $component, color = $color as u8; $fmt, $arg1);
242 };
243 ($fmt:literal, $arg1:expr, $arg2:expr, component = $component:expr, color = $color:expr) => {
244 log::info!(component = $component, color = $color as u8; $fmt, $arg1, $arg2);
245 };
246
247 ($msg:literal, component = $component:expr) => {
249 log::info!(component = $component; $msg);
250 };
251 ($fmt:literal, $arg1:expr, component = $component:expr) => {
252 log::info!(component = $component; $fmt, $arg1);
253 };
254 ($fmt:literal, $arg1:expr, $arg2:expr, component = $component:expr) => {
255 log::info!(component = $component; $fmt, $arg1, $arg2);
256 };
257
258 ($msg:literal, color = $color:expr) => {
260 log::info!(color = $color as u8; $msg);
261 };
262 ($fmt:literal, $arg1:expr, color = $color:expr) => {
263 log::info!(color = $color as u8; $fmt, $arg1);
264 };
265 ($fmt:literal, $arg1:expr, $arg2:expr, color = $color:expr) => {
266 log::info!(color = $color as u8; $fmt, $arg1, $arg2);
267 };
268 ($fmt:literal, $arg1:expr, $arg2:expr, $arg3:expr, color = $color:expr) => {
269 log::info!(color = $color as u8; $fmt, $arg1, $arg2, $arg3);
270 };
271
272 ($msg:literal) => {
274 log::info!(component = module_path!(), color = $crate::enums::LogColor::Normal as u8; $msg);
275 };
276 ($fmt:literal, $($args:expr),+) => {
277 log::info!(component = module_path!(), color = $crate::enums::LogColor::Normal as u8; $fmt, $($args),+);
278 };
279}
280
281#[macro_export]
309macro_rules! log_warn {
310 ($msg:literal, color = $color:expr, component = $component:expr) => {
312 log::warn!(component = $component, color = $color as u8; $msg);
313 };
314 ($fmt:literal, $arg1:expr, color = $color:expr, component = $component:expr) => {
315 log::warn!(component = $component, color = $color as u8; $fmt, $arg1);
316 };
317 ($fmt:literal, $arg1:expr, $arg2:expr, color = $color:expr, component = $component:expr) => {
318 log::warn!(component = $component, color = $color as u8; $fmt, $arg1, $arg2);
319 };
320
321 ($msg:literal, component = $component:expr, color = $color:expr) => {
323 log::warn!(component = $component, color = $color as u8; $msg);
324 };
325 ($fmt:literal, $arg1:expr, component = $component:expr, color = $color:expr) => {
326 log::warn!(component = $component, color = $color as u8; $fmt, $arg1);
327 };
328 ($fmt:literal, $arg1:expr, $arg2:expr, component = $component:expr, color = $color:expr) => {
329 log::warn!(component = $component, color = $color as u8; $fmt, $arg1, $arg2);
330 };
331
332 ($msg:literal, component = $component:expr) => {
334 log::warn!(component = $component, color = $crate::enums::LogColor::Yellow as u8; $msg);
335 };
336 ($fmt:literal, $arg1:expr, component = $component:expr) => {
337 log::warn!(component = $component, color = $crate::enums::LogColor::Yellow as u8; $fmt, $arg1);
338 };
339 ($fmt:literal, $arg1:expr, $arg2:expr, component = $component:expr) => {
340 log::warn!(component = $component, color = $crate::enums::LogColor::Yellow as u8; $fmt, $arg1, $arg2);
341 };
342
343 ($msg:literal, color = $color:expr) => {
345 log::warn!(color = $color as u8; $msg);
346 };
347 ($fmt:literal, $arg1:expr, color = $color:expr) => {
348 log::warn!(color = $color as u8; $fmt, $arg1);
349 };
350 ($fmt:literal, $arg1:expr, $arg2:expr, color = $color:expr) => {
351 log::warn!(color = $color as u8; $fmt, $arg1, $arg2);
352 };
353 ($fmt:literal, $arg1:expr, $arg2:expr, $arg3:expr, color = $color:expr) => {
354 log::warn!(color = $color as u8; $fmt, $arg1, $arg2, $arg3);
355 };
356
357 ($msg:literal) => {
359 log::warn!(component = module_path!(), color = $crate::enums::LogColor::Yellow as u8; $msg);
360 };
361 ($fmt:literal, $($args:expr),+) => {
362 log::warn!(component = module_path!(), color = $crate::enums::LogColor::Yellow as u8; $fmt, $($args),+);
363 };
364}
365
366#[macro_export]
396macro_rules! log_error {
397 ($msg:literal, color = $color:expr, component = $component:expr) => {
399 log::error!(component = $component, color = $color as u8; $msg);
400 };
401 ($fmt:literal, $arg1:expr, color = $color:expr, component = $component:expr) => {
402 log::error!(component = $component, color = $color as u8; $fmt, $arg1);
403 };
404 ($fmt:literal, $arg1:expr, $arg2:expr, color = $color:expr, component = $component:expr) => {
405 log::error!(component = $component, color = $color as u8; $fmt, $arg1, $arg2);
406 };
407
408 ($msg:literal, component = $component:expr, color = $color:expr) => {
410 log::error!(component = $component, color = $color as u8; $msg);
411 };
412 ($fmt:literal, $arg1:expr, component = $component:expr, color = $color:expr) => {
413 log::error!(component = $component, color = $color as u8; $fmt, $arg1);
414 };
415 ($fmt:literal, $arg1:expr, $arg2:expr, component = $component:expr, color = $color:expr) => {
416 log::error!(component = $component, color = $color as u8; $fmt, $arg1, $arg2);
417 };
418
419 ($msg:literal, component = $component:expr) => {
421 log::error!(component = $component, color = $crate::enums::LogColor::Red as u8; $msg);
422 };
423 ($fmt:literal, $arg1:expr, component = $component:expr) => {
424 log::error!(component = $component, color = $crate::enums::LogColor::Red as u8; $fmt, $arg1);
425 };
426 ($fmt:literal, $arg1:expr, $arg2:expr, component = $component:expr) => {
427 log::error!(component = $component, color = $crate::enums::LogColor::Red as u8; $fmt, $arg1, $arg2);
428 };
429
430 ($msg:literal, color = $color:expr) => {
432 log::error!(color = $color as u8; $msg);
433 };
434 ($fmt:literal, $arg1:expr, color = $color:expr) => {
435 log::error!(color = $color as u8; $fmt, $arg1);
436 };
437 ($fmt:literal, $arg1:expr, $arg2:expr, color = $color:expr) => {
438 log::error!(color = $color as u8; $fmt, $arg1, $arg2);
439 };
440 ($fmt:literal, $arg1:expr, $arg2:expr, $arg3:expr, color = $color:expr) => {
441 log::error!(color = $color as u8; $fmt, $arg1, $arg2, $arg3);
442 };
443
444 ($msg:literal) => {
446 log::error!(component = module_path!(), color = $crate::enums::LogColor::Red as u8; $msg);
447 };
448 ($fmt:literal, $($args:expr),+) => {
449 log::error!(component = module_path!(), color = $crate::enums::LogColor::Red as u8; $fmt, $($args),+);
450 };
451}
452
453pub use log_debug;
455pub use log_error;
456pub use log_info;
457pub use log_trace;
458pub use log_warn;
459
460#[cfg(all(test, not(all(feature = "simulation", madsim))))]
465mod tests {
466 use std::{thread::sleep, time::Duration};
467
468 use nautilus_core::UUID4;
469 use nautilus_model::identifiers::TraderId;
470 use rstest::*;
471 use tempfile::tempdir;
472
473 use crate::{
474 enums::LogColor,
475 logging::{
476 logger::{Logger, LoggerConfig},
477 logging_clock_set_static_mode, logging_clock_set_static_time,
478 writer::FileWriterConfig,
479 },
480 testing::wait_until,
481 };
482
483 #[rstest]
484 fn test_colored_logging_macros() {
485 let config = LoggerConfig::from_spec("stdout=Trace;fileout=Trace;is_colored").unwrap();
486
487 let temp_dir = tempdir().expect("Failed to create temporary directory");
488 let file_config = FileWriterConfig {
489 directory: Some(temp_dir.path().to_str().unwrap().to_string()),
490 ..Default::default()
491 };
492
493 let log_guard = Logger::init_with_config(
494 TraderId::from("TRADER-001"),
495 UUID4::new(),
496 config,
497 file_config,
498 )
499 .expect("Failed to initialize logger");
500
501 logging_clock_set_static_mode();
502 logging_clock_set_static_time(1_650_000_000_000_000);
503
504 log_trace!("This is a trace message", component = "TestComponent");
506 log_debug!("This is a debug message", component = "TestComponent");
507 log_info!("This is an info message", component = "TestComponent");
508 log_warn!("This is a warning message", component = "TestComponent");
509 log_error!("This is an error message", component = "TestComponent");
510
511 log_info!(
513 "Success message",
514 color = LogColor::Green,
515 component = "TestComponent"
516 );
517 log_info!(
518 "Information message",
519 color = LogColor::Blue,
520 component = "TestComponent"
521 );
522 log_warn!(
523 "Custom warning",
524 component = "TestComponent",
525 color = LogColor::Magenta
526 );
527
528 log_info!("Component test", component = "TestComponent");
530 log_warn!("Component warning", component = "TestComponent");
531
532 log_info!(
534 "Color then component",
535 color = LogColor::Cyan,
536 component = "TestComponent"
537 );
538 log_trace!(
539 "Trace color then component",
540 color = LogColor::Cyan,
541 component = "TestComponent"
542 );
543 log_trace!(
544 "Trace component then color",
545 component = "TestComponent",
546 color = LogColor::Cyan
547 );
548
549 sleep(Duration::from_millis(200));
551
552 drop(log_guard);
553
554 let mut log_contents = String::new();
556 wait_until(
557 || {
558 if let Some(log_file) = std::fs::read_dir(&temp_dir)
559 .expect("Failed to read directory")
560 .filter_map(Result::ok)
561 .find(|entry| entry.path().is_file())
562 {
563 let log_file_path = log_file.path();
564 log_contents =
565 std::fs::read_to_string(log_file_path).expect("Failed to read log file");
566 !log_contents.is_empty()
567 } else {
568 false
569 }
570 },
571 Duration::from_secs(3),
572 );
573
574 if !log_contents.contains("This is a trace message") {
576 println!("File contents:\n{log_contents}");
577 }
578
579 assert!(log_contents.contains("This is a trace message"));
581 assert!(log_contents.contains("This is a debug message"));
582 assert!(log_contents.contains("This is an info message"));
583 assert!(log_contents.contains("This is a warning message"));
584 assert!(log_contents.contains("This is an error message"));
585 assert!(log_contents.contains("Success message"));
586 assert!(log_contents.contains("Information message"));
587 assert!(log_contents.contains("Custom warning"));
588
589 assert!(log_contents.contains("Component test"));
591 assert!(log_contents.contains("Component warning"));
592 assert!(log_contents.contains("Color then component"));
593 assert!(log_contents.contains("Trace color then component"));
594 assert!(log_contents.contains("Trace component then color"));
595 }
596
597 #[rstest]
598 fn test_default_macro_captures_module_path() {
599 let config = LoggerConfig::from_spec(
606 "stdout=Off;fileout=Trace;nautilus_common::logging::macros=Debug",
607 )
608 .unwrap();
609
610 let temp_dir = tempdir().expect("Failed to create temporary directory");
611 let file_config = FileWriterConfig {
612 directory: Some(temp_dir.path().to_str().unwrap().to_string()),
613 ..Default::default()
614 };
615
616 let log_guard = Logger::init_with_config(
617 TraderId::from("TRADER-PATH"),
618 UUID4::new(),
619 config,
620 file_config,
621 )
622 .expect("Failed to initialize logger");
623
624 logging_clock_set_static_mode();
625 logging_clock_set_static_time(1_650_000_000_000_000);
626
627 log_info!("Auto-captured module path message");
629 log_debug!("Debug level auto-captured");
630
631 log_trace!("Trace should be filtered SHOULD_NOT_APPEAR");
633
634 sleep(Duration::from_millis(200));
635 drop(log_guard);
636
637 let mut log_contents = String::new();
638 wait_until(
639 || {
640 if let Some(log_file) = std::fs::read_dir(&temp_dir)
641 .expect("Failed to read directory")
642 .filter_map(Result::ok)
643 .find(|entry| entry.path().is_file())
644 {
645 log_contents =
646 std::fs::read_to_string(log_file.path()).expect("Failed to read log file");
647 !log_contents.is_empty()
648 } else {
649 false
650 }
651 },
652 Duration::from_secs(3),
653 );
654
655 assert!(
656 log_contents.contains("nautilus_common::logging::macros"),
657 "Component should contain module path, was:\n{log_contents}"
658 );
659 assert!(
660 log_contents.contains("Auto-captured module path message"),
661 "Info message should pass"
662 );
663 assert!(
664 log_contents.contains("Debug level auto-captured"),
665 "Debug message should pass"
666 );
667 assert!(
668 !log_contents.contains("SHOULD_NOT_APPEAR"),
669 "Trace should be filtered by module filter"
670 );
671 }
672}