Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Json structured logs #5784

Merged
merged 31 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9e14aa0
feat: first structure
loocapro Dec 14, 2023
63cec0c
feat: moving on
loocapro Dec 14, 2023
ae5310e
some naming
loocapro Dec 14, 2023
d687fe5
feat: docs default directive still needs some work
loocapro Dec 15, 2023
b10012f
feat: docs and doctest
loocapro Dec 15, 2023
71eab40
Merge remote-tracking branch 'origin' into json-structured-logs
loocapro Dec 22, 2023
e51d15e
Update crates/tracing/src/layers.rs
loocapro Dec 22, 2023
f24f3c7
Update crates/tracing/src/layers.rs
loocapro Dec 22, 2023
80f0f48
Update crates/tracing/src/layers.rs
loocapro Dec 22, 2023
258415f
Merge branch 'json-structured-logs' of https://github.com/loocapro/re…
loocapro Dec 22, 2023
d507250
fix: string reference for filter
loocapro Dec 22, 2023
55db389
feat: hooking up all components and remove old implementation
loocapro Dec 24, 2023
2913a82
feat: cli mod
loocapro Dec 24, 2023
9127c09
Merge remote-tracking branch 'origin' into json-structured-logs
loocapro Dec 24, 2023
eb8542a
fix: clippy
loocapro Dec 24, 2023
5a8dffe
fix: doctest
loocapro Dec 24, 2023
1ccb72b
fix: doctest
loocapro Dec 24, 2023
406d3d5
sync: merged main and aligned latest changes, removed test tracer imp…
loocapro Jan 1, 2024
d3d63ca
Update bin/reth/src/args/log_args.rs
loocapro Jan 3, 2024
498c0b1
Update bin/reth/src/args/log_args.rs
loocapro Jan 3, 2024
7eb80ad
Update bin/reth/src/args/log_args.rs
loocapro Jan 3, 2024
d3c82f5
Update crates/tracing/src/layers.rs
loocapro Jan 3, 2024
eb8f8fb
Update crates/tracing/src/lib.rs
loocapro Jan 3, 2024
df160e3
Update crates/tracing/src/lib.rs
loocapro Jan 3, 2024
96deb56
review comments
loocapro Jan 3, 2024
fa94619
Merge branch 'json-structured-logs' of https://github.com/loocapro/re…
loocapro Jan 3, 2024
1d2423f
fix: create log dir inside log writer
loocapro Jan 3, 2024
855220b
feat: log stdout filter empty as default
loocapro Jan 4, 2024
f6cccd4
fix: empty stdout filter to info
loocapro Jan 4, 2024
e36d317
Update crates/tracing/src/layers.rs
shekhirin Jan 8, 2024
4ef126c
Update crates/tracing/src/lib.rs
shekhirin Jan 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

140 changes: 88 additions & 52 deletions bin/reth/src/args/log_args.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
//! clap [Args](clap::Args) for logging configuration.

use crate::dirs::{LogsDir, PlatformPath};
use clap::{Args, ValueEnum};
use clap::{ArgAction, Args, ValueEnum};
use reth_tracing::{
tracing_subscriber::{registry::LookupSpan, EnvFilter},
BoxedLayer, FileWorkerGuard,
tracing_subscriber::filter::Directive, FileInfo, FileWorkerGuard, LayerInfo, LogFormat,
RethTracer, Tracer,
};
use std::{fmt, fmt::Display};
use tracing::Subscriber;

/// Default [directives](reth_tracing::tracing_subscriber::filter::Directive) for [EnvFilter] which
/// disables high-frequency debug logs from `hyper` and `trust-dns`
const DEFAULT_ENV_FILTER_DIRECTIVES: [&str; 3] =
["hyper::proto::h1=off", "trust_dns_proto=off", "atrust_dns_resolver=off"];

use tracing::{level_filters::LevelFilter, Level};
/// Constant to convert megabytes to bytes
const MB_TO_BYTES: u64 = 1024 * 1024;

