Line data Source code
1 : use std::{fmt, sync::Arc};
2 :
3 : use desim::time::Timing;
4 : use once_cell::sync::OnceCell;
5 : use parking_lot::Mutex;
6 : use tracing_subscriber::fmt::{format::Writer, time::FormatTime};
7 :
8 : /// SimClock can be plugged into tracing logger to print simulation time.
9 : #[derive(Clone)]
10 : pub struct SimClock {
11 : clock_ptr: Arc<Mutex<Option<Arc<Timing>>>>,
12 : }
13 :
14 : impl Default for SimClock {
15 9 : fn default() -> Self {
16 9 : SimClock {
17 9 : clock_ptr: Arc::new(Mutex::new(None)),
18 9 : }
19 9 : }
20 : }
21 :
22 : impl SimClock {
23 2008 : pub fn set_clock(&self, clock: Arc<Timing>) {
24 2008 : *self.clock_ptr.lock() = Some(clock);
25 2008 : }
26 : }
27 :
28 : impl FormatTime for SimClock {
29 13257 : fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
30 13257 : let clock = self.clock_ptr.lock();
31 :
32 13257 : if let Some(clock) = clock.as_ref() {
33 13252 : let now = clock.now();
34 13252 : write!(w, "[{}]", now)
35 : } else {
36 5 : write!(w, "[?]")
37 : }
38 13257 : }
39 : }
40 :
41 : static LOGGING_DONE: OnceCell<SimClock> = OnceCell::new();
42 :
43 : /// Returns ptr to clocks attached to tracing logger to update them when the
44 : /// world is (re)created.
45 9 : pub fn init_tracing_logger(debug_enabled: bool) -> SimClock {
46 9 : LOGGING_DONE
47 9 : .get_or_init(|| {
48 9 : let clock = SimClock::default();
49 9 : let base_logger = tracing_subscriber::fmt()
50 9 : .with_target(false)
51 9 : // prefix log lines with simulated time timestamp
52 9 : .with_timer(clock.clone())
53 9 : // .with_ansi(true) TODO
54 9 : .with_max_level(match debug_enabled {
55 2 : true => tracing::Level::DEBUG,
56 7 : false => tracing::Level::WARN,
57 : })
58 9 : .with_writer(std::io::stdout);
59 9 : base_logger.init();
60 9 :
61 9 : // logging::replace_panic_hook_with_tracing_panic_hook().forget();
62 9 :
63 9 : if !debug_enabled {
64 77687 : std::panic::set_hook(Box::new(|_| {}));
65 7 : }
66 :
67 9 : clock
68 9 : })
69 9 : .clone()
70 9 : }
71 :
72 7 : pub fn init_logger() -> SimClock {
73 7 : // RUST_TRACEBACK envvar controls whether we print all logs or only warnings.
74 7 : let debug_enabled = std::env::var("RUST_TRACEBACK").is_ok();
75 7 :
76 7 : init_tracing_logger(debug_enabled)
77 7 : }
|