reth_tracing/formatter.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
use crate::layers::BoxedLayer;
use clap::ValueEnum;
use std::{fmt, fmt::Display};
use tracing_appender::non_blocking::NonBlocking;
use tracing_subscriber::{EnvFilter, Layer, Registry};
/// Represents the logging format.
///
/// This enum defines the supported formats for logging output.
/// It is used to configure the format layer of a tracing subscriber.
#[derive(Debug, Copy, Clone, ValueEnum, Eq, PartialEq)]
pub enum LogFormat {
/// Represents JSON formatting for logs.
/// This format outputs log records as JSON objects,
/// making it suitable for structured logging.
Json,
/// Represents logfmt (key=value) formatting for logs.
/// This format is concise and human-readable,
/// typically used in command-line applications.
LogFmt,
/// Represents terminal-friendly formatting for logs.
Terminal,
}
impl LogFormat {
/// Applies the specified logging format to create a new layer.
///
/// This method constructs a tracing layer with the selected format,
/// along with additional configurations for filtering and output.
///
/// # Arguments
/// * `filter` - An `EnvFilter` used to determine which log records to output.
/// * `color` - An optional string that enables or disables ANSI color codes in the logs.
/// * `file_writer` - An optional `NonBlocking` writer for directing logs to a file.
///
/// # Returns
/// A `BoxedLayer<Registry>` that can be added to a tracing subscriber.
pub fn apply(
&self,
filter: EnvFilter,
color: Option<String>,
file_writer: Option<NonBlocking>,
) -> BoxedLayer<Registry> {
let ansi = if let Some(color) = color {
std::env::var("RUST_LOG_STYLE").map(|val| val != "never").unwrap_or(color != "never")
} else {
false
};
let target = std::env::var("RUST_LOG_TARGET")
// `RUST_LOG_TARGET` always overrides default behaviour
.map(|val| val != "0")
.unwrap_or_else(|_|
// If `RUST_LOG_TARGET` is not set, show target in logs only if the max enabled
// level is higher than INFO (DEBUG, TRACE)
filter.max_level_hint().is_none_or(|max_level| max_level > tracing::Level::INFO));
match self {
Self::Json => {
let layer =
tracing_subscriber::fmt::layer().json().with_ansi(ansi).with_target(target);
if let Some(writer) = file_writer {
layer.with_writer(writer).with_filter(filter).boxed()
} else {
layer.with_filter(filter).boxed()
}
}
Self::LogFmt => tracing_logfmt::layer().with_filter(filter).boxed(),
Self::Terminal => {
let layer = tracing_subscriber::fmt::layer().with_ansi(ansi).with_target(target);
if let Some(writer) = file_writer {
layer.with_writer(writer).with_filter(filter).boxed()
} else {
layer.with_filter(filter).boxed()
}
}
}
}
}
impl Display for LogFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Json => write!(f, "json"),
Self::LogFmt => write!(f, "logfmt"),
Self::Terminal => write!(f, "terminal"),
}
}
}