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