use tracing::Subscriber;
use tracing_subscriber::{registry::LookupSpan, Layer};
use crate::config::{TracingConfig, WriterConfig};
use crate::Error;
pub trait LayerBuilder: Send + Sync {
fn build_layer<S>(
&self,
config: &TracingConfig,
) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
where
S: Subscriber + for<'a> LookupSpan<'a>;
}
#[derive(Debug, Default, Clone)]
pub struct PrettyLayerBuilder;
impl LayerBuilder for PrettyLayerBuilder {
fn build_layer<S>(
&self,
config: &TracingConfig,
) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
let mut layer = tracing_subscriber::fmt::layer()
.pretty()
.with_timer(tracing_subscriber::fmt::time::uptime());
if config.features.line_numbers {
layer = layer.with_line_number(true);
}
if config.features.thread_names {
layer = layer.with_thread_names(true);
}
if let Some(span_events) = &config.features.span_events {
layer = layer.with_span_events(span_events.clone());
}
if !config.features.target_display {
layer = layer.with_target(false);
}
match &config.writer {
WriterConfig::Stdout => Ok(Box::new(layer.with_writer(std::io::stdout))),
WriterConfig::Stderr => Ok(Box::new(layer.with_writer(std::io::stderr))),
WriterConfig::File(path) => {
let file = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(path)?;
Ok(Box::new(layer.with_writer(file)))
}
}
}
}
#[derive(Debug, Default, Clone)]
pub struct JsonLayerBuilder;
impl LayerBuilder for JsonLayerBuilder {
fn build_layer<S>(
&self,
config: &TracingConfig,
) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
let mut layer = tracing_subscriber::fmt::layer()
.json()
.with_timer(tracing_subscriber::fmt::time::uptime());
if config.features.line_numbers {
layer = layer.with_line_number(true);
}
if config.features.thread_names {
layer = layer.with_thread_names(true);
}
if let Some(span_events) = &config.features.span_events {
layer = layer.with_span_events(span_events.clone());
}
if !config.features.target_display {
layer = layer.with_target(false);
}
match &config.writer {
WriterConfig::Stdout => Ok(Box::new(layer.with_writer(std::io::stdout))),
WriterConfig::Stderr => Ok(Box::new(layer.with_writer(std::io::stderr))),
WriterConfig::File(path) => {
let file = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(path)?;
Ok(Box::new(layer.with_writer(file)))
}
}
}
}
#[derive(Debug, Default, Clone)]
pub struct CompactLayerBuilder;
impl LayerBuilder for CompactLayerBuilder {
fn build_layer<S>(
&self,
config: &TracingConfig,
) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
let mut layer = tracing_subscriber::fmt::layer()
.compact()
.with_timer(tracing_subscriber::fmt::time::uptime());
if config.features.line_numbers {
layer = layer.with_line_number(true);
}
if config.features.thread_names {
layer = layer.with_thread_names(true);
}
if let Some(span_events) = &config.features.span_events {
layer = layer.with_span_events(span_events.clone());
}
if !config.features.target_display {
layer = layer.with_target(false);
}
match &config.writer {
WriterConfig::Stdout => Ok(Box::new(layer.with_writer(std::io::stdout))),
WriterConfig::Stderr => Ok(Box::new(layer.with_writer(std::io::stderr))),
WriterConfig::File(path) => {
let file = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(path)?;
Ok(Box::new(layer.with_writer(file)))
}
}
}
}
#[cfg(feature = "logfmt")]
#[derive(Debug, Default, Clone)]
pub struct LogfmtLayerBuilder;
#[cfg(feature = "logfmt")]
impl LayerBuilder for LogfmtLayerBuilder {
fn build_layer<S>(
&self,
config: &TracingConfig,
) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
match &config.writer {
WriterConfig::Stderr => {
Ok(Box::new(tracing_logfmt::layer()))
}
_ => {
Ok(Box::new(tracing_logfmt::layer()))
}
}
}
}