- >>) {}
+
+#[instrument(follows_from = [&Span::current()])]
+fn follows_from_current() {}
+
+#[test]
+fn follows_from_sync_test() {
+ let cause_a = span::mock().named("cause_a");
+ let cause_b = span::mock().named("cause_b");
+ let cause_c = span::mock().named("cause_c");
+ let consequence = span::mock().named("with_follows_from_sync");
+
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(cause_a.clone())
+ .new_span(cause_b.clone())
+ .new_span(cause_c.clone())
+ .new_span(consequence.clone())
+ .follows_from(consequence.clone(), cause_a)
+ .follows_from(consequence.clone(), cause_b)
+ .follows_from(consequence.clone(), cause_c)
+ .enter(consequence.clone())
+ .exit(consequence)
+ .done()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ let cause_a = tracing::span!(Level::TRACE, "cause_a");
+ let cause_b = tracing::span!(Level::TRACE, "cause_b");
+ let cause_c = tracing::span!(Level::TRACE, "cause_c");
+
+ with_follows_from_sync(&[cause_a, cause_b, cause_c])
+ });
+
+ handle.assert_finished();
+}
+
+#[test]
+fn follows_from_async_test() {
+ let cause_a = span::mock().named("cause_a");
+ let cause_b = span::mock().named("cause_b");
+ let cause_c = span::mock().named("cause_c");
+ let consequence = span::mock().named("with_follows_from_async");
+
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(cause_a.clone())
+ .new_span(cause_b.clone())
+ .new_span(cause_c.clone())
+ .new_span(consequence.clone())
+ .follows_from(consequence.clone(), cause_a)
+ .follows_from(consequence.clone(), cause_b)
+ .follows_from(consequence.clone(), cause_c)
+ .enter(consequence.clone())
+ .exit(consequence.clone())
+ .enter(consequence.clone())
+ .exit(consequence)
+ .done()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ block_on_future(async {
+ let cause_a = tracing::span!(Level::TRACE, "cause_a");
+ let cause_b = tracing::span!(Level::TRACE, "cause_b");
+ let cause_c = tracing::span!(Level::TRACE, "cause_c");
+
+ with_follows_from_async(&[cause_a, cause_b, cause_c]).await
+ })
+ });
+
+ handle.assert_finished();
+}
+
+#[test]
+fn follows_from_current_test() {
+ let cause = span::mock().named("cause");
+ let consequence = span::mock().named("follows_from_current");
+
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(cause.clone())
+ .enter(cause.clone())
+ .new_span(consequence.clone())
+ .follows_from(consequence.clone(), cause.clone())
+ .enter(consequence.clone())
+ .exit(consequence)
+ .exit(cause)
+ .done()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ tracing::span!(Level::TRACE, "cause").in_scope(follows_from_current)
+ });
+
+ handle.assert_finished();
+}
diff --git a/tracing-attributes/tests/instrument.rs b/tracing-attributes/tests/instrument.rs
index 2b2fee71e7..b215b8455d 100644
--- a/tracing-attributes/tests/instrument.rs
+++ b/tracing-attributes/tests/instrument.rs
@@ -3,12 +3,21 @@ use tracing::Level;
use tracing_attributes::instrument;
use tracing_mock::*;
+// Reproduces a compile error when an instrumented function body contains inner
+// attributes (https://github.com/tokio-rs/tracing/issues/2294).
+#[deny(unused_variables)]
+#[instrument]
+fn repro_2294() {
+ #![allow(unused_variables)]
+ let i = 42;
+}
+
#[test]
fn override_everything() {
#[instrument(target = "my_target", level = "debug")]
fn my_fn() {}
- #[instrument(level = "debug", target = "my_target")]
+ #[instrument(level = Level::DEBUG, target = "my_target")]
fn my_other_fn() {}
let span = span::mock()
diff --git a/tracing-attributes/tests/levels.rs b/tracing-attributes/tests/levels.rs
index b074ea4f28..94fc7e85a2 100644
--- a/tracing-attributes/tests/levels.rs
+++ b/tracing-attributes/tests/levels.rs
@@ -94,3 +94,49 @@ fn numeric_levels() {
handle.assert_finished();
}
+
+#[test]
+fn enum_levels() {
+ #[instrument(level = Level::TRACE)]
+ fn trace() {}
+
+ #[instrument(level = Level::DEBUG)]
+ fn debug() {}
+
+ #[instrument(level = tracing::Level::INFO)]
+ fn info() {}
+
+ #[instrument(level = Level::WARN)]
+ fn warn() {}
+
+ #[instrument(level = Level::ERROR)]
+ fn error() {}
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(span::mock().named("trace").at_level(Level::TRACE))
+ .enter(span::mock().named("trace").at_level(Level::TRACE))
+ .exit(span::mock().named("trace").at_level(Level::TRACE))
+ .new_span(span::mock().named("debug").at_level(Level::DEBUG))
+ .enter(span::mock().named("debug").at_level(Level::DEBUG))
+ .exit(span::mock().named("debug").at_level(Level::DEBUG))
+ .new_span(span::mock().named("info").at_level(Level::INFO))
+ .enter(span::mock().named("info").at_level(Level::INFO))
+ .exit(span::mock().named("info").at_level(Level::INFO))
+ .new_span(span::mock().named("warn").at_level(Level::WARN))
+ .enter(span::mock().named("warn").at_level(Level::WARN))
+ .exit(span::mock().named("warn").at_level(Level::WARN))
+ .new_span(span::mock().named("error").at_level(Level::ERROR))
+ .enter(span::mock().named("error").at_level(Level::ERROR))
+ .exit(span::mock().named("error").at_level(Level::ERROR))
+ .done()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ trace();
+ debug();
+ info();
+ warn();
+ error();
+ });
+
+ handle.assert_finished();
+}
diff --git a/tracing-attributes/tests/parents.rs b/tracing-attributes/tests/parents.rs
new file mode 100644
index 0000000000..7069b98ea5
--- /dev/null
+++ b/tracing-attributes/tests/parents.rs
@@ -0,0 +1,102 @@
+use tracing::{subscriber::with_default, Id, Level};
+use tracing_attributes::instrument;
+use tracing_mock::*;
+
+#[instrument]
+fn with_default_parent() {}
+
+#[instrument(parent = parent_span, skip(parent_span))]
+fn with_explicit_parent
(parent_span: P)
+where
+ P: Into