Rust Tracing EnvFilter
An EnvFilter is a tracing filter that can match a crate, a span, or one field value. A field rule can follow one order through a whole program.
Read the variable, or fall back
try_from_default_env reads RUST_LOG. A broken filter comes back as an error, and the fallback keeps the program running:
let filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| EnvFilter::new("info"));Turn one span up
Run the closing program with this filter. Outside the checkout span, only warn prints. Inside it, debug joins in:
$ RUST_LOG='warn,envfilter[checkout]=debug' cargo runMatch a field value
Add a field rule. Now only order 42 opens up. Order 7 stays silent, and so does the shop opened line:
$ RUST_LOG='warn,envfilter[checkout{order_id=42}]' cargo runThe anatomy of a directive
Every directive follows one shape. Leave the level off, and a match prints at every level:
target[span{field=value}]=levelExample
// Cargo.toml: tracing = "0.1" (resolved 0.1.44),
// tracing-subscriber = { version = "0.3", features = ["env-filter"] } (resolved 0.3.23)
use tracing::{debug, info, info_span, warn};
fn checkout(order_id: u32) {
let span = info_span!("checkout", order_id);
let _g = span.enter();
debug!("scanning the items");
info!("checkout done");
}
fn main() {
let filter = tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info"));
tracing_subscriber::fmt()
.with_env_filter(filter)
.with_target(false)
.without_time()
.with_ansi(false)
.init();
info!("shop opened");
checkout(42);
checkout(7);
warn!("till is low on coins");
}Key points
- EnvFilter: the tracing twin of the log filter — directives in one string, read from the environment or built in code
- A target rule names a crate or a module.
- envfilter=debug turns this one crate up.
- It leaves the rest at the global rule
- A span rule in [ ] applies only inside that span: warn plus [checkout]=debug keeps the world quiet and one span loud
- A field rule in { } matches one field value: [checkout{order_id=42}] follows a single order through the whole program
- EnvFilter lives behind the env-filter feature of tracing-subscriber.
- Ask for the feature in Cargo.toml
In this example, the output above is the quiet run. RUST_LOG is not set, so the fallback filter info applies, and both debug lines stay hidden. The program itself is small on purpose. checkout builds one span per order, and each span writes a debug line and an info line. The snippets above show two louder runs of this same binary. The first keeps the world at warn and opens the checkout span to debug. The second adds a field rule and opens only order 42. One honest limit: the filter is read once, at startup. A running program does not notice a changed variable until it restarts.
Note
env_logger rules match module paths only.
EnvFilter also matches spans and field values.
That reach is the biggest reason busy servers pick tracing.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
The filter is warn,shop[checkout{order_id=42}]. A debug! line fires inside order 7's checkout span. Does it print?