oxibonsai_runtime/
tracing_setup.rs1#[cfg(not(target_arch = "wasm32"))]
10use tracing_subscriber::{fmt, prelude::*, EnvFilter};
11
12#[derive(Debug, Clone)]
14pub struct TracingConfig {
15 pub log_level: String,
17 pub json_output: bool,
19 pub with_file: bool,
21 pub with_line_number: bool,
23 pub with_target: bool,
25}
26
27impl Default for TracingConfig {
28 fn default() -> Self {
29 Self {
30 log_level: "info".to_string(),
31 json_output: false,
32 with_file: false,
33 with_line_number: false,
34 with_target: true,
35 }
36 }
37}
38
39impl TracingConfig {
40 pub fn from_observability(obs: &crate::config::ObservabilityConfig) -> Self {
42 Self {
43 log_level: obs.log_level.clone(),
44 json_output: obs.json_logs,
45 ..Self::default()
46 }
47 }
48}
49
50#[cfg(not(target_arch = "wasm32"))]
64pub fn init_tracing(config: &TracingConfig) -> Result<(), Box<dyn std::error::Error>> {
65 let env_filter =
66 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(&config.log_level));
67
68 if config.json_output {
69 tracing_subscriber::registry()
70 .with(env_filter)
71 .with(fmt::layer().json())
72 .try_init()
73 .map_err(|e| -> Box<dyn std::error::Error> {
74 Box::new(std::io::Error::other(format!(
75 "failed to init tracing: {e}"
76 )))
77 })?;
78 } else {
79 tracing_subscriber::registry()
80 .with(env_filter)
81 .with(
82 fmt::layer()
83 .with_file(config.with_file)
84 .with_line_number(config.with_line_number)
85 .with_target(config.with_target),
86 )
87 .try_init()
88 .map_err(|e| -> Box<dyn std::error::Error> {
89 Box::new(std::io::Error::other(format!(
90 "failed to init tracing: {e}"
91 )))
92 })?;
93 }
94
95 Ok(())
96}
97
98#[cfg(target_arch = "wasm32")]
100pub fn init_tracing(_config: &TracingConfig) -> Result<(), Box<dyn std::error::Error>> {
101 Ok(())
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn default_config_values() {
110 let cfg = TracingConfig::default();
111 assert_eq!(cfg.log_level, "info");
112 assert!(!cfg.json_output);
113 assert!(!cfg.with_file);
114 assert!(!cfg.with_line_number);
115 assert!(cfg.with_target);
116 }
117
118 #[test]
119 fn from_observability_config() {
120 let obs = crate::config::ObservabilityConfig {
121 log_level: "debug".to_string(),
122 json_logs: true,
123 };
124 let cfg = TracingConfig::from_observability(&obs);
125 assert_eq!(cfg.log_level, "debug");
126 assert!(cfg.json_output);
127 }
128
129 #[test]
130 fn tracing_config_clone() {
131 let cfg = TracingConfig {
132 log_level: "warn".to_string(),
133 json_output: true,
134 with_file: true,
135 with_line_number: true,
136 with_target: false,
137 };
138 let cloned = cfg.clone();
139 assert_eq!(cloned.log_level, "warn");
140 assert!(cloned.json_output);
141 assert!(cloned.with_file);
142 assert!(cloned.with_line_number);
143 assert!(!cloned.with_target);
144 }
145
146 #[test]
147 fn tracing_config_debug() {
148 let cfg = TracingConfig::default();
149 let debug_str = format!("{cfg:?}");
150 assert!(debug_str.contains("TracingConfig"));
151 assert!(debug_str.contains("info"));
152 }
153}