diff --git a/tracing-attributes/Cargo.toml b/tracing-attributes/Cargo.toml index 85e51f6ffe..5a75ec0513 100644 --- a/tracing-attributes/Cargo.toml +++ b/tracing-attributes/Cargo.toml @@ -46,6 +46,7 @@ quote = "1" [dev-dependencies] tracing = { path = "../tracing", version = "0.1" } tracing-mock = { path = "../tracing-mock", features = ["tokio-test"] } +tracing-subscriber = { path = "../tracing-subscriber", version = "0.3", features = ["env-filter"] } tokio-test = { version = "0.3.0" } tracing-core = { path = "../tracing-core", version = "0.1"} async-trait = "0.1.44" diff --git a/tracing-attributes/src/expand.rs b/tracing-attributes/src/expand.rs index b563d4bbfe..81ee6ed906 100644 --- a/tracing-attributes/src/expand.rs +++ b/tracing-attributes/src/expand.rs @@ -200,19 +200,23 @@ fn gen_block( )) })(); + let target = args.target(); + let err_event = match args.err_mode { Some(FormatMode::Default) | Some(FormatMode::Display) => { - Some(quote!(tracing::error!(error = %e))) + Some(quote!(tracing::error!(target: #target, error = %e))) } - Some(FormatMode::Debug) => Some(quote!(tracing::error!(error = ?e))), + Some(FormatMode::Debug) => Some(quote!(tracing::error!(target: #target, error = ?e))), _ => None, }; let ret_event = match args.ret_mode { - Some(FormatMode::Display) => Some(quote!(tracing::event!(#level, return = %x))), - Some(FormatMode::Default) | Some(FormatMode::Debug) => { - Some(quote!(tracing::event!(#level, return = ?x))) - } + Some(FormatMode::Display) => Some(quote!( + tracing::event!(target: #target, #level, return = %x) + )), + Some(FormatMode::Default) | Some(FormatMode::Debug) => Some(quote!( + tracing::event!(target: #target, #level, return = ?x) + )), _ => None, }; diff --git a/tracing-attributes/src/lib.rs b/tracing-attributes/src/lib.rs index 48deea2785..40bd41076e 100644 --- a/tracing-attributes/src/lib.rs +++ b/tracing-attributes/src/lib.rs @@ -461,6 +461,9 @@ mod expand; /// } /// ``` /// +/// If a `target` is specified, both the `ret` and `err` arguments will emit outputs to +/// the declared target (or the default channel if `target` is not specified). +/// /// The `ret` and `err` arguments can be combined in order to record an event if a /// function returns [`Result::Ok`] or [`Result::Err`]: /// diff --git a/tracing-attributes/tests/err.rs b/tracing-attributes/tests/err.rs index f2706f3084..9e6d6b78c3 100644 --- a/tracing-attributes/tests/err.rs +++ b/tracing-attributes/tests/err.rs @@ -2,6 +2,8 @@ use tracing::subscriber::with_default; use tracing::Level; use tracing_attributes::instrument; use tracing_mock::*; +use tracing_subscriber::filter::EnvFilter; +use tracing_subscriber::layer::SubscriberExt; use std::convert::TryFrom; use std::num::TryFromIntError; @@ -198,3 +200,34 @@ fn test_err_display_default() { with_default(subscriber, || err().ok()); handle.assert_finished(); } + +#[test] +fn test_err_custom_target() { + let filter: EnvFilter = "my_target=error".parse().expect("filter should parse"); + let span = span::mock().named("error_span").with_target("my_target"); + + let (subscriber, handle) = subscriber::mock() + .new_span(span.clone()) + .enter(span.clone()) + .event( + event::mock() + .at_level(Level::ERROR) + .with_target("my_target"), + ) + .exit(span.clone()) + .drop_span(span) + .done() + .run_with_handle(); + + let subscriber = subscriber.with(filter); + + with_default(subscriber, || { + let error_span = tracing::error_span!(target: "my_target", "error_span"); + + { + let _enter = error_span.enter(); + tracing::error!(target: "my_target", "This should display") + } + }); + handle.assert_finished(); +} diff --git a/tracing-attributes/tests/ret.rs b/tracing-attributes/tests/ret.rs index 01879dfd2d..cfd2de10d3 100644 --- a/tracing-attributes/tests/ret.rs +++ b/tracing-attributes/tests/ret.rs @@ -4,12 +4,19 @@ use tracing_mock::*; use tracing::{subscriber::with_default, Level}; use tracing_attributes::instrument; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::EnvFilter; #[instrument(ret)] fn ret() -> i32 { 42 } +#[instrument(target = "my_target", ret)] +fn ret_with_target() -> i32 { + 42 +} + #[test] fn test() { let span = span::mock().named("ret"); @@ -30,6 +37,33 @@ fn test() { handle.assert_finished(); } +#[test] +fn test_custom_target() { + let filter: EnvFilter = "my_target=info".parse().expect("filter should parse"); + let span = span::mock() + .named("ret_with_target") + .with_target("my_target"); + + let (subscriber, handle) = subscriber::mock() + .new_span(span.clone()) + .enter(span.clone()) + .event( + event::mock() + .with_fields(field::mock("return").with_value(&tracing::field::debug(42))) + .at_level(Level::INFO) + .with_target("my_target"), + ) + .exit(span.clone()) + .drop_span(span) + .done() + .run_with_handle(); + + let subscriber = subscriber.with(filter); + + with_default(subscriber, ret_with_target); + handle.assert_finished(); +} + #[instrument(level = "warn", ret)] fn ret_warn() -> i32 { 42