From bd014f089157ab4b65b2489930fa6ae05da54076 Mon Sep 17 00:00:00 2001 From: James Liu Date: Mon, 6 Jun 2022 10:32:41 -0700 Subject: [PATCH] core, subscriber: migrate from `lazy_static` to `once_cell` (#2147) Replace `lazy_static` with `once_cell`. Fixes #2146. ## Motivation `lazy_static!`, while a declarative macro, is a macro nonetheless. It can add quite a bit of additional compilation time cost. `once_cell::sync::Lazy` does the same thing with generics, and can be used more flexibly (i.e. non-static lazily initialized values), and has been proposed to be added to `std` (see linked issue). I'm trying to reduce the compile time and dependency tree complexity of a dependent project: [bevy](https://bevyengine.org), which is using tracing. `lazy_static` and `once_cell` are both in our dependency tree and both end up doing the same thing. ## Solution Migrate to `once_cell`. --- examples/Cargo.toml | 2 +- examples/examples/hyper-echo.rs | 8 --- tracing-core/Cargo.toml | 4 +- tracing-core/src/callsite.rs | 11 ++- tracing-core/src/lib.rs | 4 -- tracing-flame/Cargo.toml | 3 +- tracing-flame/src/lib.rs | 6 +- tracing-log/Cargo.toml | 4 +- tracing-log/src/interest_cache.rs | 16 ++--- tracing-log/src/lib.rs | 14 ++-- tracing-subscriber/Cargo.toml | 6 +- .../src/filter/env/directive.rs | 70 +++++++++---------- 12 files changed, 66 insertions(+), 82 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 14d2ee34de..1f829940a0 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -32,7 +32,7 @@ futures = "0.3" tokio = { version = "1.1", features = ["full"] } # env-logger example -env_logger = "0.7" +env_logger = "0.9" # tower examples tower = { version = "0.4.4", features = ["full"] } diff --git a/examples/examples/hyper-echo.rs b/examples/examples/hyper-echo.rs index 3404a8d5e9..f0396d19cf 100644 --- a/examples/examples/hyper-echo.rs +++ b/examples/examples/hyper-echo.rs @@ -92,17 +92,9 @@ async fn echo(req: Request) -> Result, hyper::Error> { #[tokio::main] async fn main() -> Result<(), Box> { - use tracing_log::env_logger::BuilderExt; - let subscriber = tracing_subscriber::fmt() .with_max_level(Level::TRACE) .finish(); - let mut builder = env_logger::Builder::new(); - builder - .filter(Some("hyper_echo"), log::LevelFilter::Off) - .filter(Some("hyper"), log::LevelFilter::Trace) - .emit_traces() // from `tracing_log::env_logger::BuilderExt` - .try_init()?; tracing::subscriber::set_global_default(subscriber)?; let local_addr: std::net::SocketAddr = ([127, 0, 0, 1], 3000).into(); diff --git a/tracing-core/Cargo.toml b/tracing-core/Cargo.toml index 77075846e7..cedffe7bfc 100644 --- a/tracing-core/Cargo.toml +++ b/tracing-core/Cargo.toml @@ -28,13 +28,13 @@ rust-version = "1.49.0" [features] default = ["std", "valuable/std"] -std = ["lazy_static"] +std = ["once_cell"] [badges] maintenance = { status = "actively-developed" } [dependencies] -lazy_static = { version = "1.0.2", optional = true } +once_cell = { version = "1.12", optional = true } [target.'cfg(tracing_unstable)'.dependencies] valuable = { version = "0.1.0", optional = true, default_features = false } diff --git a/tracing-core/src/callsite.rs b/tracing-core/src/callsite.rs index 573125a89a..87d084647b 100644 --- a/tracing-core/src/callsite.rs +++ b/tracing-core/src/callsite.rs @@ -253,6 +253,11 @@ static CALLSITES: Callsites = Callsites { static DISPATCHERS: Dispatchers = Dispatchers::new(); +#[cfg(feature = "std")] +static LOCKED_CALLSITES: once_cell::sync::Lazy>> = + once_cell::sync::Lazy::new(Default::default); + +#[cfg(not(feature = "std"))] crate::lazy_static! { static ref LOCKED_CALLSITES: Mutex> = Mutex::new(Vec::new()); } @@ -510,6 +515,7 @@ mod private { #[cfg(feature = "std")] mod dispatchers { use crate::dispatcher; + use once_cell::sync::Lazy; use std::sync::{ atomic::{AtomicBool, Ordering}, RwLock, RwLockReadGuard, RwLockWriteGuard, @@ -519,9 +525,8 @@ mod dispatchers { has_just_one: AtomicBool, } - crate::lazy_static! { - static ref LOCKED_DISPATCHERS: RwLock> = RwLock::new(Vec::new()); - } + static LOCKED_DISPATCHERS: Lazy>> = + Lazy::new(Default::default); pub(super) enum Rebuilder<'a> { JustOne, diff --git a/tracing-core/src/lib.rs b/tracing-core/src/lib.rs index 7424a6cb3f..eceef7be22 100644 --- a/tracing-core/src/lib.rs +++ b/tracing-core/src/lib.rs @@ -254,10 +254,6 @@ macro_rules! metadata { }; } -// when `std` is enabled, use the `lazy_static` crate from crates.io -#[cfg(feature = "std")] -pub(crate) use lazy_static::lazy_static; - // Facade module: `no_std` uses spinlocks, `std` uses the mutexes in the standard library #[cfg(not(feature = "std"))] #[macro_use] diff --git a/tracing-flame/Cargo.toml b/tracing-flame/Cargo.toml index 5c6b9c0ba5..43ee62c922 100644 --- a/tracing-flame/Cargo.toml +++ b/tracing-flame/Cargo.toml @@ -28,7 +28,8 @@ smallvec = ["tracing-subscriber/smallvec"] [dependencies] tracing-subscriber = { path = "../tracing-subscriber", version = "0.3", default-features = false, features = ["registry", "fmt"] } tracing = { path = "../tracing", version = "0.1.12", default-features = false, features = ["std"] } -lazy_static = "1.3.0" +once_cell = "1.12" + [dev-dependencies] tempfile = "3" diff --git a/tracing-flame/src/lib.rs b/tracing-flame/src/lib.rs index b37bae74c1..f7d670aa61 100644 --- a/tracing-flame/src/lib.rs +++ b/tracing-flame/src/lib.rs @@ -137,7 +137,7 @@ pub use error::Error; use error::Kind; -use lazy_static::lazy_static; +use once_cell::sync::Lazy; use std::cell::Cell; use std::fmt; use std::fmt::Write as _; @@ -158,9 +158,7 @@ use tracing_subscriber::Layer; mod error; -lazy_static! { - static ref START: Instant = Instant::now(); -} +static START: Lazy = Lazy::new(Instant::now); thread_local! { static LAST_EVENT: Cell = Cell::new(*START); diff --git a/tracing-log/Cargo.toml b/tracing-log/Cargo.toml index b482341eab..a774357788 100644 --- a/tracing-log/Cargo.toml +++ b/tracing-log/Cargo.toml @@ -27,8 +27,8 @@ interest-cache = ["lru", "ahash"] [dependencies] tracing-core = { path = "../tracing-core", version = "0.1.17"} log = { version = "0.4" } -lazy_static = "1.3.0" -env_logger = { version = "0.7", optional = true } +once_cell = "1.12" +env_logger = { version = "0.8", optional = true } lru = { version = "0.7.0", optional = true } ahash = { version = "0.7.4", optional = true } diff --git a/tracing-log/src/interest_cache.rs b/tracing-log/src/interest_cache.rs index fb3da875eb..aabf9ebaf7 100644 --- a/tracing-log/src/interest_cache.rs +++ b/tracing-log/src/interest_cache.rs @@ -1,6 +1,7 @@ use ahash::AHasher; use log::{Level, Metadata}; use lru::LruCache; +use once_cell::sync::Lazy; use std::cell::RefCell; use std::hash::Hasher; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -140,12 +141,10 @@ static SENTINEL_METADATA: tracing_core::Metadata<'static> = tracing_core::Metada tracing_core::metadata::Kind::EVENT, ); -lazy_static::lazy_static! { - static ref CONFIG: Mutex = { - tracing_core::callsite::register(&SENTINEL_CALLSITE); - Mutex::new(InterestCacheConfig::disabled()) - }; -} +static CONFIG: Lazy> = Lazy::new(|| { + tracing_core::callsite::register(&SENTINEL_CALLSITE); + Mutex::new(InterestCacheConfig::disabled()) +}); thread_local! { static STATE: RefCell = { @@ -236,10 +235,7 @@ mod tests { fn lock_for_test() -> impl Drop { // We need to make sure only one test runs at a time. - - lazy_static::lazy_static! { - static ref LOCK: Mutex<()> = Mutex::new(()); - } + static LOCK: Lazy> = Lazy::new(Mutex::new); match LOCK.lock() { Ok(guard) => guard, diff --git a/tracing-log/src/lib.rs b/tracing-log/src/lib.rs index 09e9114a4c..44b3f1d32d 100644 --- a/tracing-log/src/lib.rs +++ b/tracing-log/src/lib.rs @@ -128,7 +128,7 @@ unused_parens, while_true )] -use lazy_static::lazy_static; +use once_cell::sync::Lazy; use std::{fmt, io}; @@ -346,13 +346,11 @@ log_cs!( ErrorCallsite ); -lazy_static! { - static ref TRACE_FIELDS: Fields = Fields::new(&TRACE_CS); - static ref DEBUG_FIELDS: Fields = Fields::new(&DEBUG_CS); - static ref INFO_FIELDS: Fields = Fields::new(&INFO_CS); - static ref WARN_FIELDS: Fields = Fields::new(&WARN_CS); - static ref ERROR_FIELDS: Fields = Fields::new(&ERROR_CS); -} +static TRACE_FIELDS: Lazy = Lazy::new(|| Fields::new(&TRACE_CS)); +static DEBUG_FIELDS: Lazy = Lazy::new(|| Fields::new(&DEBUG_CS)); +static INFO_FIELDS: Lazy = Lazy::new(|| Fields::new(&INFO_CS)); +static WARN_FIELDS: Lazy = Lazy::new(|| Fields::new(&WARN_CS)); +static ERROR_FIELDS: Lazy = Lazy::new(|| Fields::new(&ERROR_CS)); fn level_to_cs(level: Level) -> (&'static dyn Callsite, &'static Fields) { match level { diff --git a/tracing-subscriber/Cargo.toml b/tracing-subscriber/Cargo.toml index 8f36c8f7eb..3595318c46 100644 --- a/tracing-subscriber/Cargo.toml +++ b/tracing-subscriber/Cargo.toml @@ -27,7 +27,7 @@ rust-version = "1.49.0" default = ["smallvec", "fmt", "ansi", "tracing-log", "std"] alloc = [] std = ["alloc", "tracing-core/std"] -env-filter = ["matchers", "regex", "lazy_static", "tracing", "std", "thread_local"] +env-filter = ["matchers", "regex", "once_cell", "tracing", "std", "thread_local"] fmt = ["registry", "std"] ansi = ["fmt", "ansi_term"] registry = ["sharded-slab", "thread_local", "std"] @@ -45,7 +45,7 @@ tracing = { optional = true, path = "../tracing", version = "0.1", default-featu matchers = { optional = true, version = "0.1.0" } regex = { optional = true, version = "1", default-features = false, features = ["std"] } smallvec = { optional = true, version = "1.2.0" } -lazy_static = { optional = true, version = "1" } +once_cell = { optional = true, version = "1.12" } # fmt tracing-log = { path = "../tracing-log", version = "0.1.2", optional = true, default-features = false, features = ["log-tracer", "std"] } @@ -58,7 +58,7 @@ serde = { version = "1.0", optional = true } tracing-serde = { path = "../tracing-serde", version = "0.1.3", optional = true } # opt-in deps -parking_lot = { version = "0.13", optional = true } +parking_lot = { version = "0.12", optional = true } # registry sharded-slab = { version = "0.1.0", optional = true } diff --git a/tracing-subscriber/src/filter/env/directive.rs b/tracing-subscriber/src/filter/env/directive.rs index 3e993f6c92..f062e6ef93 100644 --- a/tracing-subscriber/src/filter/env/directive.rs +++ b/tracing-subscriber/src/filter/env/directive.rs @@ -4,7 +4,7 @@ use crate::filter::{ env::{field, FieldMap}, level::LevelFilter, }; -use lazy_static::lazy_static; +use once_cell::sync::Lazy; use regex::Regex; use std::{cmp::Ordering, fmt, iter::FromIterator, str::FromStr}; use tracing_core::{span, Level, Metadata}; @@ -120,41 +120,39 @@ impl Directive { } pub(super) fn parse(from: &str, regex: bool) -> Result { - lazy_static! { - static ref DIRECTIVE_RE: Regex = Regex::new( - r"(?x) - ^(?P(?i:trace|debug|info|warn|error|off|[0-5]))$ | - # ^^^. - # `note: we match log level names case-insensitively - ^ - (?: # target name or span name - (?P[\w:-]+)|(?P\[[^\]]*\]) - ){1,2} - (?: # level or nothing - =(?P(?i:trace|debug|info|warn|error|off|[0-5]))? - # ^^^. - # `note: we match log level names case-insensitively - )? - $ - " - ) - .unwrap(); - static ref SPAN_PART_RE: Regex = - Regex::new(r#"(?P[^\]\{]+)?(?:\{(?P[^\}]*)\})?"#).unwrap(); - static ref FIELD_FILTER_RE: Regex = - // TODO(eliza): this doesn't _currently_ handle value matchers that include comma - // characters. We should fix that. - Regex::new(r#"(?x) - ( - # field name - [[:word:]][[[:word:]]\.]* - # value part (optional) - (?:=[^,]+)? - ) - # trailing comma or EOS - (?:,\s?|$) - "#).unwrap(); - } + static DIRECTIVE_RE: Lazy = Lazy::new(|| Regex::new( + r"(?x) + ^(?P(?i:trace|debug|info|warn|error|off|[0-5]))$ | + # ^^^. + # `note: we match log level names case-insensitively + ^ + (?: # target name or span name + (?P[\w:-]+)|(?P\[[^\]]*\]) + ){1,2} + (?: # level or nothing + =(?P(?i:trace|debug|info|warn|error|off|[0-5]))? + # ^^^. + # `note: we match log level names case-insensitively + )? + $ + " + ) + .unwrap()); + static SPAN_PART_RE: Lazy = + Lazy::new(|| Regex::new(r#"(?P[^\]\{]+)?(?:\{(?P[^\}]*)\})?"#).unwrap()); + static FIELD_FILTER_RE: Lazy = + // TODO(eliza): this doesn't _currently_ handle value matchers that include comma + // characters. We should fix that. + Lazy::new(|| Regex::new(r#"(?x) + ( + # field name + [[:word:]][[[:word:]]\.]* + # value part (optional) + (?:=[^,]+)? + ) + # trailing comma or EOS + (?:,\s?|$) + "#).unwrap()); let caps = DIRECTIVE_RE.captures(from).ok_or_else(ParseError::new)?;