#![cfg_attr(docsrs, feature(doc_cfg))] #![doc( html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", issue_tracker_base_url = "https://github.com/paradigmxzy/reth/issues/" )] #![warn(missing_docs, unreachable_pub)] #![deny(unused_must_use, rust_2018_idioms)] #![doc(test( no_crate_inject, attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) ))] //! reth tracing subscribers and utilities. //! //! Contains a standardized set of layers: //! //! - [`stdout()`] //! - [`file()`] //! - [`journald()`] //! //! As well as a simple way to initialize a subscriber: [`init`]. use std::path::Path; use tracing::Subscriber; use tracing_subscriber::{ filter::Directive, prelude::*, registry::LookupSpan, EnvFilter, Layer, Registry, }; // Re-export tracing crates pub use tracing; pub use tracing_subscriber; /// A boxed tracing [Layer]. pub type BoxedLayer = Box + Send + Sync>; /// Initializes a new [Subscriber] based on the given layers. pub fn init(layers: Vec>) { tracing_subscriber::registry().with(layers).init(); } /// Builds a new tracing layer that writes to stdout. /// /// The events are filtered by `default_directive`, unless overridden by `RUST_LOG`. /// /// Colors can be disabled with `RUST_LOG_STYLE=never`, and event targets can be displayed with /// `RUST_LOG_TARGET=1`. pub fn stdout(default_directive: impl Into) -> BoxedLayer where S: Subscriber, for<'a> S: LookupSpan<'a>, { // TODO: Auto-detect let with_ansi = std::env::var("RUST_LOG_STYLE").map(|val| val != "never").unwrap_or(true); let with_target = std::env::var("RUST_LOG_TARGET").map(|val| val != "0").unwrap_or(true); let filter = EnvFilter::builder().with_default_directive(default_directive.into()).from_env_lossy(); tracing_subscriber::fmt::layer() .with_ansi(with_ansi) .with_target(with_target) .with_filter(filter) .boxed() } /// Builds a new tracing layer that appends to a log file. /// /// The events are filtered by `filter`. /// /// The boxed layer and a guard is returned. When the guard is dropped the buffer for the log /// file is immediately flushed to disk. Any events after the guard is dropped may be missed. #[must_use = "tracing guard must be kept alive to flush events to disk"] pub fn file( filter: EnvFilter, dir: impl AsRef, file_name: impl AsRef, ) -> (BoxedLayer, tracing_appender::non_blocking::WorkerGuard) where S: Subscriber, for<'a> S: LookupSpan<'a>, { let (writer, guard) = tracing_appender::non_blocking(tracing_appender::rolling::never(dir, file_name)); let layer = tracing_subscriber::fmt::layer() .with_ansi(false) .with_writer(writer) .with_filter(filter) .boxed(); (layer, guard) } /// A worker guard returned by [`file()`]. /// /// When a guard is dropped, all events currently in-memory are flushed to the log file this guard /// belongs to. pub type FileWorkerGuard = tracing_appender::non_blocking::WorkerGuard; /// Builds a new tracing layer that writes events to journald. /// /// The events are filtered by `filter`. /// /// If the layer cannot connect to journald for any reason this function will return an error. pub fn journald(filter: EnvFilter) -> std::io::Result> where S: Subscriber, for<'a> S: LookupSpan<'a>, { Ok(tracing_journald::layer()?.with_filter(filter).boxed()) } /// Initializes a tracing subscriber for tests. /// /// The filter is configurable via `RUST_LOG`. /// /// # Note /// /// The subscriber will silently fail if it could not be installed. pub fn init_test_tracing() { let _ = tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env()) .with_writer(std::io::stderr) .try_init(); }