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 54 : fn default() -> Self {
16 54 : SimClock {
17 54 : clock_ptr: Arc::new(Mutex::new(None)),
18 54 : }
19 54 : }
20 : }
21 :
22 : impl SimClock {
23 12048 : pub fn set_clock(&self, clock: Arc<Timing>) {
24 12048 : *self.clock_ptr.lock() = Some(clock);
25 12048 : }
26 : }
27 :
28 : impl FormatTime for SimClock {
29 79539 : fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
30 79539 : let clock = self.clock_ptr.lock();
31 :
32 79539 : if let Some(clock) = clock.as_ref() {
33 79509 : let now = clock.now();
34 79509 : write!(w, "[{}]", now)
35 : } else {
36 30 : write!(w, "[?]")
37 : }
38 79539 : }
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 54 : pub fn init_tracing_logger(debug_enabled: bool) -> SimClock {
46 54 : LOGGING_DONE
47 54 : .get_or_init(|| {
48 54 : let clock = SimClock::default();
49 54 : let base_logger = tracing_subscriber::fmt()
50 54 : .with_target(false)
51 54 : // prefix log lines with simulated time timestamp
52 54 : .with_timer(clock.clone())
53 54 : // .with_ansi(true) TODO
54 54 : .with_max_level(match debug_enabled {
55 12 : true => tracing::Level::DEBUG,
56 42 : false => tracing::Level::WARN,
57 : })
58 54 : .with_writer(std::io::stdout);
59 54 : base_logger.init();
60 54 :
61 54 : // logging::replace_panic_hook_with_tracing_panic_hook().forget();
62 54 :
63 54 : if !debug_enabled {
64 466576 : std::panic::set_hook(Box::new(|_| {}));
65 42 : }
66 :
67 54 : clock
68 54 : })
69 54 : .clone()
70 54 : }
71 :
72 42 : pub fn init_logger() -> SimClock {
73 42 : // RUST_TRACEBACK envvar controls whether we print all logs or only warnings.
74 42 : let debug_enabled = std::env::var("RUST_TRACEBACK").is_ok();
75 42 :
76 42 : init_tracing_logger(debug_enabled)
77 42 : }
|