1use std::str::FromStr;
2use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum LogFormat {
7 Json,
8 Text,
9}
10
11impl FromStr for LogFormat {
12 type Err = String;
13
14 fn from_str(s: &str) -> Result<Self, Self::Err> {
15 match s.to_lowercase().as_str() {
16 "json" => Ok(LogFormat::Json),
17 "text" => Ok(LogFormat::Text),
18 _ => Err(format!(
19 "Invalid log format '{}'. Valid values: json, text",
20 s
21 )),
22 }
23 }
24}
25
26pub fn init_logging(format: LogFormat, trace_id: Option<String>) {
28 let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
29
30 match format {
31 LogFormat::Json => {
32 let fmt_layer = fmt::layer()
33 .json()
34 .with_current_span(true)
35 .with_span_list(false)
36 .with_writer(std::io::stderr);
37
38 tracing_subscriber::registry()
39 .with(filter)
40 .with(fmt_layer)
41 .init();
42 }
43 LogFormat::Text => {
44 let fmt_layer = fmt::layer().with_writer(std::io::stderr).with_target(false);
45
46 tracing_subscriber::registry()
47 .with(filter)
48 .with(fmt_layer)
49 .init();
50 }
51 }
52
53 if let Some(tid) = trace_id {
55 tracing::info!(traceId = %tid, "Request started");
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use std::str::FromStr;
63
64 #[test]
65 fn test_log_format_from_str() {
66 assert_eq!(LogFormat::from_str("json").unwrap(), LogFormat::Json);
67 assert_eq!(LogFormat::from_str("JSON").unwrap(), LogFormat::Json);
68 assert_eq!(LogFormat::from_str("text").unwrap(), LogFormat::Text);
69 assert_eq!(LogFormat::from_str("TEXT").unwrap(), LogFormat::Text);
70 assert!(LogFormat::from_str("anything").is_err());
71 assert!(LogFormat::from_str("invalid").is_err());
72 }
73}