diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 1f0be6d943..ce38c8ab02 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -19,7 +19,6 @@ tracing-tower = { version = "0.1.0", path = "../tracing-tower" } tracing-subscriber = { path = "../tracing-subscriber", version = "0.3.0", features = ["json", "env-filter"] } tracing-futures = { version = "0.2.1", path = "../tracing-futures", features = ["futures-01"] } tracing-attributes = { path = "../tracing-attributes", version = "0.1.22" } -tracing-log = { path = "../tracing-log", version = "0.1.3", features = ["env_logger"] } tracing-serde = { path = "../tracing-serde" } tracing-appender = { path = "../tracing-appender", version = "0.2.0" } tracing-journald = { path = "../tracing-journald" } diff --git a/tracing-log/Cargo.toml b/tracing-log/Cargo.toml index 306eb08811..efed1028df 100644 --- a/tracing-log/Cargo.toml +++ b/tracing-log/Cargo.toml @@ -18,17 +18,15 @@ readme = "README.md" rust-version = "1.56.0" [features] -default = ["log-tracer", "trace-logger", "std"] +default = ["log-tracer", "std"] std = ["log/std"] log-tracer = [] -trace-logger = [] interest-cache = ["lru", "ahash"] [dependencies] tracing-core = { path = "../tracing-core", version = "0.1.28"} log = { version = "0.4.17" } once_cell = "1.13.0" -env_logger = { version = "0.8.4", optional = true } lru = { version = "0.7.7", optional = true } ahash = { version = "0.7.6", optional = true } diff --git a/tracing-log/README.md b/tracing-log/README.md index 3da5f6b7e1..267ce7b7f0 100644 --- a/tracing-log/README.md +++ b/tracing-log/README.md @@ -43,8 +43,6 @@ This crate provides: - [`AsTrace`] and [`AsLog`] traits for converting between `tracing` and `log` types. - [`LogTracer`], a [`log::Log`] implementation that consumes [`log::Record`]s and outputs them as [`tracing::Event`]s. -- An [`env_logger`] module, with helpers for using the [`env_logger` crate] - with `tracing` (optional, enabled by the `env_logger` feature). [`tracing`]: https://crates.io/crates/tracing [`log`]: https://crates.io/crates/log diff --git a/tracing-log/src/env_logger.rs b/tracing-log/src/env_logger.rs deleted file mode 100644 index 74922d1dc6..0000000000 --- a/tracing-log/src/env_logger.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! Utilities for configuring the `env_logger` crate to emit `tracing` events. - -/// Extension trait to configure an `env_logger::Builder` to emit traces. -pub trait BuilderExt: crate::sealed::Sealed { - /// Configure the built `env_logger::Logger` to emit `tracing` events for - /// all consumed `log` records, rather than printing them to standard out. - /// - /// Note that this replaces any previously configured formatting. - fn emit_traces(&mut self) -> &mut Self; -} - -impl crate::sealed::Sealed for env_logger::Builder {} - -impl BuilderExt for env_logger::Builder { - fn emit_traces(&mut self) -> &mut Self { - self.format(|_, record| super::format_trace(record)) - } -} - -/// Attempts to initialize the global logger with an env logger configured to -/// emit `tracing` events. -/// -/// This should be called early in the execution of a Rust program. Any log -/// events that occur before initialization will be ignored. -/// -/// # Errors -/// -/// This function will fail if it is called more than once, or if another -/// library has already initialized a global logger. -pub fn try_init() -> Result<(), log::SetLoggerError> { - env_logger::Builder::from_default_env() - .emit_traces() - .try_init() -} - -/// Initializes the global logger with an env logger configured to -/// emit `tracing` events. -/// -/// This should be called early in the execution of a Rust program. Any log -/// events that occur before initialization will be ignored. -/// -/// # Panics -/// -/// This function will panic if it is called more than once, or if another -/// library has already initialized a global logger. -pub fn init() { - try_init() - .expect("tracing_log::env_logger::init should not be called after logger initialized"); -} diff --git a/tracing-log/src/lib.rs b/tracing-log/src/lib.rs index 218c968354..bb162d9e14 100644 --- a/tracing-log/src/lib.rs +++ b/tracing-log/src/lib.rs @@ -13,8 +13,6 @@ //! - [`AsTrace`] and [`AsLog`] traits for converting between `tracing` and `log` types. //! - [`LogTracer`], a [`log::Log`] implementation that consumes [`log::Record`]s //! and outputs them as [`tracing::Event`]. -//! - An [`env_logger`] module, with helpers for using the [`env_logger` crate] -//! with `tracing` (optional, enabled by the `env-logger` feature). //! //! *Compiler support: [requires `rustc` 1.56+][msrv]* //! @@ -57,23 +55,20 @@ //! //! ## Caution: Mixing both conversions //! -//! Note that logger implementations that convert log records to trace events +//! Note that `log::Logger` implementations that convert log records to trace events //! should not be used with `Subscriber`s that convert trace events _back_ into -//! log records (such as the `TraceLogger`), as doing so will result in the -//! event recursing between the subscriber and the logger forever (or, in real -//! life, probably overflowing the call stack). +//! `log` records, as doing so will result in the event recursing between the subscriber +//! and the logger forever (or, in real life, probably overflowing the call stack). //! //! If the logging of trace events generated from log records produced by the //! `log` crate is desired, either the `log` crate should not be used to //! implement this logging, or an additional layer of filtering will be //! required to avoid infinitely converting between `Event` and `log::Record`. //! -//! # Feature Flags -//! * `trace-logger`: enables an experimental `log` subscriber, deprecated since -//! version 0.1.1. +//! ## Feature Flags +//! +//! * `std`: enables features that require the Rust standard library (on by default) //! * `log-tracer`: enables the `LogTracer` type (on by default) -//! * `env_logger`: enables the `env_logger` module, with helpers for working -//! with the [`env_logger` crate]. //! * `interest-cache`: makes it possible to configure an interest cache for //! logs emitted through the `log` crate (see [`Builder::with_interest_cache`]); requires `std` //! @@ -94,7 +89,6 @@ //! [`init`]: LogTracer::init //! [`init_with_filter`]: LogTracer::init_with_filter //! [`tracing`]: https://crates.io/crates/tracing -//! [`env_logger` crate]: https://crates.io/crates/env-logger //! [`tracing::Subscriber`]: https://docs.rs/tracing/latest/tracing/trait.Subscriber.html //! [`Subscriber`]: https://docs.rs/tracing/latest/tracing/trait.Subscriber.html //! [`tracing::Event`]: https://docs.rs/tracing/latest/tracing/struct.Event.html @@ -143,33 +137,11 @@ use tracing_core::{ #[cfg_attr(docsrs, doc(cfg(feature = "log-tracer")))] pub mod log_tracer; -#[cfg(feature = "trace-logger")] -#[cfg_attr(docsrs, doc(cfg(feature = "trace-logger")))] -pub mod trace_logger; - #[cfg(feature = "log-tracer")] #[cfg_attr(docsrs, doc(cfg(feature = "log-tracer")))] #[doc(inline)] pub use self::log_tracer::LogTracer; -#[cfg(feature = "trace-logger")] -#[cfg_attr(docsrs, doc(cfg(feature = "trace-logger")))] -#[deprecated( - since = "0.1.1", - note = "use the `tracing` crate's \"log\" feature flag instead" -)] -#[allow(deprecated)] -#[doc(inline)] -pub use self::trace_logger::TraceLogger; - -#[cfg(feature = "env_logger")] -#[cfg_attr(docsrs, doc(cfg(feature = "env_logger")))] -#[deprecated( - since = "0.1.4", - note = "use `tracing-subscriber`'s `fmt::Subscriber` instead" -)] -pub mod env_logger; - pub use log; #[cfg(all(feature = "interest-cache", feature = "log-tracer", feature = "std"))] diff --git a/tracing-log/src/trace_logger.rs b/tracing-log/src/trace_logger.rs deleted file mode 100644 index 88a52f7524..0000000000 --- a/tracing-log/src/trace_logger.rs +++ /dev/null @@ -1,458 +0,0 @@ -//! A `tracing` [`Subscriber`] that uses the [`log`] crate as a backend for -//! formatting `tracing` spans and events. -//! -//! When a [`TraceLogger`] is set as the current subscriber, it will record -//! traces by emitting [`log::Record`]s that can be collected by a logger. -//! -//! **Note**: This API has been deprecated since version 0.1.1. In order to emit -//! `tracing` events as `log` records, the ["log" and "log-always" feature -//! flags][flags] on the `tracing` crate should be used instead. -//! -//! [`log`]: log -//! [`Subscriber`]: https://docs.rs/tracing/0.1.7/tracing/subscriber/trait.Subscriber.html -//! [`log::Record`]:log::Record -//! [flags]: https://docs.rs/tracing/latest/tracing/#crate-feature-flags -#![deprecated( - since = "0.1.1", - note = "use the `tracing` crate's \"log\" feature flag instead" -)] -use crate::AsLog; -use std::{ - cell::RefCell, - collections::HashMap, - fmt::{self, Write}, - sync::{ - atomic::{AtomicUsize, Ordering}, - Mutex, - }, -}; -use tracing_core::{ - field, - span::{self, Id}, - Event, Metadata, Subscriber, -}; - -/// A `tracing` [`Subscriber`] implementation that logs all recorded -/// trace events. -/// -/// **Note**: This API has been deprecated since version 0.1.1. In order to emit -/// `tracing` events as `log` records, the ["log" and "log-always" feature -/// flags][flags] on the `tracing` crate should be used instead. -/// -/// [`Subscriber`]: https://docs.rs/tracing/0.1.7/tracing/subscriber/trait.Subscriber.html -/// [flags]: https://docs.rs/tracing/latest/tracing/#crate-feature-flags -pub struct TraceLogger { - settings: Builder, - spans: Mutex>, - next_id: AtomicUsize, -} - -thread_local! { - static CURRENT: RefCell> = RefCell::new(Vec::new()); -} -/// Configures and constructs a [`TraceLogger`]. -/// -#[derive(Debug)] -pub struct Builder { - log_span_closes: bool, - log_enters: bool, - log_exits: bool, - log_ids: bool, - parent_fields: bool, - log_parent: bool, -} - -// ===== impl TraceLogger ===== - -impl TraceLogger { - /// Returns a new `TraceLogger` with the default configuration. - pub fn new() -> Self { - Self::builder().finish() - } - - /// Returns a `Builder` for configuring a `TraceLogger`. - pub fn builder() -> Builder { - Default::default() - } - - fn from_builder(settings: Builder) -> Self { - Self { - settings, - ..Default::default() - } - } - - fn next_id(&self) -> Id { - Id::from_u64(self.next_id.fetch_add(1, Ordering::SeqCst) as u64) - } -} - -// ===== impl Builder ===== - -impl Builder { - /// Configures whether or not the [`TraceLogger`] being constructed will log - /// when a span closes. - /// - pub fn with_span_closes(self, log_span_closes: bool) -> Self { - Self { - log_span_closes, - ..self - } - } - - /// Configures whether or not the [`TraceLogger`] being constructed will - /// include the fields of parent spans when formatting events. - /// - pub fn with_parent_fields(self, parent_fields: bool) -> Self { - Self { - parent_fields, - ..self - } - } - - /// Configures whether or not the [`TraceLogger`] being constructed will log - /// when a span is entered. - /// - /// If this is set to false, fields from the current span will still be - /// recorded as context, but the actual entry will not create a log record. - /// - pub fn with_span_entry(self, log_enters: bool) -> Self { - Self { log_enters, ..self } - } - - /// Configures whether or not the [`TraceLogger`] being constructed will log - /// when a span is exited. - /// - pub fn with_span_exits(self, log_exits: bool) -> Self { - Self { log_exits, ..self } - } - - /// Configures whether or not the [`TraceLogger`] being constructed will - /// include span IDs when formatting log output. - /// - pub fn with_ids(self, log_ids: bool) -> Self { - Self { log_ids, ..self } - } - - /// Configures whether or not the [`TraceLogger`] being constructed will - /// include the names of parent spans as context when formatting events. - /// - pub fn with_parent_names(self, log_parent: bool) -> Self { - Self { log_parent, ..self } - } - - /// Complete the builder, returning a configured [`TraceLogger`]. - /// - pub fn finish(self) -> TraceLogger { - TraceLogger::from_builder(self) - } -} - -impl Default for Builder { - fn default() -> Self { - Builder { - log_span_closes: false, - parent_fields: true, - log_exits: false, - log_ids: false, - log_parent: true, - log_enters: false, - } - } -} - -impl Default for TraceLogger { - fn default() -> Self { - TraceLogger { - settings: Default::default(), - spans: Default::default(), - next_id: AtomicUsize::new(1), - } - } -} - -#[derive(Debug)] -struct SpanLineBuilder { - parent: Option, - ref_count: usize, - fields: String, - file: Option, - line: Option, - module_path: Option, - target: String, - level: log::Level, - name: &'static str, -} - -impl SpanLineBuilder { - fn new(parent: Option, meta: &Metadata<'_>, fields: String) -> Self { - Self { - parent, - ref_count: 1, - fields, - file: meta.file().map(String::from), - line: meta.line(), - module_path: meta.module_path().map(String::from), - target: String::from(meta.target()), - level: meta.level().as_log(), - name: meta.name(), - } - } - - fn log_meta(&self) -> log::Metadata<'_> { - log::MetadataBuilder::new() - .level(self.level) - .target(self.target.as_ref()) - .build() - } - - fn finish(self) { - let log_meta = self.log_meta(); - let logger = log::logger(); - if logger.enabled(&log_meta) { - logger.log( - &log::Record::builder() - .metadata(log_meta) - .target(self.target.as_ref()) - .module_path(self.module_path.as_ref().map(String::as_ref)) - .file(self.file.as_ref().map(String::as_ref)) - .line(self.line) - .args(format_args!("close {}; {}", self.name, self.fields)) - .build(), - ); - } - } -} - -impl field::Visit for SpanLineBuilder { - fn record_debug(&mut self, field: &field::Field, value: &dyn fmt::Debug) { - write!(self.fields, " {}={:?};", field.name(), value) - .expect("write to string should never fail") - } -} - -impl Subscriber for TraceLogger { - fn enabled(&self, metadata: &Metadata<'_>) -> bool { - log::logger().enabled(&metadata.as_log()) - } - - fn new_span(&self, attrs: &span::Attributes<'_>) -> Id { - let id = self.next_id(); - let mut spans = self.spans.lock().unwrap(); - let mut fields = String::new(); - let parent = self.current_id(); - if self.settings.parent_fields { - let mut next_parent = parent.as_ref(); - while let Some(parent) = next_parent.and_then(|p| spans.get(p)) { - write!(&mut fields, "{}", parent.fields).expect("write to string cannot fail"); - next_parent = parent.parent.as_ref(); - } - } - let mut span = SpanLineBuilder::new(parent, attrs.metadata(), fields); - attrs.record(&mut span); - spans.insert(id.clone(), span); - id - } - - fn record(&self, span: &Id, values: &span::Record<'_>) { - let mut spans = self.spans.lock().unwrap(); - if let Some(span) = spans.get_mut(span) { - values.record(span); - } - } - - fn record_follows_from(&self, span: &Id, follows: &Id) { - // TODO: this should eventually track the relationship? - log::logger().log( - &log::Record::builder() - .level(log::Level::Trace) - .args(format_args!("span {:?} follows_from={:?};", span, follows)) - .build(), - ); - } - - fn enter(&self, id: &Id) { - let _ = CURRENT.try_with(|current| { - let mut current = current.borrow_mut(); - if current.contains(id) { - // Ignore duplicate enters. - return; - } - current.push(id.clone()); - }); - let spans = self.spans.lock().unwrap(); - if self.settings.log_enters { - if let Some(span) = spans.get(id) { - let log_meta = span.log_meta(); - let logger = log::logger(); - if logger.enabled(&log_meta) { - let current_id = self.current_id(); - let current_fields = current_id - .as_ref() - .and_then(|id| spans.get(id)) - .map(|span| span.fields.as_ref()) - .unwrap_or(""); - if self.settings.log_ids { - logger.log( - &log::Record::builder() - .metadata(log_meta) - .target(span.target.as_ref()) - .module_path(span.module_path.as_ref().map(String::as_ref)) - .file(span.file.as_ref().map(String::as_ref)) - .line(span.line) - .args(format_args!( - "enter {}; in={:?}; {}", - span.name, current_id, current_fields - )) - .build(), - ); - } else { - logger.log( - &log::Record::builder() - .metadata(log_meta) - .target(span.target.as_ref()) - .module_path(span.module_path.as_ref().map(String::as_ref)) - .file(span.file.as_ref().map(String::as_ref)) - .line(span.line) - .args(format_args!("enter {}; {}", span.name, current_fields)) - .build(), - ); - } - } - } - } - } - - fn exit(&self, id: &Id) { - let _ = CURRENT.try_with(|current| { - let mut current = current.borrow_mut(); - if current.last() == Some(id) { - current.pop() - } else { - None - } - }); - if self.settings.log_exits { - let spans = self.spans.lock().unwrap(); - if let Some(span) = spans.get(id) { - let log_meta = span.log_meta(); - let logger = log::logger(); - if logger.enabled(&log_meta) { - logger.log( - &log::Record::builder() - .metadata(log_meta) - .target(span.target.as_ref()) - .module_path(span.module_path.as_ref().map(String::as_ref)) - .file(span.file.as_ref().map(String::as_ref)) - .line(span.line) - .args(format_args!("exit {}", span.name)) - .build(), - ); - } - } - } - } - - fn event(&self, event: &Event<'_>) { - let meta = event.metadata(); - let log_meta = meta.as_log(); - let logger = log::logger(); - if logger.enabled(&log_meta) { - let spans = self.spans.lock().unwrap(); - let current = self.current_id().and_then(|id| spans.get(&id)); - let (current_fields, parent) = current - .map(|span| { - let fields = span.fields.as_ref(); - let parent = if self.settings.log_parent { - Some(span.name) - } else { - None - }; - (fields, parent) - }) - .unwrap_or(("", None)); - logger.log( - &log::Record::builder() - .metadata(log_meta) - .target(meta.target()) - .module_path(meta.module_path().as_ref().cloned()) - .file(meta.file().as_ref().cloned()) - .line(meta.line()) - .args(format_args!( - "{}{}{}{}", - parent.unwrap_or(""), - if parent.is_some() { ": " } else { "" }, - LogEvent(event), - current_fields, - )) - .build(), - ); - } - } - - fn clone_span(&self, id: &Id) -> Id { - let mut spans = self.spans.lock().unwrap(); - if let Some(span) = spans.get_mut(id) { - span.ref_count += 1; - } - id.clone() - } - - fn try_close(&self, id: Id) -> bool { - let mut spans = self.spans.lock().unwrap(); - if spans.contains_key(&id) { - if spans.get(&id).unwrap().ref_count == 1 { - let span = spans.remove(&id).unwrap(); - if self.settings.log_span_closes { - span.finish(); - } - return true; - } else { - spans.get_mut(&id).unwrap().ref_count -= 1; - } - } - false - } -} - -impl TraceLogger { - #[inline] - fn current_id(&self) -> Option { - CURRENT - .try_with(|current| current.borrow().last().map(|span| self.clone_span(span))) - .ok()? - } -} - -struct LogEvent<'a>(&'a Event<'a>); - -impl<'a> fmt::Display for LogEvent<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut has_logged = false; - let mut format_fields = |field: &field::Field, value: &dyn fmt::Debug| { - let name = field.name(); - let leading = if has_logged { " " } else { "" }; - // TODO: handle fmt error? - let _ = if name == "message" { - write!(f, "{}{:?};", leading, value) - } else { - write!(f, "{}{}={:?};", leading, name, value) - }; - has_logged = true; - }; - - self.0.record(&mut format_fields); - Ok(()) - } -} - -impl fmt::Debug for TraceLogger { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("TraceLogger") - .field("settings", &self.settings) - .field("spans", &self.spans) - .field("current", &self.current_id()) - .field("next_id", &self.next_id) - .finish() - } -} diff --git a/tracing-macros/Cargo.toml b/tracing-macros/Cargo.toml index 9f578ef5a0..59424170de 100644 --- a/tracing-macros/Cargo.toml +++ b/tracing-macros/Cargo.toml @@ -18,11 +18,10 @@ license = "MIT" rust-version = "1.56.0" [dependencies] -tracing = "0.1.35" +tracing = { path = "../tracing", version = "0.1.35" } [dev-dependencies] -tracing-log = "0.1.3" -env_logger = "0.7.1" +tracing-subscriber = { path = "../tracing-subscriber", version = "0.3.0", features = ["env-filter"] } [badges] maintenance = { status = "experimental" } diff --git a/tracing-macros/examples/factorial.rs b/tracing-macros/examples/factorial.rs index c5257f08f8..4f2c095da0 100644 --- a/tracing-macros/examples/factorial.rs +++ b/tracing-macros/examples/factorial.rs @@ -2,6 +2,7 @@ #![deny(rust_2018_idioms)] use tracing_macros::dbg; +use tracing_subscriber::{fmt, layer::SubscriberExt, EnvFilter}; fn factorial(n: u32) -> u32 { if dbg!(n <= 1) { @@ -12,9 +13,10 @@ fn factorial(n: u32) -> u32 { } fn main() { - env_logger::Builder::new().parse_filters("trace").init(); - #[allow(deprecated)] - let subscriber = tracing_log::TraceLogger::new(); + let subscriber = tracing_subscriber::registry() + .with(EnvFilter::from_default_env().add_directive(tracing::Level::TRACE.into())) + .with(fmt::Layer::new()); - tracing::subscriber::with_default(subscriber, || dbg!(factorial(4))); + tracing::subscriber::set_global_default(subscriber).expect("Unable to set a global subscriber"); + dbg!(factorial(4)); }