openmina_node_common/
tracing.rs

1pub use tracing::Level;
2
3#[cfg(not(target_family = "wasm"))]
4mod native {
5    use std::{fmt::Result, path::PathBuf};
6    use tracing::{field::Visit, level_filters::LevelFilter, Level};
7    use tracing_appender::non_blocking::WorkerGuard;
8    use tracing_subscriber::{
9        field::{RecordFields, VisitOutput},
10        fmt::{
11            format::{PrettyVisitor, Writer},
12            time::FormatTime,
13            FormatFields,
14        },
15        layer::SubscriberExt,
16        Layer,
17    };
18
19    #[allow(unused)]
20    fn redux_timer(w: &mut Writer<'_>) -> Result {
21        match redux::SystemTime::now().duration_since(redux::SystemTime::UNIX_EPOCH) {
22            Ok(v) => {
23                write!(w, "{}", v.as_nanos())
24            }
25            Err(_) => write!(w, "unknown-time"),
26        }
27    }
28
29    #[allow(dead_code)]
30    struct ReduxTimer;
31
32    impl FormatTime for ReduxTimer {
33        fn format_time(&self, w: &mut Writer<'_>) -> Result {
34            redux_timer(w)
35        }
36    }
37
38    struct FilterVisit<T>(T);
39
40    impl<T> FilterVisit<T> {
41        fn into_inner(self) -> T {
42            self.0
43        }
44    }
45
46    impl<T> Visit for FilterVisit<T>
47    where
48        T: Visit,
49    {
50        fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
51            if !field.name().starts_with("trace_") {
52                self.0.record_debug(field, value);
53            }
54        }
55    }
56
57    #[derive(Default)]
58    struct TracingFieldFormatter;
59
60    impl<'writer> FormatFields<'writer> for TracingFieldFormatter {
61        fn format_fields<R: RecordFields>(
62            &self,
63            writer: Writer<'writer>,
64            fields: R,
65        ) -> std::fmt::Result {
66            let mut v = FilterVisit(PrettyVisitor::new(writer, true));
67            fields.record(&mut v);
68            v.into_inner().finish()
69        }
70    }
71
72    pub fn initialize(max_log_level: Level) {
73        let builder = tracing_subscriber::FmtSubscriber::builder()
74            .with_max_level(max_log_level)
75            .with_ansi(std::io::IsTerminal::is_terminal(&std::io::stdout()))
76            .with_test_writer();
77        //.with_timer(ReduxTimer)
78
79        if max_log_level != Level::TRACE {
80            let subscriber = builder.fmt_fields(TracingFieldFormatter).finish();
81            tracing::subscriber::set_global_default(subscriber)
82        } else {
83            let subscriber = builder.finish();
84            tracing::subscriber::set_global_default(subscriber)
85        }
86        .expect("global subscriber should be configurable");
87    }
88
89    pub fn initialize_with_filesystem_output(
90        max_log_level: Level,
91        log_output_dir: PathBuf,
92    ) -> WorkerGuard {
93        let file_appender = tracing_appender::rolling::daily(log_output_dir, "openmina.log");
94        let (file_writer, file_guard) = tracing_appender::non_blocking(file_appender);
95        let level_filter = LevelFilter::from_level(max_log_level);
96
97        let file_layer = tracing_subscriber::fmt::layer()
98            .with_writer(file_writer)
99            .with_ansi(false)
100            .with_filter(level_filter);
101
102        let stdout_layer = tracing_subscriber::fmt::layer()
103            .with_writer(std::io::stdout)
104            .with_ansi(std::io::IsTerminal::is_terminal(&std::io::stdout()))
105            .with_filter(level_filter);
106
107        let subscriber = tracing_subscriber::Registry::default()
108            .with(file_layer)
109            .with(stdout_layer);
110
111        tracing::subscriber::set_global_default(subscriber)
112            .expect("Failed to set global subscriber");
113
114        file_guard
115    }
116}
117
118#[cfg(target_family = "wasm")]
119mod web {
120    use super::*;
121    use tracing_wasm::{set_as_global_default_with_config, WASMLayerConfigBuilder};
122
123    pub fn initialize(max_log_level: Level) {
124        let mut config = WASMLayerConfigBuilder::new();
125        config.set_max_level(max_log_level);
126        set_as_global_default_with_config(config.build());
127    }
128}
129
130#[cfg(not(target_family = "wasm"))]
131pub use native::{initialize, initialize_with_filesystem_output};
132#[cfg(target_family = "wasm")]
133pub use web::initialize;