openmina_node_common/
tracing.rs1pub 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 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;