tokio-rs / tracing

Application level tracing for Rust.
https://tracing.rs
MIT License
5.51k stars 721 forks source link

Filter `field=value` doesn't work. #1181

Open wllenyj opened 3 years ago

wllenyj commented 3 years ago

Bug Report

Version

master branch cargo build --exmaples

$ cargo --version cargo 1.47.0 (f3c7e066a 2020-08-28)

Platform

Linux 4.9

Crates

Description

When I run the subscriber-filter example like this, it doesn't work like I thought it would.

RUST_LOG=[shave{yak=2}] ../target/debug/examples/subscriber-filter 

Output nothing.

Run like this, it work:

$ RUST_LOG=[shave{yak}] ../target/debug/examples/subscriber-filter 
Jan 10 23:28:31.626 TRACE shave{yak=1}: subscriber_filter::yak_shave: hello! I'm gonna shave a yak excitement="yay!"
Jan 10 23:28:31.626 TRACE shave{yak=1}: subscriber_filter::yak_shave: yak shaved successfully
Jan 10 23:28:31.626 TRACE shave{yak=2}: subscriber_filter::yak_shave: hello! I'm gonna shave a yak excitement="yay!"
Jan 10 23:28:31.626 TRACE shave{yak=2}: subscriber_filter::yak_shave: yak shaved successfully
Jan 10 23:28:31.626 TRACE shave{yak=3}: subscriber_filter::yak_shave: hello! I'm gonna shave a yak excitement="yay!"
Jan 10 23:28:31.627  WARN shave{yak=3}: subscriber_filter::yak_shave: could not locate yak

I tried :

RUST_LOG=[shave{yak=\"2\"}] 
RUST_LOG=[shave{yak='2'}]
RUST_LOG="[shave{yak=\"2\"}]"

none of them worked.

Thanks all.

hawkw commented 3 years ago

Ah, I see the issue --- this is an interaction between how the filter is interpreted and the span generated by the #[instrument] macro. #[instrument] records all fields as fmt::Debug, but [shave{yak=2}] creates a filter that expects the numeric value 2, not a value whose fmt::Debug implementation produces the string 2. On the other hand, the filters with quotes expect a string value, not a fmt::Debug value.

To demonstrate the issue, you can try changing the shave function from

#[tracing::instrument]
pub fn shave(yak: usize) -> Result<(), Box<dyn Error + 'static>> {
   // ...
}

to

pub fn shave(yak: usize) -> Result<(), Box<dyn Error + 'static>> {
    let span = tracing::trace_span!("shave", yak);
    let _e = span.enter();
    // ...
}

With the manually created span, yak is recorded as a number. Then, the filter behaves as expected:

$ RUST_LOG="[shave{yak=2}]" cargo run --example subscriber-filter 
    Finished dev [unoptimized + debuginfo] target(s) in 0.10s
     Running `target/debug/examples/subscriber-filter`
Jan 10 10:44:28.502 TRACE shave{yak=2}: subscriber_filter::yak_shave: hello! I'm gonna shave a yak excitement="yay!"
Jan 10 10:44:28.502 TRACE shave{yak=2}: subscriber_filter::yak_shave: yak shaved successfully

We should improve how EnvFilter handles cases like this. It would probably be good to always try matching fmt::Debug output when a Debug value is recorded, even when a primitive type is expected.

Yamakaky commented 3 years ago

Additional faulty case:

    tracing_subscriber::fmt()
        .with_env_filter(tracing_subscriber::EnvFilter::new("[{x}]=debug"))
        .init();
    tracing::debug!(x="a", "test");

shows the DEBUG log line, but the following doesn't print anything:

    tracing_subscriber::fmt()
        .with_env_filter(tracing_subscriber::EnvFilter::new("[{x=a}]=debug"))
        .init();
    tracing::debug!(x="a", "test");

I tried using x="a", same result.

matklad commented 3 years ago

I am seeing the same effect, but looks like the root cause might be different. Seems filters with value somehow don't enable spans?

Ie, if I have a single filter, it doesnit work. If, however, I add a dummy fiter which matches noting, I get output:

image

image

EDIT: this might be just wrong? seems like {nope} just enables all infos

maddiemort commented 2 years ago

I think I'm seeing the same issue as in the original report, where the value recorded for a field comes from a type alias for u64, and I can't seem to filter on that field value with any syntax I've tried.

Has there been any progress on this issue? I see that there's a note about matching on Debug representations vs. literal values in the EnvFilter documentation, but I'm not sure if that's been around since before this issue was filed.

davidbarsky commented 2 years ago

I haven't been able to dig into this properly—and Eliza would probably be able to correct me on this—but most of the progress has gone to https://github.com/CAD97/tracing-filter/, which will be the successor to EnvFilter. I would try and see if you still have this issue with tracing-filter.

msdrigg commented 2 years ago

I've had the same issue as the original issue, but my recorded field is actually the debug representation -- not anything special with numbers or bools. No regex I can use matches the value, and even disabling regex (using EnvFilter::builder) and matching with the exact value fails.

You can see I also tried this with the tracing-filter crate, and I am seeing the same issue there

maddiemort commented 1 year ago

I would try and see if you still have this issue with tracing-filter.

Unfortunately it looks like tracing-filter only has two filtering implementations at the moment: simple filters, which are too simple to be able to do the kind of filtering that triggers the bug for me; and legacy filters, which are described as "100% bug-for-bug compatible" with the original, and in my testing that held true (this bug appeared there too). So that's not a solution for me, for the time being.

juancampa commented 1 year ago

Here's a minimal reproducible example of the filtering issue:

https://github.com/juancampa/tracing-field-filtering-repro

farnoy commented 11 months ago

Has anyone found a good solution to this? My workaround is this:

  1. use a span! macro manually
  2. event!(parent: &span, ...)
  3. let env_filter =
        EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("warn"));
    let log_file = File::create(concat!(env!("CARGO_MANIFEST_DIR"), "/log.txt")).unwrap();
    let fmt_layer = fmt::layer()
        .with_span_events(tracing_subscriber::fmt::format::FmtSpan::NONE) // this is the default
        .with_writer(log_file);

Filtering on field values only works for spans, not events, but not the enter & exit events of each span. So the only solution I could find is to output events after nesting them in a span which has the fields I want to filter on.

seunlanlege commented 9 months ago

I encountered this issue and this syntax worked for me

RUST_LOG="module[span{field=value}]" ./binary

Basically, don't quote the value

pielgrzym commented 6 months ago

Can someone modify EnvFilter docs (or other apropriate docs) to warn people that this feature is broken? This will hopefully spare someone time debugging.

rustonaut commented 5 months ago

Basically, don't quote the value

the doesn't work in a lot of situations

cattingcat commented 3 weeks ago

Is there any plans to fix it? Any workaround?

fn main() {
    let filter = EnvFilter::new("info,[my_span_1]=off");

    tracing_subscriber::fmt()
        .with_env_filter(filter)
        .init();

    tracing::info!("logged 1");

    let span_1 = tracing::span!(Level::INFO, "my_span_1");
    let _enter = span_1.enter();

    tracing::info!("not logged");
    tracing::warn!("logged 2");
}
2024-10-23T19:10:22.998649Z  INFO tracing2: logged 1
2024-10-23T19:10:22.998827Z  INFO my_span_1: tracing2: not logged
2024-10-23T19:10:22.998847Z  WARN my_span_1: tracing2: logged 2