/// The log configuration.
#[derive(Debug, Args)]
#[command(next_help_heading = "Logging")]
pub struct LogArgs {
/// The format to use for logs written to std.
#[arg(long = "log.std.format", value_name = "FORMAT", global = true, default_value_t = LogFormat::Terminal)]
pub log_std_format: LogFormat,
loocapro marked this conversation as resolved.
Show resolved Hide resolved

/// The format to use for logs written to the log file.
#[arg(long = "log.file.format", value_name = "FORMAT", global = true, default_value_t = LogFormat::Terminal)]
pub log_file_format: LogFormat,

/// The path to put log files in.
#[arg(long = "log.file.directory", value_name = "PATH", global = true, default_value_t)]
pub log_file_directory: PlatformPath<LogsDir>,
Expand Down Expand Up @@ -60,55 +62,50 @@ pub struct LogArgs {
default_value_t = ColorMode::Always
)]
pub color: ColorMode,
/// The verbosity settings for the tracer.
#[clap(flatten)]
pub verbosity: Verbosity,
}

impl LogArgs {
/// Builds tracing layers from the current log options.
pub fn layers<S>(&self) -> eyre::Result<(Vec<BoxedLayer<S>>, Option<FileWorkerGuard>)>
where
S: Subscriber,
for<'a> S: LookupSpan<'a>,
{
let mut layers = Vec::new();

// Function to create a new EnvFilter with environment (from `RUST_LOG` env var), default
// (from `DEFAULT_DIRECTIVES`) and additional directives.
let create_env_filter = |additional_directives: &str| -> eyre::Result<EnvFilter> {
let env_filter = EnvFilter::builder().from_env_lossy();

DEFAULT_ENV_FILTER_DIRECTIVES
.into_iter()
.chain(additional_directives.split(','))
.try_fold(env_filter, |env_filter, directive| {
Ok(env_filter.add_directive(directive.parse()?))
})
};

// Create and add the journald layer if enabled
/// Creates a LayerInfo instance.
loocapro marked this conversation as resolved.
Show resolved Hide resolved
fn layer(&self, format: LogFormat, use_color: bool) -> LayerInfo {
LayerInfo::new(
format,
self.log_file_filter.clone(),
loocapro marked this conversation as resolved.
Show resolved Hide resolved
self.verbosity.directive(),
if use_color { Some(self.color.to_string()) } else { None },
)
}

/// File info from the current log options.
fn file_info(&self) -> FileInfo {
FileInfo::new(
self.log_file_directory.clone().into(),
self.log_file_max_size * MB_TO_BYTES,
self.log_file_max_files,
)
}

/// Initializes tracing with the configured options from cli args.
pub fn init_tracing(&self) -> eyre::Result<Option<FileWorkerGuard>> {
let mut tracer = RethTracer::new();

let stdout = self.layer(self.log_std_format, true);
tracer = tracer.with_stdout(stdout);

if self.journald {
let journald_filter = create_env_filter(&self.journald_filter)?;
layers.push(
reth_tracing::journald(journald_filter).expect("Could not connect to journald"),
);
tracer = tracer.with_journald(self.journald_filter.clone());
}

// Create and add the file logging layer if enabled
let file_guard = if self.log_file_max_files > 0 {
let file_filter = create_env_filter(&self.log_file_filter)?;
let (layer, guard) = reth_tracing::file(
file_filter,
&self.log_file_directory,
"reth.log",
self.log_file_max_size * MB_TO_BYTES,
self.log_file_max_files,
);
layers.push(layer);
Some(guard)
} else {
None
};
if self.log_file_max_files > 0 {
let info = self.file_info();
let file = self.layer(self.log_file_format, false);
tracer = tracer.with_file(file, info);
}

Ok((layers, file_guard))
let guard = tracer.init()?;
Ok(guard)
}
}

Expand All @@ -132,3 +129,42 @@ impl Display for ColorMode {
}
}
}

/// The verbosity settings for the cli.
#[derive(Debug, Copy, Clone, Args)]
#[command(next_help_heading = "Display")]
pub struct Verbosity {
/// Set the minimum log level.
///
/// -v Errors
/// -vv Warnings
/// -vvv Info
/// -vvvv Debug
/// -vvvvv Traces (warning: very verbose!)
#[clap(short, long, action = ArgAction::Count, global = true, default_value_t = 3, verbatim_doc_comment, help_heading = "Display")]
verbosity: u8,

/// Silence all log output.
#[clap(long, alias = "silent", short = 'q', global = true, help_heading = "Display")]
quiet: bool,
}

