From 5fabf2513f1a70c0e920fada2bdde0a798dbd090 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Fri, 24 Sep 2021 14:29:11 -0400 Subject: [PATCH 01/15] add an option filter example --- tracing-subscriber/src/layer/mod.rs | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index 5ba89575b4..535a09ea51 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -393,6 +393,38 @@ //! # Ok(()) } //! ``` //! +//! ## Runtime-configurable Layers +//! +//! Conditionally enabling/disabling layers at runtime can be challenging due to the generics +//! used Layers implementations. However, A Layer wrapped in an `Option` is also Layers, which +//! allows some runtime configuration: +//! +//! ``` +//! // wrap this in a function so we don't actually create `debug.log` when +//! // running the doctests.. +//! # fn docs() -> Result<(), Box> { +//! use tracing_subscriber::{Registry, prelude::*}; +//! use std::{fs::File, sync::Arc}; +//! let stdout_log = tracing_subscriber::fmt::layer() +//! .pretty(); +//! +//! let debug_log = match std::env::var("LOG_PATH") { +//! Ok(path) => { +//! let file = File::create("debug.log")?; +//! let layer = tracing_subscriber::fmt::layer() +//! .with_writer(Arc::new(file)); +//! Some(layer) +//! }, +//! Err(_) => None, +//! }; +//! +//! let subscriber = Registry::default() +//! .with(stdout_log) +//! .with(debug_log); +//! tracing::subscriber::set_global_default(subscriber).expect("Unable to set global subscriber"); +//! # Ok(()) } +//! ``` +//! //! [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html //! [span IDs]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Id.html //! [the current span]: Context::current_span From aae3b41d660dfcbd0ce646ad1b8d3baca33ebcd6 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Fri, 24 Sep 2021 14:29:31 -0400 Subject: [PATCH 02/15] don't create a `debug_log.json` when running doc tests --- tracing-subscriber/src/filter/targets.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracing-subscriber/src/filter/targets.rs b/tracing-subscriber/src/filter/targets.rs index 70dae3665a..ac4abb750e 100644 --- a/tracing-subscriber/src/filter/targets.rs +++ b/tracing-subscriber/src/filter/targets.rs @@ -118,7 +118,7 @@ use tracing_core::{Interest, Metadata, Subscriber}; /// }; /// use tracing_core::Level; /// use std::{sync::Arc, fs::File}; -/// # fn main() -> Result<(), Box> { +/// # fn docs() -> Result<(), Box> { /// /// // A layer that logs events to stdout using the human-readable "pretty" /// // format. From 3d2565d16f3c9fce170a008db368ae9d784137c5 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Fri, 24 Sep 2021 17:10:32 -0400 Subject: [PATCH 03/15] Update tracing-subscriber/src/layer/mod.rs Co-authored-by: Eliza Weisman --- tracing-subscriber/src/layer/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index 535a09ea51..6eb2397dd7 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -410,7 +410,9 @@ //! //! let debug_log = match std::env::var("LOG_PATH") { //! Ok(path) => { -//! let file = File::create("debug.log")?; +//! let mut path = PathBuf::from(path); +//! path.push("debug.log"); +//! let file = File::create(path)?; //! let layer = tracing_subscriber::fmt::layer() //! .with_writer(Arc::new(file)); //! Some(layer) From 8c057e9c40b918328457aadb08ac571daea19a7b Mon Sep 17 00:00:00 2001 From: David Barsky Date: Fri, 24 Sep 2021 17:10:42 -0400 Subject: [PATCH 04/15] Update tracing-subscriber/src/layer/mod.rs Co-authored-by: Eliza Weisman --- tracing-subscriber/src/layer/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index 6eb2397dd7..33954c9f78 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -422,6 +422,9 @@ //! //! let subscriber = Registry::default() //! .with(stdout_log) +//! // If the log file is not enabled, `debug_log` will be `None`, and this layer +//! // will do nothing. However, the subscriber will still have the same _type_ +//! // regardless of whether the `Option`'s value is `None` or `Some`. //! .with(debug_log); //! tracing::subscriber::set_global_default(subscriber).expect("Unable to set global subscriber"); //! # Ok(()) } From 80b63eb8960e791f93dcc773e40127f493f7b66f Mon Sep 17 00:00:00 2001 From: David Barsky Date: Fri, 24 Sep 2021 17:10:59 -0400 Subject: [PATCH 05/15] Update tracing-subscriber/src/layer/mod.rs Co-authored-by: Eliza Weisman --- tracing-subscriber/src/layer/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index 33954c9f78..e9c5717bba 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -400,8 +400,8 @@ //! allows some runtime configuration: //! //! ``` -//! // wrap this in a function so we don't actually create `debug.log` when -//! // running the doctests.. +//! # // wrap this in a function so we don't actually create `debug.log` when +//! # // running the doctests.. //! # fn docs() -> Result<(), Box> { //! use tracing_subscriber::{Registry, prelude::*}; //! use std::{fs::File, sync::Arc}; From 03d7ec30a124cdb4169f8cc9d2e34c48e32bc47c Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 24 Sep 2021 14:24:27 -0700 Subject: [PATCH 06/15] Update tracing-subscriber/src/layer/mod.rs --- tracing-subscriber/src/layer/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index e9c5717bba..d0887f7dec 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -404,7 +404,7 @@ //! # // running the doctests.. //! # fn docs() -> Result<(), Box> { //! use tracing_subscriber::{Registry, prelude::*}; -//! use std::{fs::File, sync::Arc}; +//! use std::{fs::File, sync::Arc, path::PathBuf}; //! let stdout_log = tracing_subscriber::fmt::layer() //! .pretty(); //! From 24e6619a54c7af03b81557a533ff373a6630b2cd Mon Sep 17 00:00:00 2001 From: David Barsky Date: Sun, 26 Sep 2021 09:56:47 -0400 Subject: [PATCH 07/15] Update tracing-subscriber/src/layer/mod.rs Co-authored-by: Eliza Weisman --- tracing-subscriber/src/layer/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index d0887f7dec..b7e61a407d 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -393,7 +393,7 @@ //! # Ok(()) } //! ``` //! -//! ## Runtime-configurable Layers +//! ## Runtime Configuration With Layers //! //! Conditionally enabling/disabling layers at runtime can be challenging due to the generics //! used Layers implementations. However, A Layer wrapped in an `Option` is also Layers, which From cccdcec3a80dfcd7c8cd2e5aa8bec2135b3ffe74 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Sun, 26 Sep 2021 09:57:13 -0400 Subject: [PATCH 08/15] Update tracing-subscriber/src/layer/mod.rs Co-authored-by: Eliza Weisman --- tracing-subscriber/src/layer/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index b7e61a407d..e1f566f817 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -408,6 +408,9 @@ //! let stdout_log = tracing_subscriber::fmt::layer() //! .pretty(); //! +//! // If the LOG_PATH environment variable is set, also log events +//! // to that file. If the environment variable is not set, then `debug_log` +//! // will be `None`. //! let debug_log = match std::env::var("LOG_PATH") { //! Ok(path) => { //! let mut path = PathBuf::from(path); From d621354942a10e7a9635c82df4830f0c5cd050d8 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Sun, 26 Sep 2021 09:57:21 -0400 Subject: [PATCH 09/15] Update tracing-subscriber/src/layer/mod.rs Co-authored-by: Eliza Weisman --- tracing-subscriber/src/layer/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index e1f566f817..f4996e2a46 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -429,7 +429,9 @@ //! // will do nothing. However, the subscriber will still have the same _type_ //! // regardless of whether the `Option`'s value is `None` or `Some`. //! .with(debug_log); -//! tracing::subscriber::set_global_default(subscriber).expect("Unable to set global subscriber"); +//! +//! tracing::subscriber::set_global_default(subscriber) +///! .expect("Unable to set global subscriber"); //! # Ok(()) } //! ``` //! From f5c2fb9e566e9024da452c5a2ca451699708e83a Mon Sep 17 00:00:00 2001 From: David Barsky Date: Sun, 26 Sep 2021 10:33:08 -0400 Subject: [PATCH 10/15] fix build-breaking typo --- tracing-subscriber/src/layer/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index f4996e2a46..6232667045 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -408,7 +408,7 @@ //! let stdout_log = tracing_subscriber::fmt::layer() //! .pretty(); //! -//! // If the LOG_PATH environment variable is set, also log events +//! // If the LOG_PATH environment variable is set, also log events //! // to that file. If the environment variable is not set, then `debug_log` //! // will be `None`. //! let debug_log = match std::env::var("LOG_PATH") { @@ -431,7 +431,7 @@ //! .with(debug_log); //! //! tracing::subscriber::set_global_default(subscriber) -///! .expect("Unable to set global subscriber"); +//! .expect("Unable to set global subscriber"); //! # Ok(()) } //! ``` //! From d71486e024e322ce37d64af7801380ebda2fe4b4 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Wed, 29 Sep 2021 12:18:59 -0400 Subject: [PATCH 11/15] added a `compile_fail` example --- tracing-subscriber/src/layer/mod.rs | 95 +++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 27 deletions(-) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index 6232667045..0cbfa67d69 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -395,40 +395,80 @@ //! //! ## Runtime Configuration With Layers //! -//! Conditionally enabling/disabling layers at runtime can be challenging due to the generics -//! used Layers implementations. However, A Layer wrapped in an `Option` is also Layers, which -//! allows some runtime configuration: +//! In some cases, a particular [`Layer`] may be enabled or disabled based on +//! runtime configuration. This can introduce challenges, because the type of a +//! layered [`Subscriber`] depends on which layers are added to it: if an `if` +//! or `match` expression adds some [`Layer`]s in one branch and other layers +//! in another, the [`Subscriber`] values returned by those branches will have +//! different types. For example, the following _will not_ work: +//! +//! ```compile_fail +//! # fn docs() -> Result<(), Box> { +//! # use std::path::PathBuf; +//! # struct Config { +//! # is_prod: bool, +//! # path: PathBuf, +//! # } +//! # let cfg = Config { is_prod: false, path: PathBuf::from("debug.log") }; +//! use std::{fs::File, sync::Arc}; +//! use tracing_subscriber::{Registry, prelude::*}; //! +//! let stdout_log = tracing_subscriber::fmt::layer().pretty(); +//! let subscriber = Registry::default().with(stdout_log); +//! +//! // The compile error will occur here because the if and else +//! // branches have different, and therefore incompatible, types. +//! let subscriber = if cfg.is_prod { +//! let file = File::create(cfg.path)?; +//! let layer = tracing_subscriber::fmt::layer() +//! .json() +//! .with_writer(Arc::new(file)); +//! subscriber.with(layer) +//! } else { +//! subscriber +//! }; +//! +//! tracing::subscriber::set_global_default(subscriber) +//! .expect("Unable to set global subscriber"); +//! # Ok(()) } //! ``` -//! # // wrap this in a function so we don't actually create `debug.log` when -//! # // running the doctests.. +//! +//! However, a [`Layer`] wrapped in an [`Option`] [also implements the `Layer` +//! trait][option-impl]. This allows individual layers to be enabled or disabled at +//! runtime while always producing a [`Subscriber`] of the same type. For +//! example: +//! +//! ``` +//! # use std::path::PathBuf; //! # fn docs() -> Result<(), Box> { +//! # struct Config { +//! # is_prod: bool, +//! # path: PathBuf, +//! # } +//! # let cfg = Config { is_prod: false, path: PathBuf::from("debug.log") }; +//! use std::{fs::File, sync::Arc}; //! use tracing_subscriber::{Registry, prelude::*}; -//! use std::{fs::File, sync::Arc, path::PathBuf}; -//! let stdout_log = tracing_subscriber::fmt::layer() -//! .pretty(); //! -//! // If the LOG_PATH environment variable is set, also log events -//! // to that file. If the environment variable is not set, then `debug_log` -//! // will be `None`. -//! let debug_log = match std::env::var("LOG_PATH") { -//! Ok(path) => { -//! let mut path = PathBuf::from(path); -//! path.push("debug.log"); -//! let file = File::create(path)?; -//! let layer = tracing_subscriber::fmt::layer() -//! .with_writer(Arc::new(file)); -//! Some(layer) -//! }, -//! Err(_) => None, +//! let stdout_log = tracing_subscriber::fmt::layer().pretty(); +//! let subscriber = Registry::default().with(stdout_log); +//! +//! // if cfg.is_prod is true, also log JSON-based logs to a file. +//! // note: in reality, https://crates.io/crates/tracing-appender should +//! // be used instead of the example below. +//! let json_log = if cfg.is_prod { +//! let file = File::create(cfg.path)?; +//! let json_log = tracing_subscriber::fmt::layer() +//! .json() +//! .with_writer(Arc::new(file)); +//! Some(json_log) +//! } else { +//! None //! }; //! -//! let subscriber = Registry::default() -//! .with(stdout_log) -//! // If the log file is not enabled, `debug_log` will be `None`, and this layer -//! // will do nothing. However, the subscriber will still have the same _type_ -//! // regardless of whether the `Option`'s value is `None` or `Some`. -//! .with(debug_log); +//! // If cfg.is_prod file is false, then `json` will be `None`, and this layer +//! // will do nothing. However, the subscriber will still have the same _type_ +//! // regardless of whether the `Option`'s value is `None` or `Some`. +//! let subscriber = subscriber.with(json_log); //! //! tracing::subscriber::set_global_default(subscriber) //! .expect("Unable to set global subscriber"); @@ -444,6 +484,7 @@ //! [`Layer::register_callsite`]: Layer::register_callsite //! [`Layer::enabled`]: Layer::enabled //! [`Interest::never()`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/struct.Interest.html#method.never +//! [option-impl]: crate::layer::Layer#impl-Layer-for-Option //! [`Filtered`]: crate::filter::Filtered //! [`filter`]: crate::filter //! [`Targets`]: crate::filter::Targets From 4f327db83288096969d32105ae1030c04ec8cfe5 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Wed, 29 Sep 2021 12:43:59 -0400 Subject: [PATCH 12/15] Update tracing-subscriber/src/layer/mod.rs Co-authored-by: Eliza Weisman --- tracing-subscriber/src/layer/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index 0cbfa67d69..71d45618c2 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -417,7 +417,7 @@ //! let subscriber = Registry::default().with(stdout_log); //! //! // The compile error will occur here because the if and else -//! // branches have different, and therefore incompatible, types. +//! // branches have different (and therefore incompatible) types. //! let subscriber = if cfg.is_prod { //! let file = File::create(cfg.path)?; //! let layer = tracing_subscriber::fmt::layer() From 69c02e684ebba8d28ad1c234fd0b26dd458eb3a0 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Wed, 29 Sep 2021 12:44:24 -0400 Subject: [PATCH 13/15] Update tracing-subscriber/src/layer/mod.rs Co-authored-by: Eliza Weisman --- tracing-subscriber/src/layer/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index 71d45618c2..a6d8a462a7 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -404,12 +404,11 @@ //! //! ```compile_fail //! # fn docs() -> Result<(), Box> { -//! # use std::path::PathBuf; //! # struct Config { //! # is_prod: bool, -//! # path: PathBuf, +//! # path: &'static str, //! # } -//! # let cfg = Config { is_prod: false, path: PathBuf::from("debug.log") }; +//! # let cfg = Config { is_prod: false, path: "debug.log" }; //! use std::{fs::File, sync::Arc}; //! use tracing_subscriber::{Registry, prelude::*}; //! From 93f0f18f2f168a158128a8aacafc59d844a2622d Mon Sep 17 00:00:00 2001 From: David Barsky Date: Wed, 29 Sep 2021 12:44:43 -0400 Subject: [PATCH 14/15] Update tracing-subscriber/src/layer/mod.rs Co-authored-by: Eliza Weisman --- tracing-subscriber/src/layer/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index a6d8a462a7..dd1e5df447 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -464,7 +464,7 @@ //! None //! }; //! -//! // If cfg.is_prod file is false, then `json` will be `None`, and this layer +//! // If `cfg.is_prod` is false, then `json` will be `None`, and this layer //! // will do nothing. However, the subscriber will still have the same _type_ //! // regardless of whether the `Option`'s value is `None` or `Some`. //! let subscriber = subscriber.with(json_log); From 10fc0cf4129d0649edeaaffa95f150cdf41e6915 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Wed, 29 Sep 2021 12:48:00 -0400 Subject: [PATCH 15/15] more fixups that gh didn't let me do --- tracing-subscriber/src/layer/mod.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index dd1e5df447..adbf8cd06f 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -438,22 +438,19 @@ //! example: //! //! ``` -//! # use std::path::PathBuf; //! # fn docs() -> Result<(), Box> { //! # struct Config { //! # is_prod: bool, -//! # path: PathBuf, +//! # path: &'static str, //! # } -//! # let cfg = Config { is_prod: false, path: PathBuf::from("debug.log") }; +//! # let cfg = Config { is_prod: false, path: "debug.log" }; //! use std::{fs::File, sync::Arc}; //! use tracing_subscriber::{Registry, prelude::*}; //! //! let stdout_log = tracing_subscriber::fmt::layer().pretty(); //! let subscriber = Registry::default().with(stdout_log); //! -//! // if cfg.is_prod is true, also log JSON-based logs to a file. -//! // note: in reality, https://crates.io/crates/tracing-appender should -//! // be used instead of the example below. +//! // if `cfg.is_prod` is true, also log JSON-formatted logs to a file. //! let json_log = if cfg.is_prod { //! let file = File::create(cfg.path)?; //! let json_log = tracing_subscriber::fmt::layer() @@ -464,8 +461,8 @@ //! None //! }; //! -//! // If `cfg.is_prod` is false, then `json` will be `None`, and this layer -//! // will do nothing. However, the subscriber will still have the same _type_ +//! // If `cfg.is_prod` is false, then `json` will be `None`, and this layer +//! // will do nothing. However, the subscriber will still have the same type //! // regardless of whether the `Option`'s value is `None` or `Some`. //! let subscriber = subscriber.with(json_log); //!