Skip to content

Commit f2c30d5

Browse files
authored
feat(subscriber): use per-layer filtering (#140)
Currently, the `console_subscriber::build()` and `console_subscriber::init()` functions configure an `EnvFilter` that enables the `tokio` and `runtime` targets, plus any targets configured by `RUST_LOG`. This means that the `tokio` spans used by the console will always be enabled at the `TRACE` level for all layers. This includes the `fmt` layer we previously added in `init`. Since this resulted in the `fmt` layer logs being cluttered with a bunch of `tokio=trace` spans and events even when only high-level application logs are enabled by `RUST_LOG`, we removed the `fmt` layer in PR #64. However, tokio-rs/tracing#1523 was recently merged and [released][1], adding support for [per-layer filtering][2] to `tracing-subscriber`. We can now use the per-layer filtering API to selectively enable the `tokio`/`runtime` spans and events at the `TRACE` level _only_ for the `TasksLayer`, and add a filter to the `fmt` layer based on `RUST_LOG`. This allows us to put back the `fmt` layer in `console_subscriber::init`. Now, if we run the example app (which uses `init`) with a `RUST_LOG` value that enables only the app's logs, we get nice output: ![image](https://user-images.githubusercontent.com/2796466/133124582-608c2b72-db2f-4588-bb75-585312ac8d66.png) However, we can also enable the `console-subscriber` crate's internal logging: ![image](https://user-images.githubusercontent.com/2796466/133124746-7df10f14-cf8c-40ef-96f3-5046039a8577.png) And, we can still enable `tokio=trace` ourselves, if we actually _want_ to see all the task spans and waker events: ![image](https://user-images.githubusercontent.com/2796466/133124851-3e4af25a-06a4-4912-9950-bfbab6dba4c7.png) I also added some `trace!` and `debug!` macros in `examples/app.rs` to demo that `console_subscriber::init()` also enables logging. Closes #76
1 parent 738335f commit f2c30d5

File tree

4 files changed

+68
-19
lines changed

4 files changed

+68
-19
lines changed

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

console-subscriber/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ console-api = { path = "../console-api", features = ["transport"]}
1818
tonic = { version = "0.5", features = ["transport"] }
1919
tracing-core = "0.1.18"
2020
tracing = "0.1.26"
21-
tracing-subscriber = { version = "0.2.19", default-features = false, features = ["fmt", "registry", "env-filter"] }
21+
tracing-subscriber = { version = "0.2.21", default-features = false, features = ["fmt", "registry"] }
2222
futures = { version = "0.3", default-features = false }
2323
hdrhistogram = { version = "7.3.0", default-features = false, features = ["serialization"] }
2424
serde = { version = "1", features = ["derive"] }

console-subscriber/examples/app.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
6565
async fn spawn_tasks(min: u64, max: u64) {
6666
loop {
6767
for i in min..max {
68+
tracing::trace!(i, "spawning wait task");
6869
tokio::task::Builder::new().name("wait").spawn(wait(i));
69-
tokio::time::sleep(Duration::from_secs(max) - Duration::from_secs(i)).await;
70+
71+
let sleep = Duration::from_secs(max) - Duration::from_secs(i);
72+
tracing::trace!(?sleep, "sleeping...");
73+
tokio::time::sleep(sleep).await;
7074
}
7175
}
7276
}
7377

7478
#[tracing::instrument]
7579
async fn wait(seconds: u64) {
80+
tracing::debug!("waiting...");
7681
tokio::time::sleep(Duration::from_secs(seconds)).await;
82+
tracing::trace!("done!");
7783
}
7884

7985
#[tracing::instrument]

console-subscriber/src/init.rs

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,35 @@
11
use crate::TasksLayer;
22
use std::thread;
33
use tokio::runtime;
4-
use tracing_subscriber::{layer::Layered, prelude::*, EnvFilter, Registry};
4+
use tracing_subscriber::{
5+
filter::{Filtered, LevelFilter, Targets},
6+
layer::Layered,
7+
prelude::*,
8+
Registry,
9+
};
510

6-
type ConsoleSubscriberLayer = Layered<TasksLayer, Layered<EnvFilter, Registry>>;
11+
type ConsoleSubscriberLayer = Layered<Filtered<TasksLayer, Targets, Registry>, Registry>;
712

8-
/// Starts the console subscriber server on its own thread.
13+
/// Initializes the console [tracing `Subscriber`][sub] and starts the console
14+
/// subscriber [`Server`] on its own background thread.
915
///
1016
/// This function represents the easiest way to get started using
1117
/// tokio-console.
1218
///
19+
/// In addition to the [`TasksLayer`], which collects instrumentation data
20+
/// consumed by the console, the default [`Subscriber`][sub] initialized by this
21+
/// function also includes a [`tracing_subscriber::fmt`] layer, which logs
22+
/// tracing spans and events to stdout. Which spans and events are logged will
23+
/// be determined by the `RUST_LOG` environment variable.
24+
///
1325
/// **Note**: this function sets the [default `tracing` subscriber][default]
1426
/// for your application. If you need to add additional layers to this
1527
/// subscriber, see [`build`].
1628
///
1729
/// [default]: https://docs.rs/tracing/latest/tracing/dispatcher/index.html#setting-the-default-subscriber
30+
/// [sub]: https://docs.rs/tracing/latest/tracing/trait.Subscriber.html
31+
/// [`tracing_subscriber::fmt`]: https://docs.rs/tracing-subscriber/latest/tracing-subscriber/fmt/index.html
32+
/// [`Server`]: crate::Server
1833
///
1934
/// ## Configuration
2035
///
@@ -28,7 +43,7 @@ type ConsoleSubscriberLayer = Layered<TasksLayer, Layered<EnvFilter, Registry>>;
2843
/// | `TOKIO_CONSOLE_BIND` | A HOST:PORT description, such as `localhost:1234` | `127.0.0.1:6669` |
2944
/// | `TOKIO_CONSOLE_PUBLISH_INTERVAL_MS` | The number of milliseconds to wait between sending updates to the console | 1000ms (1s) |
3045
/// | `TOKIO_CONSOLE_RECORD_PATH` | The file path to save a recording | None |
31-
/// | `RUST_LOG` | Configure the tracing filter. See [`EnvFilter`] for further information | `tokio=trace` |
46+
/// | `RUST_LOG` | Configures what events are logged events. See [`Targets`] for details. | "error" |
3247
///
3348
/// ## Further customization
3449
///
@@ -42,29 +57,53 @@ type ConsoleSubscriberLayer = Layered<TasksLayer, Layered<EnvFilter, Registry>>;
4257
/// // .with(..potential additional layer..)
4358
/// .init();
4459
/// ```
60+
///
61+
/// [`Targets`]: https://docs.rs/tracing-subscriber/latest/tracing-subscriber/filter/struct.Targets.html
4562
pub fn init() {
46-
build().init()
63+
let fmt_filter = std::env::var("RUST_LOG")
64+
.ok()
65+
.and_then(|rust_log| match rust_log.parse::<Targets>() {
66+
Ok(targets) => Some(targets),
67+
Err(e) => {
68+
eprintln!("failed to parse `RUST_LOG={:?}`: {}", rust_log, e);
69+
None
70+
}
71+
})
72+
.unwrap_or_else(|| Targets::default().with_default(LevelFilter::ERROR));
73+
build()
74+
.with(tracing_subscriber::fmt::layer().with_filter(fmt_filter))
75+
.init()
4776
}
4877

4978
/// Returns a new `tracing` [subscriber] configured with a [`TasksLayer`]
5079
/// and a [filter] that enables the spans and events required by the console.
5180
///
81+
/// This function spawns the console subscriber's [`Server`] in its own Tokio
82+
/// runtime in a background thread.
83+
///
5284
/// Unlike [`init`], this function does not set the default subscriber, allowing
5385
/// additional [`Layer`]s to be added.
5486
///
5587
/// [subscriber]: https://docs.rs/tracing/latest/tracing/subscriber/trait.Subscriber.html
56-
/// [filter]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html
88+
/// [filter]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.Targets.html
5789
/// [`Layer`]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/layer/trait.Layer.html
90+
/// [`Server`]: crate::Server
5891
///
5992
/// ## Configuration
6093
///
6194
/// `console_subscriber::build` supports all of the environmental
62-
/// configuration described at [`console_subscriber::init`][init]
95+
/// configuration described at [`console_subscriber::init`].
6396
///
6497
/// ## Differences from `init`
6598
///
99+
/// Unlike [`console_subscriber::init`], this function does *not* add a
100+
/// [`tracing_subscriber::fmt`] layer to the configured `Subscriber`. This means
101+
/// that this function will not log spans and events based on the value of the
102+
/// `RUST_LOG` environment variable. Instead, a user-provided [`fmt::Layer`] can
103+
/// be added in order to customize the log format.
104+
///
66105
/// You must call [`.init()`] on the final subscriber in order to [set the
67-
/// subscriber as the default][set_default].
106+
/// subscriber as the default][default].
68107
///
69108
/// ## Examples
70109
///
@@ -76,16 +115,20 @@ pub fn init() {
76115
/// .init();
77116
/// ```
78117
/// [`.init()`]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/util/trait.SubscriberInitExt.html
79-
/// [set_default]: https://docs.rs/tracing/latest/tracing/subscriber/fn.set_default.html
118+
/// [default]: https://docs.rs/tracing/latest/tracing/dispatcher/index.html#setting-the-default-subscriber
119+
/// [sub]: https://docs.rs/tracing/latest/tracing/trait.Subscriber.html
120+
/// [`tracing_subscriber::fmt`]: https://docs.rs/tracing-subscriber/latest/tracing-subscriber/fmt/index.html
121+
/// [`fmt::Layer`]: https://docs.rs/tracing-subscriber/latest/tracing-subscriber/fmt/struct.Layer.html
122+
/// [`console_subscriber::init`]: crate::init()
80123
#[must_use = "build() without init() will not set the default tracing subscriber"]
81124
pub fn build() -> ConsoleSubscriberLayer {
82125
let (layer, server) = TasksLayer::builder().with_default_env().build();
83126

84-
let filter = EnvFilter::from_default_env()
85-
.add_directive("tokio=trace".parse().unwrap())
86-
.add_directive("runtime=trace".parse().unwrap());
127+
let filter = Targets::new()
128+
.with_target("tokio", LevelFilter::TRACE)
129+
.with_target("runtime", LevelFilter::TRACE);
87130

88-
let console_subscriber = tracing_subscriber::registry().with(filter).with(layer);
131+
let console_subscriber = tracing_subscriber::registry().with(layer.with_filter(filter));
89132

90133
thread::Builder::new()
91134
.name("console_subscriber".into())

0 commit comments

Comments
 (0)