1#![doc = include_str!("../README.md")]
2#![warn(clippy::pedantic)]
3
4#[cfg(feature = "console")]
5pub mod console;
6#[cfg(feature = "lines")]
7pub mod lines;
8#[cfg(feature = "otel")]
9pub mod otel;
10
11use std::fs::OpenOptions;
12
13use anyhow::Result;
14use bon::builder;
15use bon::Builder;
16use camino::Utf8PathBuf;
17use tracing_log::LogTracer;
18use tracing_subscriber::fmt::writer::BoxMakeWriter;
19use tracing_subscriber::layer::SubscriberExt;
20use tracing_subscriber::EnvFilter;
21use tracing_subscriber::Layer;
22use tracing_subscriber::Registry;
23
24pub type BoxLayer = Box<dyn Layer<Registry> + Send + Sync>;
26
27#[derive(Debug, Clone, Builder)]
29pub struct TracingConfig {
30 #[cfg(feature = "lines")]
31 #[builder(default = Utf8PathBuf::from("/dev/fd/2"))]
33 log_file: Utf8PathBuf,
34
35 #[cfg(feature = "lines")]
36 #[builder(default = String::from("info"))]
38 log_level: String,
39
40 #[cfg(feature = "lines")]
41 #[builder(default = lines::LinesFormat::Glog)]
43 log_format: lines::LinesFormat,
44
45 #[cfg(feature = "otel")]
46 #[builder(default = String::from("template-rust"))]
48 service_name: String,
49}
50
51impl Default for TracingConfig {
52 fn default() -> Self {
53 Self::builder().build()
54 }
55}
56
57impl TracingConfig {
58 pub fn init(&self) -> Result<()> {
67 LogTracer::init()?;
69
70 let mut layers = Vec::new();
72
73 #[cfg(feature = "lines")]
74 {
75 let filter = EnvFilter::builder().parse_lossy(&self.log_level);
76 let writer = OpenOptions::new()
77 .create(true)
78 .append(true)
79 .open(&self.log_file)?;
80 let layer = lines::LinesConfig::builder()
81 .writer(BoxMakeWriter::new(writer))
82 .filter(filter)
83 .format(self.log_format)
84 .build()
85 .layer();
86 layers.push(layer);
87 }
88
89 #[cfg(feature = "otel")]
90 {
91 let layer = otel::OtelConfig::builder()
92 .service_name(self.service_name.to_owned())
93 .build()
94 .layer()?;
95 layers.push(layer);
96 }
97
98 #[cfg(feature = "console")]
99 {
100 let layer = console::ConsoleConfig::builder().build().layer();
101 layers.push(layer);
102 }
103
104 let subscriber = tracing_subscriber::registry().with(layers);
105 tracing::subscriber::set_global_default(subscriber)?;
106
107 Ok(())
108 }
109}