impl Verbosity {
/// Get the corresponding [Directive] for the given verbosity, or none if the verbosity
/// corresponds to silent.
pub fn directive(&self) -> Directive {
if self.quiet {
LevelFilter::OFF.into()
} else {
let level = match self.verbosity - 1 {
0 => Level::ERROR,
1 => Level::WARN,
2 => Level::INFO,
3 => Level::DEBUG,
_ => Level::TRACE,
};

format!("{level}").parse().unwrap()
loocapro marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
58 changes: 3 additions & 55 deletions bin/reth/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,9 @@ use crate::{
runner::CliRunner,
version::{LONG_VERSION, SHORT_VERSION},
};
use clap::{value_parser, ArgAction, Args, Parser, Subcommand};
use clap::{value_parser, Parser, Subcommand};
use reth_primitives::ChainSpec;
use reth_tracing::{
tracing::{metadata::LevelFilter, Level},
tracing_subscriber::filter::Directive,
FileWorkerGuard,
};
use reth_tracing::FileWorkerGuard;
use std::sync::Arc;

pub mod components;
Expand Down Expand Up @@ -67,9 +63,6 @@ pub struct Cli<Ext: RethCliExt = ()> {

#[clap(flatten)]
logs: LogArgs,

#[clap(flatten)]
verbosity: Verbosity,
}

impl<Ext: RethCliExt> Cli<Ext> {
Expand Down Expand Up @@ -101,13 +94,7 @@ impl<Ext: RethCliExt> Cli<Ext> {
/// If file logging is enabled, this function returns a guard that must be kept alive to ensure
/// that all logs are flushed to disk.
pub fn init_tracing(&self) -> eyre::Result<Option<FileWorkerGuard>> {
let mut layers =
vec![reth_tracing::stdout(self.verbosity.directive(), &self.logs.color.to_string())];

let (additional_layers, guard) = self.logs.layers()?;
layers.extend(additional_layers);

reth_tracing::init(layers);
let guard = self.logs.init_tracing()?;
Ok(guard)
}

Expand Down Expand Up @@ -173,45 +160,6 @@ impl<Ext: RethCliExt> Commands<Ext> {
}
}

/// The verbosity settings for the cli.
#[derive(Debug, Copy, Clone, Args)]
#[command(next_help_heading = "Display")]
pub struct Verbosity {
/// Set the minimum log level.
///
/// -v Errors
/// -vv Warnings
/// -vvv Info
/// -vvvv Debug
/// -vvvvv Traces (warning: very verbose!)
#[clap(short, long, action = ArgAction::Count, global = true, default_value_t = 3, verbatim_doc_comment, help_heading = "Display")]
verbosity: u8,

/// Silence all log output.
#[clap(long, alias = "silent", short = 'q', global = true, help_heading = "Display")]
quiet: bool,
}

impl Verbosity {
/// Get the corresponding [Directive] for the given verbosity, or none if the verbosity
/// corresponds to silent.
pub fn directive(&self) -> Directive {
if self.quiet {
LevelFilter::OFF.into()
} else {
let level = match self.verbosity - 1 {
0 => Level::ERROR,
1 => Level::WARN,
2 => Level::INFO,
3 => Level::DEBUG,
_ => Level::TRACE,
};

format!("{level}").parse().unwrap()
}
}
}

#[cfg(test)]
mod tests {
use clap::CommandFactory;
Expand Down
5 changes: 4 additions & 1 deletion crates/tracing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ description = "tracing helpers"

[dependencies]
tracing.workspace = true
tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] }
tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt", "json"] }
tracing-appender.workspace = true
tracing-journald = "0.3"
tracing-logfmt = "0.3.3"
rolling-file = "0.2.0"
eyre.workspace = true
clap = { workspace = true, features = ["derive"] }
Loading
Loading