aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-21 00:14:26 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-21 00:14:26 +0000
commit7095c45c7e35fdf9eed69d4c2505713a2d0266ae (patch)
treea990b115a73aad33abb10ec88f84bbcd1c2219a5
parent1b05238b94571b9b4ba9668719e312da34b9d8a5 (diff)
parentc580f843942c4f1f9769cde8683729dad8007925 (diff)
downloadtracing-attributes-android14-qpr2-release.tar.gz
Change-Id: I8cddbb45f58cf312780ac777039d148dbbb4b35a
-rw-r--r--.cargo_vcs_info.json6
-rw-r--r--Android.bp4
-rw-r--r--CHANGELOG.md93
-rw-r--r--Cargo.toml18
-rw-r--r--Cargo.toml.orig15
-rw-r--r--METADATA12
-rw-r--r--README.md12
-rw-r--r--cargo2android.json4
-rw-r--r--cargo_embargo.json3
-rw-r--r--patches/syn-2.diff906
-rw-r--r--src/attr.rs39
-rw-r--r--src/expand.rs15
-rw-r--r--src/lib.rs234
-rw-r--r--tests/async_fn.rs113
-rw-r--r--tests/destructuring.rs54
-rw-r--r--tests/err.rs154
-rw-r--r--tests/fields.rs53
-rw-r--r--tests/follows_from.rs28
-rw-r--r--tests/instrument.rs56
-rw-r--r--tests/levels.rs110
-rw-r--r--tests/names.rs24
-rw-r--r--tests/parents.rs14
-rw-r--r--tests/ret.rs128
-rw-r--r--tests/targets.rs40
-rw-r--r--tests/ui.rs7
-rw-r--r--tests/ui/async_instrument.stderr8
-rw-r--r--tests/ui/const_instrument.rs8
-rw-r--r--tests/ui/const_instrument.stderr15
28 files changed, 914 insertions, 1259 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..ae421af
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,6 @@
+{
+ "git": {
+ "sha1": "2502f19d934b092fc01bb7493eacbb16b4038bf3"
+ },
+ "path_in_vcs": "tracing-attributes"
+} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 429532b..2137241 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,4 @@
-// This file is generated by cargo2android.py --config cargo2android.json.
+// This file is generated by cargo_embargo.
// Do not modify this file as changes will be overridden on upgrade.
package {
@@ -24,7 +24,7 @@ rust_proc_macro {
name: "libtracing_attributes",
crate_name: "tracing_attributes",
cargo_env_compat: true,
- cargo_pkg_version: "0.1.23",
+ cargo_pkg_version: "0.1.27",
srcs: ["src/lib.rs"],
edition: "2018",
rustlibs: [
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 42cb09b..3cb95f7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,95 @@
+# 0.1.27 (October 13, 2023)
+
+### Changed
+
+- Bump minimum version of proc-macro2 to 1.0.60 ([#2732])
+- Generate less dead code for async block return type hint ([#2709])
+
+### Fixed
+
+- Fix a compilation error in `#[instrument]` when the `"log"` feature is enabled ([#2599])
+
+[#2732]: https://github.com/tokio-rs/tracing/pull/2732
+[#2709]: https://github.com/tokio-rs/tracing/pull/2709
+[#2599]: https://github.com/tokio-rs/tracing/pull/2599
+
+# 0.1.26 (June 21th, 2023)
+
+This release of `tracing-attributes` fixes warnings due to `allow` attributes in
+generated code that allow lints which may not exist on earlier versions of rustc.
+
+### Fixed
+
+- Allow `unknown_lints` in macro-generated code ([#2626])
+
+Thanks to @mladedav for contributing to this release!
+
+# 0.1.25 (June 19th, 2023)
+
+This release of `tracing-attributes` fixes the Clippy lint
+[`let_with_type_underscore`] in code generated by the `#[instrument]`
+attribute in Rust 1.70+.
+
+### Fixed
+
+- Allow [`clippy::let_with_type_underscore`] in macro-generated code ([#2609])
+
+Thanks to @coolreader19 for contributing to this release!
+
+[#2609]: https://github.com/tokio-rs/tracing/pull/2609
+
+[`let_with_type_underscore`]: http://rust-lang.github.io/rust-clippy/rust-1.70.0/index.html#let_with_type_underscore
+
+# 0.1.24 (April 24th, 2023)
+
+This release of `tracing-attributes` adds support for passing an optional
+`level` to the `err` and `ret` arguments to `#[instrument]`, allowing the level
+of the generated return-value event to be overridden. For example,
+
+```rust
+#[instrument(err(level = "info"))]
+fn my_great_function() -> Result<(), &'static str> {
+ // ...
+}
+```
+
+will emit an `INFO`-level event if the function returns an `Err`.
+
+In addition, this release updates the [`syn`] dependency to v2.x.x.
+
+### Added
+
+- `level` argument to `err` and `ret` to override the level of the generated
+ return value event ([#2335])
+- Improved compiler error message when `#[instrument]` is added to a `const fn`
+ ([#2418])
+
+### Changed
+
+- Updated `syn` dependency to 2.0 ([#2516])
+
+### Fixed
+
+- Fix `clippy::unreachable` warnings in `#[instrument]`-generated code ([#2356])
+- Removed unused "visit" feature flag from `syn` dependency ([#2530])
+
+### Documented
+
+- Documented default level for `err` ([#2433])
+- Improved documentation for levels in `#[instrument]` ([#2350])
+
+Thanks to @nitnelave, @jsgf, @Abhicodes-crypto, @LukeMathWalker, @andrewpollack,
+@quad, @klensy, @davidpdrsn, and @dbidwell94 for contributign to this release!
+
+[`syn`]: https://crates.io/crates/syn
+[#2335]: https://github.com/tokio-rs/tracing/pull/2335
+[#2418]: https://github.com/tokio-rs/tracing/pull/2418
+[#2516]: https://github.com/tokio-rs/tracing/pull/2516
+[#2356]: https://github.com/tokio-rs/tracing/pull/2356
+[#2530]: https://github.com/tokio-rs/tracing/pull/2530
+[#2433]: https://github.com/tokio-rs/tracing/pull/2433
+[#2350]: https://github.com/tokio-rs/tracing/pull/2350
+
# 0.1.23 (October 6, 2022)
This release of `tracing-attributes` fixes a bug where compiler diagnostic spans
@@ -5,6 +97,7 @@ for type errors in `#[instrument]`ed `async fn`s have the location of the
`#[instrument]` attribute rather than the location of the actual error, and a
bug where inner attributes in `#[instrument]`ed functions would cause a compiler
error.
+
### Fixed
- Fix incorrect handling of inner attributes in `#[instrument]`ed functions ([#2307])
diff --git a/Cargo.toml b/Cargo.toml
index 5639de0..8d90671 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2018"
-rust-version = "1.49.0"
+rust-version = "1.56.0"
name = "tracing-attributes"
-version = "0.1.23"
+version = "0.1.27"
authors = [
"Tokio Contributors <team@tokio.rs>",
"Eliza Weisman <eliza@buoyant.io>",
@@ -43,18 +43,17 @@ repository = "https://github.com/tokio-rs/tracing"
proc-macro = true
[dependencies.proc-macro2]
-version = "1"
+version = "1.0.60"
[dependencies.quote]
-version = "1"
+version = "1.0.20"
[dependencies.syn]
-version = "1.0.98"
+version = "2.0"
features = [
"full",
"parsing",
"printing",
- "visit",
"visit-mut",
"clone-impls",
"extra-traits",
@@ -63,20 +62,17 @@ features = [
default-features = false
[dev-dependencies.async-trait]
-version = "0.1.56"
+version = "0.1.67"
[dev-dependencies.rustversion]
version = "1.0.9"
[dev-dependencies.tokio-test]
-version = "0.3.0"
+version = "0.4.2"
[dev-dependencies.tracing]
version = "0.1.35"
-[dev-dependencies.tracing-core]
-version = "0.1.28"
-
[dev-dependencies.tracing-subscriber]
version = "0.3.0"
features = ["env-filter"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index d6e3adb..5bac47a 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -8,7 +8,7 @@ name = "tracing-attributes"
# - README.md
# - Update CHANGELOG.md.
# - Create "v0.1.x" git tag.
-version = "0.1.23"
+version = "0.1.27"
authors = [
"Tokio Contributors <team@tokio.rs>",
"Eliza Weisman <eliza@buoyant.io>",
@@ -28,7 +28,7 @@ keywords = ["logging", "tracing", "macro", "instrument", "log"]
license = "MIT"
readme = "README.md"
edition = "2018"
-rust-version = "1.49.0"
+rust-version = "1.56.0"
[lib]
proc-macro = true
@@ -39,17 +39,16 @@ proc-macro = true
async-await = []
[dependencies]
-proc-macro2 = "1"
-syn = { version = "1.0.98", default-features = false, features = ["full", "parsing", "printing", "visit", "visit-mut", "clone-impls", "extra-traits", "proc-macro"] }
-quote = "1"
+proc-macro2 = "1.0.60"
+syn = { version = "2.0", default-features = false, features = ["full", "parsing", "printing", "visit-mut", "clone-impls", "extra-traits", "proc-macro"] }
+quote = "1.0.20"
[dev-dependencies]
tracing = { path = "../tracing", version = "0.1.35" }
tracing-mock = { path = "../tracing-mock", features = ["tokio-test"] }
tracing-subscriber = { path = "../tracing-subscriber", version = "0.3.0", features = ["env-filter"] }
-tokio-test = { version = "0.3.0" }
-tracing-core = { path = "../tracing-core", version = "0.1.28"}
-async-trait = "0.1.56"
+tokio-test = "0.4.2"
+async-trait = "0.1.67"
trybuild = "1.0.64"
rustversion = "1.0.9"
diff --git a/METADATA b/METADATA
index ff17979..e49db78 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/tracing-attributes
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
+
name: "tracing-attributes"
description: "Macro attributes for application-level tracing."
third_party {
@@ -7,13 +11,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/tracing-attributes/tracing-attributes-0.1.23.crate"
+ value: "https://static.crates.io/crates/tracing-attributes/tracing-attributes-0.1.27.crate"
}
- version: "0.1.23"
+ version: "0.1.27"
license_type: NOTICE
last_upgrade_date {
year: 2023
- month: 3
- day: 3
+ month: 11
+ day: 17
}
}
diff --git a/README.md b/README.md
index 356b511..f14dbb6 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ Macro attributes for application-level tracing.
[crates-badge]: https://img.shields.io/crates/v/tracing-attributes.svg
[crates-url]: https://crates.io/crates/tracing-attributes
[docs-badge]: https://docs.rs/tracing-attributes/badge.svg
-[docs-url]: https://docs.rs/tracing-attributes/0.1.23
+[docs-url]: https://docs.rs/tracing-attributes/0.1.26
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
[docs-master-url]: https://tracing-rs.netlify.com/tracing_attributes
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
@@ -37,7 +37,7 @@ structured, event-based diagnostic information. This crate provides the
Note that this macro is also re-exported by the main `tracing` crate.
-*Compiler support: [requires `rustc` 1.49+][msrv]*
+*Compiler support: [requires `rustc` 1.56+][msrv]*
[msrv]: #supported-rust-versions
@@ -47,7 +47,7 @@ First, add this to your `Cargo.toml`:
```toml
[dependencies]
-tracing-attributes = "0.1.23"
+tracing-attributes = "0.1.26"
```
@@ -69,14 +69,14 @@ pub fn my_function(my_arg: usize) {
## Supported Rust Versions
Tracing is built against the latest stable release. The minimum supported
-version is 1.49. The current Tracing version is not guaranteed to build on Rust
+version is 1.56. The current Tracing version is not guaranteed to build on Rust
versions earlier than the minimum supported version.
Tracing follows the same compiler support policies as the rest of the Tokio
project. The current stable Rust compiler and the three most recent minor
versions before it will always be supported. For example, if the current stable
-compiler version is 1.45, the minimum supported version will not be increased
-past 1.42, three minor versions prior. Increasing the minimum supported compiler
+compiler version is 1.69, the minimum supported version will not be increased
+past 1.66, three minor versions prior. Increasing the minimum supported compiler
version is not considered a semver breaking change as long as doing so complies
with this policy.
diff --git a/cargo2android.json b/cargo2android.json
deleted file mode 100644
index fe43c3f..0000000
--- a/cargo2android.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "run": true,
- "device": true
-}
diff --git a/cargo_embargo.json b/cargo_embargo.json
new file mode 100644
index 0000000..cb908d7
--- /dev/null
+++ b/cargo_embargo.json
@@ -0,0 +1,3 @@
+{
+ "run_cargo": false
+}
diff --git a/patches/syn-2.diff b/patches/syn-2.diff
deleted file mode 100644
index 247e761..0000000
--- a/patches/syn-2.diff
+++ /dev/null
@@ -1,906 +0,0 @@
-diff --git a/src/attr.rs b/src/attr.rs
-index ff875e1..9b778c8 100644
---- a/src/attr.rs
-+++ b/src/attr.rs
-@@ -6,6 +6,14 @@ use quote::{quote, quote_spanned, ToTokens};
- use syn::ext::IdentExt as _;
- use syn::parse::{Parse, ParseStream};
-
-+/// Arguments to `#[instrument(err(...))]` and `#[instrument(ret(...))]` which describe how the
-+/// return value event should be emitted.
-+#[derive(Clone, Default, Debug)]
-+pub(crate) struct EventArgs {
-+ level: Option<Level>,
-+ pub(crate) mode: FormatMode,
-+}
-+
- #[derive(Clone, Default, Debug)]
- pub(crate) struct InstrumentArgs {
- level: Option<Level>,
-@@ -14,53 +22,16 @@ pub(crate) struct InstrumentArgs {
- pub(crate) parent: Option<Expr>,
- pub(crate) follows_from: Option<Expr>,
- pub(crate) skips: HashSet<Ident>,
-- pub(crate) skip_all: bool,
- pub(crate) fields: Option<Fields>,
-- pub(crate) err_mode: Option<FormatMode>,
-- pub(crate) ret_mode: Option<FormatMode>,
-+ pub(crate) err_args: Option<EventArgs>,
-+ pub(crate) ret_args: Option<EventArgs>,
- /// Errors describing any unrecognized parse inputs that we skipped.
- parse_warnings: Vec<syn::Error>,
- }
-
- impl InstrumentArgs {
-- pub(crate) fn level(&self) -> impl ToTokens {
-- fn is_level(lit: &LitInt, expected: u64) -> bool {
-- match lit.base10_parse::<u64>() {
-- Ok(value) => value == expected,
-- Err(_) => false,
-- }
-- }
--
-- match &self.level {
-- Some(Level::Str(ref lit)) if lit.value().eq_ignore_ascii_case("trace") => {
-- quote!(tracing::Level::TRACE)
-- }
-- Some(Level::Str(ref lit)) if lit.value().eq_ignore_ascii_case("debug") => {
-- quote!(tracing::Level::DEBUG)
-- }
-- Some(Level::Str(ref lit)) if lit.value().eq_ignore_ascii_case("info") => {
-- quote!(tracing::Level::INFO)
-- }
-- Some(Level::Str(ref lit)) if lit.value().eq_ignore_ascii_case("warn") => {
-- quote!(tracing::Level::WARN)
-- }
-- Some(Level::Str(ref lit)) if lit.value().eq_ignore_ascii_case("error") => {
-- quote!(tracing::Level::ERROR)
-- }
-- Some(Level::Int(ref lit)) if is_level(lit, 1) => quote!(tracing::Level::TRACE),
-- Some(Level::Int(ref lit)) if is_level(lit, 2) => quote!(tracing::Level::DEBUG),
-- Some(Level::Int(ref lit)) if is_level(lit, 3) => quote!(tracing::Level::INFO),
-- Some(Level::Int(ref lit)) if is_level(lit, 4) => quote!(tracing::Level::WARN),
-- Some(Level::Int(ref lit)) if is_level(lit, 5) => quote!(tracing::Level::ERROR),
-- Some(Level::Path(ref pat)) => quote!(#pat),
-- Some(_) => quote! {
-- compile_error!(
-- "unknown verbosity level, expected one of \"trace\", \
-- \"debug\", \"info\", \"warn\", or \"error\", or a number 1-5"
-- )
-- },
-- None => quote!(tracing::Level::INFO),
-- }
-+ pub(crate) fn level(&self) -> Level {
-+ self.level.clone().unwrap_or(Level::Info)
- }
-
- pub(crate) fn target(&self) -> impl ToTokens {
-@@ -146,20 +117,8 @@ impl Parse for InstrumentArgs {
- if !args.skips.is_empty() {
- return Err(input.error("expected only a single `skip` argument"));
- }
-- if args.skip_all {
-- return Err(input.error("expected either `skip` or `skip_all` argument"));
-- }
- let Skips(skips) = input.parse()?;
- args.skips = skips;
-- } else if lookahead.peek(kw::skip_all) {
-- if args.skip_all {
-- return Err(input.error("expected only a single `skip_all` argument"));
-- }
-- if !args.skips.is_empty() {
-- return Err(input.error("expected either `skip` or `skip_all` argument"));
-- }
-- let _ = input.parse::<kw::skip_all>()?;
-- args.skip_all = true;
- } else if lookahead.peek(kw::fields) {
- if args.fields.is_some() {
- return Err(input.error("expected only a single `fields` argument"));
-@@ -167,12 +126,12 @@ impl Parse for InstrumentArgs {
- args.fields = Some(input.parse()?);
- } else if lookahead.peek(kw::err) {
- let _ = input.parse::<kw::err>();
-- let mode = FormatMode::parse(input)?;
-- args.err_mode = Some(mode);
-+ let err_args = EventArgs::parse(input)?;
-+ args.err_args = Some(err_args);
- } else if lookahead.peek(kw::ret) {
- let _ = input.parse::<kw::ret>()?;
-- let mode = FormatMode::parse(input)?;
-- args.ret_mode = Some(mode);
-+ let ret_args = EventArgs::parse(input)?;
-+ args.ret_args = Some(ret_args);
- } else if lookahead.peek(Token![,]) {
- let _ = input.parse::<Token![,]>()?;
- } else {
-@@ -190,6 +149,55 @@ impl Parse for InstrumentArgs {
- }
- }
-
-+impl EventArgs {
-+ pub(crate) fn level(&self, default: Level) -> Level {
-+ self.level.clone().unwrap_or(default)
-+ }
-+}
-+
-+impl Parse for EventArgs {
-+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
-+ if !input.peek(syn::token::Paren) {
-+ return Ok(Self::default());
-+ }
-+ let content;
-+ let _ = syn::parenthesized!(content in input);
-+ let mut result = Self::default();
-+ let mut parse_one_arg =
-+ || {
-+ let lookahead = content.lookahead1();
-+ if lookahead.peek(kw::level) {
-+ if result.level.is_some() {
-+ return Err(content.error("expected only a single `level` argument"));
-+ }
-+ result.level = Some(content.parse()?);
-+ } else if result.mode != FormatMode::default() {
-+ return Err(content.error("expected only a single format argument"));
-+ } else if let Some(ident) = content.parse::<Option<Ident>>()? {
-+ match ident.to_string().as_str() {
-+ "Debug" => result.mode = FormatMode::Debug,
-+ "Display" => result.mode = FormatMode::Display,
-+ _ => return Err(syn::Error::new(
-+ ident.span(),
-+ "unknown event formatting mode, expected either `Debug` or `Display`",
-+ )),
-+ }
-+ }
-+ Ok(())
-+ };
-+ parse_one_arg()?;
-+ if !content.is_empty() {
-+ if content.lookahead1().peek(Token![,]) {
-+ let _ = content.parse::<Token![,]>()?;
-+ parse_one_arg()?;
-+ } else {
-+ return Err(content.error("expected `,` or `)`"));
-+ }
-+ }
-+ Ok(result)
-+ }
-+}
-+
- struct StrArg<T> {
- value: LitStr,
- _p: std::marker::PhantomData<T>,
-@@ -224,6 +232,19 @@ impl<T: Parse> Parse for ExprArg<T> {
- }
- }
-
-+struct IdentOrSelf(Ident);
-+impl Parse for IdentOrSelf {
-+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
-+ Ok(Self(
-+ if let Ok(self_token) = input.parse::<Token![self]>() {
-+ Ident::new("self", self_token.span)
-+ } else {
-+ input.parse()?
-+ },
-+ ))
-+ }
-+}
-+
- struct Skips(HashSet<Ident>);
-
- impl Parse for Skips {
-@@ -231,16 +252,16 @@ impl Parse for Skips {
- let _ = input.parse::<kw::skip>();
- let content;
- let _ = syn::parenthesized!(content in input);
-- let names: Punctuated<Ident, Token![,]> = content.parse_terminated(Ident::parse_any)?;
-+ let names: Punctuated<IdentOrSelf, Token![,]> = Punctuated::parse_terminated(&content)?;
- let mut skips = HashSet::new();
- for name in names {
-- if skips.contains(&name) {
-+ if skips.contains(&name.0) {
- return Err(syn::Error::new(
-- name.span(),
-+ name.0.span(),
- "tried to skip the same field twice",
- ));
- } else {
-- skips.insert(name);
-+ skips.insert(name.0);
- }
- }
- Ok(Self(skips))
-@@ -260,27 +281,6 @@ impl Default for FormatMode {
- }
- }
-
--impl Parse for FormatMode {
-- fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
-- if !input.peek(syn::token::Paren) {
-- return Ok(FormatMode::default());
-- }
-- let content;
-- let _ = syn::parenthesized!(content in input);
-- let maybe_mode: Option<Ident> = content.parse()?;
-- maybe_mode.map_or(Ok(FormatMode::default()), |ident| {
-- match ident.to_string().as_str() {
-- "Debug" => Ok(FormatMode::Debug),
-- "Display" => Ok(FormatMode::Display),
-- _ => Err(syn::Error::new(
-- ident.span(),
-- "unknown error mode, must be Debug or Display",
-- )),
-- }
-- })
-- }
--}
--
- #[derive(Clone, Debug)]
- pub(crate) struct Fields(pub(crate) Punctuated<Field, Token![,]>);
-
-@@ -303,7 +303,7 @@ impl Parse for Fields {
- let _ = input.parse::<kw::fields>();
- let content;
- let _ = syn::parenthesized!(content in input);
-- let fields: Punctuated<_, Token![,]> = content.parse_terminated(Field::parse)?;
-+ let fields: Punctuated<_, Token![,]> = Punctuated::parse_terminated(&content)?;
- Ok(Self(fields))
- }
- }
-@@ -376,9 +376,12 @@ impl ToTokens for FieldKind {
- }
-
- #[derive(Clone, Debug)]
--enum Level {
-- Str(LitStr),
-- Int(LitInt),
-+pub(crate) enum Level {
-+ Trace,
-+ Debug,
-+ Info,
-+ Warn,
-+ Error,
- Path(Path),
- }
-
-@@ -388,9 +391,37 @@ impl Parse for Level {
- let _ = input.parse::<Token![=]>()?;
- let lookahead = input.lookahead1();
- if lookahead.peek(LitStr) {
-- Ok(Self::Str(input.parse()?))
-+ let str: LitStr = input.parse()?;
-+ match str.value() {
-+ s if s.eq_ignore_ascii_case("trace") => Ok(Level::Trace),
-+ s if s.eq_ignore_ascii_case("debug") => Ok(Level::Debug),
-+ s if s.eq_ignore_ascii_case("info") => Ok(Level::Info),
-+ s if s.eq_ignore_ascii_case("warn") => Ok(Level::Warn),
-+ s if s.eq_ignore_ascii_case("error") => Ok(Level::Error),
-+ _ => Err(input.error(
-+ "unknown verbosity level, expected one of \"trace\", \
-+ \"debug\", \"info\", \"warn\", or \"error\", or a number 1-5",
-+ )),
-+ }
- } else if lookahead.peek(LitInt) {
-- Ok(Self::Int(input.parse()?))
-+ fn is_level(lit: &LitInt, expected: u64) -> bool {
-+ match lit.base10_parse::<u64>() {
-+ Ok(value) => value == expected,
-+ Err(_) => false,
-+ }
-+ }
-+ let int: LitInt = input.parse()?;
-+ match &int {
-+ i if is_level(i, 1) => Ok(Level::Trace),
-+ i if is_level(i, 2) => Ok(Level::Debug),
-+ i if is_level(i, 3) => Ok(Level::Info),
-+ i if is_level(i, 4) => Ok(Level::Warn),
-+ i if is_level(i, 5) => Ok(Level::Error),
-+ _ => Err(input.error(
-+ "unknown verbosity level, expected one of \"trace\", \
-+ \"debug\", \"info\", \"warn\", or \"error\", or a number 1-5",
-+ )),
-+ }
- } else if lookahead.peek(Ident) {
- Ok(Self::Path(input.parse()?))
- } else {
-@@ -399,10 +430,22 @@ impl Parse for Level {
- }
- }
-
-+impl ToTokens for Level {
-+ fn to_tokens(&self, tokens: &mut TokenStream) {
-+ match self {
-+ Level::Trace => tokens.extend(quote!(tracing::Level::TRACE)),
-+ Level::Debug => tokens.extend(quote!(tracing::Level::DEBUG)),
-+ Level::Info => tokens.extend(quote!(tracing::Level::INFO)),
-+ Level::Warn => tokens.extend(quote!(tracing::Level::WARN)),
-+ Level::Error => tokens.extend(quote!(tracing::Level::ERROR)),
-+ Level::Path(ref pat) => tokens.extend(quote!(#pat)),
-+ }
-+ }
-+}
-+
- mod kw {
- syn::custom_keyword!(fields);
- syn::custom_keyword!(skip);
-- syn::custom_keyword!(skip_all);
- syn::custom_keyword!(level);
- syn::custom_keyword!(target);
- syn::custom_keyword!(parent);
-diff --git a/src/expand.rs b/src/expand.rs
-index 7005b44..a4a463a 100644
---- a/src/expand.rs
-+++ b/src/expand.rs
-@@ -10,7 +10,7 @@ use syn::{
- };
-
- use crate::{
-- attr::{Field, Fields, FormatMode, InstrumentArgs},
-+ attr::{Field, Fields, FormatMode, InstrumentArgs, Level},
- MaybeItemFn, MaybeItemFnRef,
- };
-
-@@ -64,7 +64,7 @@ pub(crate) fn gen_function<'a, B: ToTokens + 'a>(
- // unreachable, but does affect inference, so it needs to be written
- // exactly that way for it to do its magic.
- let fake_return_edge = quote_spanned! {return_span=>
-- #[allow(unreachable_code, clippy::diverging_sub_expression, clippy::let_unit_value)]
-+ #[allow(unreachable_code, clippy::diverging_sub_expression, clippy::let_unit_value, clippy::unreachable)]
- if false {
- let __tracing_attr_fake_return: #return_type =
- unreachable!("this is just for type inference, and is unreachable code");
-@@ -116,7 +116,8 @@ fn gen_block<B: ToTokens>(
- .map(|name| quote!(#name))
- .unwrap_or_else(|| quote!(#instrumented_function_name));
-
-- let level = args.level();
-+ let args_level = args.level();
-+ let level = args_level.clone();
-
- let follows_from = args.follows_from.iter();
- let follows_from = quote! {
-@@ -134,7 +135,7 @@ fn gen_block<B: ToTokens>(
- .into_iter()
- .flat_map(|param| match param {
- FnArg::Typed(PatType { pat, ty, .. }) => {
-- param_names(*pat, RecordType::parse_from_ty(&*ty))
-+ param_names(*pat, RecordType::parse_from_ty(&ty))
- }
- FnArg::Receiver(_) => Box::new(iter::once((
- Ident::new("self", param.span()),
-@@ -178,7 +179,7 @@ fn gen_block<B: ToTokens>(
- let quoted_fields: Vec<_> = param_names
- .iter()
- .filter(|(param, _)| {
-- if args.skip_all || args.skips.contains(param) {
-+ if args.skips.contains(param) {
- return false;
- }
-
-@@ -232,21 +233,33 @@ fn gen_block<B: ToTokens>(
-
- let target = args.target();
-
-- let err_event = match args.err_mode {
-- Some(FormatMode::Default) | Some(FormatMode::Display) => {
-- Some(quote!(tracing::error!(target: #target, error = %e)))
-+ let err_event = match args.err_args {
-+ Some(event_args) => {
-+ let level_tokens = event_args.level(Level::Error);
-+ match event_args.mode {
-+ FormatMode::Default | FormatMode::Display => Some(quote!(
-+ tracing::event!(target: #target, #level_tokens, error = %e)
-+ )),
-+ FormatMode::Debug => Some(quote!(
-+ tracing::event!(target: #target, #level_tokens, 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!(target: #target, #level, return = %x)
-- )),
-- Some(FormatMode::Default) | Some(FormatMode::Debug) => Some(quote!(
-- tracing::event!(target: #target, #level, return = ?x)
-- )),
-+ let ret_event = match args.ret_args {
-+ Some(event_args) => {
-+ let level_tokens = event_args.level(args_level);
-+ match event_args.mode {
-+ FormatMode::Display => Some(quote!(
-+ tracing::event!(target: #target, #level_tokens, return = %x)
-+ )),
-+ FormatMode::Default | FormatMode::Debug => Some(quote!(
-+ tracing::event!(target: #target, #level_tokens, return = ?x)
-+ )),
-+ }
-+ }
- _ => None,
- };
-
-@@ -464,10 +477,7 @@ fn param_names(pat: Pat, record_type: RecordType) -> Box<dyn Iterator<Item = (Id
- .into_iter()
- .flat_map(|p| param_names(p, RecordType::Debug)),
- ),
-- Pat::TupleStruct(PatTupleStruct {
-- pat: PatTuple { elems, .. },
-- ..
-- }) => Box::new(
-+ Pat::TupleStruct(PatTupleStruct { elems, .. }) => Box::new(
- elems
- .into_iter()
- .flat_map(|p| param_names(p, RecordType::Debug)),
-@@ -551,7 +561,7 @@ impl<'block> AsyncInfo<'block> {
- // last expression of the block: it determines the return value of the
- // block, this is quite likely a `Box::pin` statement or an async block
- let (last_expr_stmt, last_expr) = block.stmts.iter().rev().find_map(|stmt| {
-- if let Stmt::Expr(expr) = stmt {
-+ if let Stmt::Expr(expr, _) = stmt {
- Some((stmt, expr))
- } else {
- None
-diff --git a/src/lib.rs b/src/lib.rs
-index f5974e4..4b92520 100644
---- a/src/lib.rs
-+++ b/src/lib.rs
-@@ -12,11 +12,11 @@
- //!
- //! ## Usage
- //!
--//! First, add this to your `Cargo.toml`:
-+//! In the `Cargo.toml`:
- //!
- //! ```toml
- //! [dependencies]
--//! tracing-attributes = "0.1.23"
-+//! tracing = "0.1"
- //! ```
- //!
- //! The [`#[instrument]`][instrument] attribute can now be added to a function
-@@ -24,7 +24,7 @@
- //! called. For example:
- //!
- //! ```
--//! use tracing_attributes::instrument;
-+//! use tracing::instrument;
- //!
- //! #[instrument]
- //! pub fn my_function(my_arg: usize) {
-@@ -35,8 +35,8 @@
- //! ```
- //!
- //! [`tracing`]: https://crates.io/crates/tracing
-+//! [instrument]: macro@instrument
- //! [span]: https://docs.rs/tracing/latest/tracing/span/index.html
--//! [instrument]: macro@self::instrument
- //!
- //! ## Supported Rust Versions
- //!
-@@ -52,19 +52,17 @@
- //! supported compiler version is not considered a semver breaking change as
- //! long as doing so complies with this policy.
- //!
--#![doc(html_root_url = "https://docs.rs/tracing-attributes/0.1.23")]
- #![doc(
- html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
-+ html_favicon_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/favicon.ico",
- issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
- )]
--#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
- #![warn(
- missing_debug_implementations,
- missing_docs,
- rust_2018_idioms,
- unreachable_pub,
- bad_style,
-- const_err,
- dead_code,
- improper_ctypes,
- non_shorthand_field_patterns,
-@@ -79,12 +77,9 @@
- unused_parens,
- while_true
- )]
--// TODO: once `tracing` bumps its MSRV to 1.42, remove this allow.
--#![allow(unused)]
--extern crate proc_macro;
-
- use proc_macro2::TokenStream;
--use quote::ToTokens;
-+use quote::{quote, ToTokens};
- use syn::parse::{Parse, ParseStream};
- use syn::{Attribute, ItemFn, Signature, Visibility};
-
-@@ -93,7 +88,7 @@ mod expand;
- /// Instruments a function to create and enter a `tracing` [span] every time
- /// the function is called.
- ///
--/// Unless overriden, a span with the [`INFO`] [level] will be generated.
-+/// Unless overriden, a span with `info` level will be generated.
- /// The generated span's name will be the name of the function.
- /// By default, all arguments to the function are included as fields on the
- /// span. Arguments that are `tracing` [primitive types] implementing the
-@@ -101,216 +96,27 @@ mod expand;
- /// not implement `Value` will be recorded using [`std::fmt::Debug`].
- ///
- /// [primitive types]: https://docs.rs/tracing/latest/tracing/field/trait.Value.html#foreign-impls
--/// [`Value` trait]: https://docs.rs/tracing/latest/tracing/field/trait.Value.html.
--///
--/// # Overriding Span Attributes
--///
--/// To change the [name] of the generated span, add a `name` argument to the
--/// `#[instrument]` macro, followed by an equals sign and a string literal. For
--/// example:
--///
--/// ```
--/// # use tracing_attributes::instrument;
--///
--/// // The generated span's name will be "my_span" rather than "my_function".
--/// #[instrument(name = "my_span")]
--/// pub fn my_function() {
--/// // ... do something incredibly interesting and important ...
--/// }
--/// ```
--///
--/// To override the [target] of the generated span, add a `target` argument to
--/// the `#[instrument]` macro, followed by an equals sign and a string literal
--/// for the new target. The [module path] is still recorded separately. For
--/// example:
--///
--/// ```
--/// pub mod my_module {
--/// # use tracing_attributes::instrument;
--/// // The generated span's target will be "my_crate::some_special_target",
--/// // rather than "my_crate::my_module".
--/// #[instrument(target = "my_crate::some_special_target")]
--/// pub fn my_function() {
--/// // ... all kinds of neat code in here ...
--/// }
--/// }
--/// ```
--///
--/// Finally, to override the [level] of the generated span, add a `level`
--/// argument, followed by an equals sign and a string literal with the name of
--/// the desired level. Level names are not case sensitive. For example:
--///
--/// ```
--/// # use tracing_attributes::instrument;
--/// // The span's level will be TRACE rather than INFO.
--/// #[instrument(level = "trace")]
--/// pub fn my_function() {
--/// // ... I have written a truly marvelous implementation of this function,
--/// // which this example is too narrow to contain ...
--/// }
--/// ```
--///
--/// # Skipping Fields
--///
--/// To skip recording one or more arguments to a function or method, pass
--/// the argument's name inside the `skip()` argument on the `#[instrument]`
--/// macro. This can be used when an argument to an instrumented function does
--/// not implement [`fmt::Debug`], or to exclude an argument with a verbose or
--/// costly `Debug` implementation. Note that:
-+/// [`Value` trait]: https://docs.rs/tracing/latest/tracing/field/trait.Value.html
- ///
-+/// To skip recording a function's or method's argument, pass the argument's name
-+/// to the `skip` argument on the `#[instrument]` macro. For example,
-+/// `skip` can be used when an argument to an instrumented function does
-+/// not implement [`fmt::Debug`], or to exclude an argument with a verbose
-+/// or costly Debug implementation. Note that:
- /// - multiple argument names can be passed to `skip`.
- /// - arguments passed to `skip` do _not_ need to implement `fmt::Debug`.
- ///
--/// You can also use `skip_all` to skip all arguments.
--///
--/// ## Examples
--///
--/// ```
--/// # use tracing_attributes::instrument;
--/// # use std::collections::HashMap;
--/// // This type doesn't implement `fmt::Debug`!
--/// struct NonDebug;
--///
--/// // `arg` will be recorded, while `non_debug` will not.
--/// #[instrument(skip(non_debug))]
--/// fn my_function(arg: usize, non_debug: NonDebug) {
--/// // ...
--/// }
--///
--/// // These arguments are huge
--/// #[instrument(skip_all)]
--/// fn my_big_data_function(large: Vec<u8>, also_large: HashMap<String, String>) {
--/// // ...
--/// }
--/// ```
--///
--/// Skipping the `self` parameter:
--///
--/// ```
--/// # use tracing_attributes::instrument;
--/// #[derive(Debug)]
--/// struct MyType {
--/// data: Vec<u8>, // Suppose this buffer is often quite long...
--/// }
--///
--/// impl MyType {
--/// // Suppose we don't want to print an entire kilobyte of `data`
--/// // every time this is called...
--/// #[instrument(skip(self))]
--/// pub fn my_method(&mut self, an_interesting_argument: usize) {
--/// // ... do something (hopefully, using all that `data`!)
--/// }
--/// }
--/// ```
--///
--/// # Adding Fields
--///
--/// Additional fields (key-value pairs with arbitrary data) may be added to the
--/// generated span using the `fields` argument on the `#[instrument]` macro. Any
--/// Rust expression can be used as a field value in this manner. These
--/// expressions will be evaluated at the beginning of the function's body, so
--/// arguments to the function may be used in these expressions. Field names may
--/// also be specified *without* values. Doing so will result in an [empty field]
--/// whose value may be recorded later within the function body.
--///
--/// This supports the same [field syntax] as the `span!` and `event!` macros.
-+/// Additional fields (key-value pairs with arbitrary data) can be passed to
-+/// to the generated span through the `fields` argument on the
-+/// `#[instrument]` macro. Strings, integers or boolean literals are accepted values
-+/// for each field. The name of the field must be a single valid Rust
-+/// identifier, nested (dotted) field names are not supported.
- ///
- /// Note that overlap between the names of fields and (non-skipped) arguments
- /// will result in a compile error.
- ///
--/// ## Examples
--///
--/// Adding a new field based on the value of an argument:
--///
--/// ```
--/// # use tracing_attributes::instrument;
--///
--/// // This will record a field named "i" with the value of `i` *and* a field
--/// // named "next" with the value of `i` + 1.
--/// #[instrument(fields(next = i + 1))]
--/// pub fn my_function(i: usize) {
--/// // ...
--/// }
--/// ```
--///
--/// Recording specific properties of a struct as their own fields:
--///
--/// ```
--/// # mod http {
--/// # pub struct Error;
--/// # pub struct Response<B> { pub(super) _b: std::marker::PhantomData<B> }
--/// # pub struct Request<B> { _b: B }
--/// # impl<B> std::fmt::Debug for Request<B> {
--/// # fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
--/// # f.pad("request")
--/// # }
--/// # }
--/// # impl<B> Request<B> {
--/// # pub fn uri(&self) -> &str { "fake" }
--/// # pub fn method(&self) -> &str { "GET" }
--/// # }
--/// # }
--/// # use tracing_attributes::instrument;
--///
--/// // This will record the request's URI and HTTP method as their own separate
--/// // fields.
--/// #[instrument(fields(http.uri = req.uri(), http.method = req.method()))]
--/// pub fn handle_request<B>(req: http::Request<B>) -> http::Response<B> {
--/// // ... handle the request ...
--/// # http::Response { _b: std::marker::PhantomData }
--/// }
--/// ```
--///
--/// This can be used in conjunction with `skip` or `skip_all` to record only
--/// some fields of a struct:
--/// ```
--/// # use tracing_attributes::instrument;
--/// // Remember the struct with the very large `data` field from the earlier
--/// // example? Now it also has a `name`, which we might want to include in
--/// // our span.
--/// #[derive(Debug)]
--/// struct MyType {
--/// name: &'static str,
--/// data: Vec<u8>,
--/// }
--///
--/// impl MyType {
--/// // This will skip the `data` field, but will include `self.name`,
--/// // formatted using `fmt::Display`.
--/// #[instrument(skip(self), fields(self.name = %self.name))]
--/// pub fn my_method(&mut self, an_interesting_argument: usize) {
--/// // ... do something (hopefully, using all that `data`!)
--/// }
--/// }
--/// ```
--///
--/// Adding an empty field to be recorded later:
--///
--/// ```
--/// # use tracing_attributes::instrument;
--///
--/// // This function does a very interesting and important mathematical calculation.
--/// // Suppose we want to record both the inputs to the calculation *and* its result...
--/// #[instrument(fields(result))]
--/// pub fn do_calculation(input_1: usize, input_2: usize) -> usize {
--/// // Rerform the calculation.
--/// let result = input_1 + input_2;
--///
--/// // Record the result as part of the current span.
--/// tracing::Span::current().record("result", &result);
--///
--/// // Now, the result will also be included on this event!
--/// tracing::info!("calculation complete!");
--///
--/// // ... etc ...
--/// # 0
--/// }
--/// ```
--///
- /// # Examples
--///
- /// Instrumenting a function:
--///
- /// ```
- /// # use tracing_attributes::instrument;
- /// #[instrument]
-@@ -324,11 +130,15 @@ mod expand;
- /// Setting the level for the generated span:
- /// ```
- /// # use tracing_attributes::instrument;
--/// #[instrument(level = "debug")]
-+/// # use tracing::Level;
-+/// #[instrument(level = Level::DEBUG)]
- /// pub fn my_function() {
- /// // ...
- /// }
- /// ```
-+/// Levels can be specified either with [`Level`] constants, literal strings
-+/// (e.g., `"debug"`, `"info"`) or numerically (1—5, corresponding to [`Level::TRACE`]—[`Level::ERROR`]).
-+///
- /// Overriding the generated span's name:
- /// ```
- /// # use tracing_attributes::instrument;
-@@ -399,7 +209,7 @@ mod expand;
- /// }
- /// ```
- ///
--/// To add an additional context to the span, pass key-value pairs to `fields`:
-+/// To add additional context to the span, pass key-value pairs to `fields`:
- ///
- /// ```
- /// # use tracing_attributes::instrument;
-@@ -419,10 +229,21 @@ mod expand;
- /// 42
- /// }
- /// ```
--/// The return value event will have the same level as the span generated by `#[instrument]`.
--/// By default, this will be [`INFO`], but if the level is overridden, the event will be at the same
-+/// The level of the return value event defaults to the same level as the span generated by `#[instrument]`.
-+/// By default, this will be `TRACE`, but if the span level is overridden, the event will be at the same
- /// level.
- ///
-+/// It's also possible to override the level for the `ret` event independently:
-+///
-+/// ```
-+/// # use tracing_attributes::instrument;
-+/// # use tracing::Level;
-+/// #[instrument(ret(level = Level::WARN))]
-+/// fn my_function() -> i32 {
-+/// 42
-+/// }
-+/// ```
-+///
- /// **Note**: if the function returns a `Result<T, E>`, `ret` will record returned values if and
- /// only if the function returns [`Result::Ok`].
- ///
-@@ -438,8 +259,8 @@ mod expand;
- /// }
- /// ```
- ///
--/// If the function returns a `Result<T, E>` and `E` implements `std::fmt::Display`, you can add
--/// `err` or `err(Display)` to emit error events when the function returns `Err`:
-+/// If the function returns a `Result<T, E>` and `E` implements `std::fmt::Display`, adding
-+/// `err` or `err(Display)` will emit error events when the function returns `Err`:
- ///
- /// ```
- /// # use tracing_attributes::instrument;
-@@ -449,9 +270,22 @@ mod expand;
- /// }
- /// ```
- ///
-+/// The level of the error value event defaults to `ERROR`.
-+///
-+/// Similarly, overriding the level of the `err` event :
-+///
-+/// ```
-+/// # use tracing_attributes::instrument;
-+/// # use tracing::Level;
-+/// #[instrument(err(level = Level::INFO))]
-+/// fn my_function(arg: usize) -> Result<(), std::io::Error> {
-+/// Ok(())
-+/// }
-+/// ```
-+///
- /// By default, error values will be recorded using their `std::fmt::Display` implementations.
- /// If an error implements `std::fmt::Debug`, it can be recorded using its `Debug` implementation
--/// instead, by writing `err(Debug)`:
-+/// instead by writing `err(Debug)`:
- ///
- /// ```
- /// # use tracing_attributes::instrument;
-@@ -510,44 +344,21 @@ mod expand;
- /// }
- /// ```
- ///
--/// Note than on `async-trait` <= 0.1.43, references to the `Self`
--/// type inside the `fields` argument were only allowed when the instrumented
--/// function is a method (i.e., the function receives `self` as an argument).
--/// For example, this *used to not work* because the instrument function
--/// didn't receive `self`:
--/// ```
--/// # use tracing::instrument;
--/// use async_trait::async_trait;
--///
--/// #[async_trait]
--/// pub trait Bar {
--/// async fn bar();
--/// }
--///
--/// #[derive(Debug)]
--/// struct BarImpl(usize);
-+/// `const fn` cannot be instrumented, and will result in a compilation failure:
- ///
--/// #[async_trait]
--/// impl Bar for BarImpl {
--/// #[instrument(fields(tmp = std::any::type_name::<Self>()))]
--/// async fn bar() {}
--/// }
-+/// ```compile_fail
-+/// # use tracing_attributes::instrument;
-+/// #[instrument]
-+/// const fn my_const_function() {}
- /// ```
--/// Instead, you should manually rewrite any `Self` types as the type for
--/// which you implement the trait: `#[instrument(fields(tmp = std::any::type_name::<Bar>()))]`
--/// (or maybe you can just bump `async-trait`).
- ///
- /// [span]: https://docs.rs/tracing/latest/tracing/span/index.html
--/// [name]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.name
--/// [target]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.target
--/// [level]: https://docs.rs/tracing/latest/tracing/struct.Level.html
--/// [module path]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.module_path
--/// [`INFO`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.INFO
--/// [empty field]: https://docs.rs/tracing/latest/tracing/field/struct.Empty.html
--/// [field syntax]: https://docs.rs/tracing/latest/tracing/#recording-fields
- /// [`follows_from`]: https://docs.rs/tracing/latest/tracing/struct.Span.html#method.follows_from
- /// [`tracing`]: https://github.com/tokio-rs/tracing
- /// [`fmt::Debug`]: std::fmt::Debug
-+/// [`Level`]: https://docs.rs/tracing/latest/tracing/struct.Level.html
-+/// [`Level::TRACE`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.TRACE
-+/// [`Level::ERROR`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.ERROR
- #[proc_macro_attribute]
- pub fn instrument(
- args: proc_macro::TokenStream,
-@@ -584,6 +395,13 @@ fn instrument_precise(
- let input = syn::parse::<ItemFn>(item)?;
- let instrumented_function_name = input.sig.ident.to_string();
-
-+ if input.sig.constness.is_some() {
-+ return Ok(quote! {
-+ compile_error!("the `#[instrument]` attribute may not be used with `const fn`s")
-+ }
-+ .into());
-+ }
-+
- // check for async_trait-like patterns in the block, and instrument
- // the future instead of the wrapper
- if let Some(async_like) = expand::AsyncInfo::from_fn(&input) {
diff --git a/src/attr.rs b/src/attr.rs
index 9b778c8..f5ad409 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -22,6 +22,7 @@ pub(crate) struct InstrumentArgs {
pub(crate) parent: Option<Expr>,
pub(crate) follows_from: Option<Expr>,
pub(crate) skips: HashSet<Ident>,
+ pub(crate) skip_all: bool,
pub(crate) fields: Option<Fields>,
pub(crate) err_args: Option<EventArgs>,
pub(crate) ret_args: Option<EventArgs>,
@@ -117,8 +118,20 @@ impl Parse for InstrumentArgs {
if !args.skips.is_empty() {
return Err(input.error("expected only a single `skip` argument"));
}
+ if args.skip_all {
+ return Err(input.error("expected either `skip` or `skip_all` argument"));
+ }
let Skips(skips) = input.parse()?;
args.skips = skips;
+ } else if lookahead.peek(kw::skip_all) {
+ if args.skip_all {
+ return Err(input.error("expected only a single `skip_all` argument"));
+ }
+ if !args.skips.is_empty() {
+ return Err(input.error("expected either `skip` or `skip_all` argument"));
+ }
+ let _ = input.parse::<kw::skip_all>()?;
+ args.skip_all = true;
} else if lookahead.peek(kw::fields) {
if args.fields.is_some() {
return Err(input.error("expected only a single `fields` argument"));
@@ -232,19 +245,6 @@ impl<T: Parse> Parse for ExprArg<T> {
}
}
-struct IdentOrSelf(Ident);
-impl Parse for IdentOrSelf {
- fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
- Ok(Self(
- if let Ok(self_token) = input.parse::<Token![self]>() {
- Ident::new("self", self_token.span)
- } else {
- input.parse()?
- },
- ))
- }
-}
-
struct Skips(HashSet<Ident>);
impl Parse for Skips {
@@ -252,16 +252,16 @@ impl Parse for Skips {
let _ = input.parse::<kw::skip>();
let content;
let _ = syn::parenthesized!(content in input);
- let names: Punctuated<IdentOrSelf, Token![,]> = Punctuated::parse_terminated(&content)?;
+ let names = content.parse_terminated(Ident::parse_any, Token![,])?;
let mut skips = HashSet::new();
for name in names {
- if skips.contains(&name.0) {
+ if skips.contains(&name) {
return Err(syn::Error::new(
- name.0.span(),
+ name.span(),
"tried to skip the same field twice",
));
} else {
- skips.insert(name.0);
+ skips.insert(name);
}
}
Ok(Self(skips))
@@ -303,7 +303,7 @@ impl Parse for Fields {
let _ = input.parse::<kw::fields>();
let content;
let _ = syn::parenthesized!(content in input);
- let fields: Punctuated<_, Token![,]> = Punctuated::parse_terminated(&content)?;
+ let fields = content.parse_terminated(Field::parse, Token![,])?;
Ok(Self(fields))
}
}
@@ -348,7 +348,7 @@ impl ToTokens for Field {
let name = &self.name;
let kind = &self.kind;
tokens.extend(quote! {
- #name = #kind#value
+ #name = #kind #value
})
} else if self.kind == FieldKind::Value {
// XXX(eliza): I don't like that fields without values produce
@@ -446,6 +446,7 @@ impl ToTokens for Level {
mod kw {
syn::custom_keyword!(fields);
syn::custom_keyword!(skip);
+ syn::custom_keyword!(skip_all);
syn::custom_keyword!(level);
syn::custom_keyword!(target);
syn::custom_keyword!(parent);
diff --git a/src/expand.rs b/src/expand.rs
index a4a463a..a7123e5 100644
--- a/src/expand.rs
+++ b/src/expand.rs
@@ -64,10 +64,13 @@ pub(crate) fn gen_function<'a, B: ToTokens + 'a>(
// unreachable, but does affect inference, so it needs to be written
// exactly that way for it to do its magic.
let fake_return_edge = quote_spanned! {return_span=>
- #[allow(unreachable_code, clippy::diverging_sub_expression, clippy::let_unit_value, clippy::unreachable)]
+ #[allow(
+ unknown_lints, unreachable_code, clippy::diverging_sub_expression,
+ clippy::let_unit_value, clippy::unreachable, clippy::let_with_type_underscore,
+ clippy::empty_loop
+ )]
if false {
- let __tracing_attr_fake_return: #return_type =
- unreachable!("this is just for type inference, and is unreachable code");
+ let __tracing_attr_fake_return: #return_type = loop {};
return __tracing_attr_fake_return;
}
};
@@ -179,7 +182,7 @@ fn gen_block<B: ToTokens>(
let quoted_fields: Vec<_> = param_names
.iter()
.filter(|(param, _)| {
- if args.skips.contains(param) {
+ if args.skip_all || args.skips.contains(param) {
return false;
}
@@ -340,7 +343,7 @@ fn gen_block<B: ToTokens>(
// regression in case the level is enabled.
let __tracing_attr_span;
let __tracing_attr_guard;
- if tracing::level_enabled!(#level) {
+ if tracing::level_enabled!(#level) || tracing::if_log_enabled!(#level, {true} else {false}) {
__tracing_attr_span = #span;
#follows_from
__tracing_attr_guard = __tracing_attr_span.enter();
@@ -561,7 +564,7 @@ impl<'block> AsyncInfo<'block> {
// last expression of the block: it determines the return value of the
// block, this is quite likely a `Box::pin` statement or an async block
let (last_expr_stmt, last_expr) = block.stmts.iter().rev().find_map(|stmt| {
- if let Stmt::Expr(expr, _) = stmt {
+ if let Stmt::Expr(expr, _semi) = stmt {
Some((stmt, expr))
} else {
None
diff --git a/src/lib.rs b/src/lib.rs
index 4b92520..6a0fd54 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,7 +6,7 @@
//!
//! Note that this macro is also re-exported by the main `tracing` crate.
//!
-//! *Compiler support: [requires `rustc` 1.49+][msrv]*
+//! *Compiler support: [requires `rustc` 1.56+][msrv]*
//!
//! [msrv]: #supported-rust-versions
//!
@@ -16,7 +16,7 @@
//!
//! ```toml
//! [dependencies]
-//! tracing = "0.1"
+//! tracing-attributes = "0.1.24"
//! ```
//!
//! The [`#[instrument]`][instrument] attribute can now be added to a function
@@ -35,28 +35,28 @@
//! ```
//!
//! [`tracing`]: https://crates.io/crates/tracing
-//! [instrument]: macro@instrument
//! [span]: https://docs.rs/tracing/latest/tracing/span/index.html
+//! [instrument]: macro@self::instrument
//!
//! ## Supported Rust Versions
//!
//! Tracing is built against the latest stable release. The minimum supported
-//! version is 1.49. The current Tracing version is not guaranteed to build on
+//! version is 1.56. The current Tracing version is not guaranteed to build on
//! Rust versions earlier than the minimum supported version.
//!
//! Tracing follows the same compiler support policies as the rest of the Tokio
//! project. The current stable Rust compiler and the three most recent minor
//! versions before it will always be supported. For example, if the current
-//! stable compiler version is 1.45, the minimum supported version will not be
-//! increased past 1.42, three minor versions prior. Increasing the minimum
+//! stable compiler version is 1.69, the minimum supported version will not be
+//! increased past 1.66, three minor versions prior. Increasing the minimum
//! supported compiler version is not considered a semver breaking change as
//! long as doing so complies with this policy.
//!
#![doc(
html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
- html_favicon_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/favicon.ico",
issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
)]
+#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
#![warn(
missing_debug_implementations,
missing_docs,
@@ -77,6 +77,9 @@
unused_parens,
while_true
)]
+// TODO: once `tracing` bumps its MSRV to 1.42, remove this allow.
+#![allow(unused)]
+extern crate proc_macro;
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
@@ -88,7 +91,7 @@ mod expand;
/// Instruments a function to create and enter a `tracing` [span] every time
/// the function is called.
///
-/// Unless overriden, a span with `info` level will be generated.
+/// Unless overridden, a span with the [`INFO`] [level] will be generated.
/// The generated span's name will be the name of the function.
/// By default, all arguments to the function are included as fields on the
/// span. Arguments that are `tracing` [primitive types] implementing the
@@ -96,27 +99,217 @@ mod expand;
/// not implement `Value` will be recorded using [`std::fmt::Debug`].
///
/// [primitive types]: https://docs.rs/tracing/latest/tracing/field/trait.Value.html#foreign-impls
-/// [`Value` trait]: https://docs.rs/tracing/latest/tracing/field/trait.Value.html
+/// [`Value` trait]: https://docs.rs/tracing/latest/tracing/field/trait.Value.html.
+///
+/// # Overriding Span Attributes
+///
+/// To change the [name] of the generated span, add a `name` argument to the
+/// `#[instrument]` macro, followed by an equals sign and a string literal. For
+/// example:
+///
+/// ```
+/// # use tracing_attributes::instrument;
+///
+/// // The generated span's name will be "my_span" rather than "my_function".
+/// #[instrument(name = "my_span")]
+/// pub fn my_function() {
+/// // ... do something incredibly interesting and important ...
+/// }
+/// ```
+///
+/// To override the [target] of the generated span, add a `target` argument to
+/// the `#[instrument]` macro, followed by an equals sign and a string literal
+/// for the new target. The [module path] is still recorded separately. For
+/// example:
+///
+/// ```
+/// pub mod my_module {
+/// # use tracing_attributes::instrument;
+/// // The generated span's target will be "my_crate::some_special_target",
+/// // rather than "my_crate::my_module".
+/// #[instrument(target = "my_crate::some_special_target")]
+/// pub fn my_function() {
+/// // ... all kinds of neat code in here ...
+/// }
+/// }
+/// ```
+///
+/// Finally, to override the [level] of the generated span, add a `level`
+/// argument, followed by an equals sign and a string literal with the name of
+/// the desired level. Level names are not case sensitive. For example:
+///
+/// ```
+/// # use tracing_attributes::instrument;
+/// // The span's level will be TRACE rather than INFO.
+/// #[instrument(level = "trace")]
+/// pub fn my_function() {
+/// // ... I have written a truly marvelous implementation of this function,
+/// // which this example is too narrow to contain ...
+/// }
+/// ```
+///
+/// # Skipping Fields
+///
+/// To skip recording one or more arguments to a function or method, pass
+/// the argument's name inside the `skip()` argument on the `#[instrument]`
+/// macro. This can be used when an argument to an instrumented function does
+/// not implement [`fmt::Debug`], or to exclude an argument with a verbose or
+/// costly `Debug` implementation. Note that:
///
-/// To skip recording a function's or method's argument, pass the argument's name
-/// to the `skip` argument on the `#[instrument]` macro. For example,
-/// `skip` can be used when an argument to an instrumented function does
-/// not implement [`fmt::Debug`], or to exclude an argument with a verbose
-/// or costly Debug implementation. Note that:
/// - multiple argument names can be passed to `skip`.
/// - arguments passed to `skip` do _not_ need to implement `fmt::Debug`.
///
+/// You can also use `skip_all` to skip all arguments.
+///
+/// ## Examples
+///
+/// ```
+/// # use tracing_attributes::instrument;
+/// # use std::collections::HashMap;
+/// // This type doesn't implement `fmt::Debug`!
+/// struct NonDebug;
+///
+/// // `arg` will be recorded, while `non_debug` will not.
+/// #[instrument(skip(non_debug))]
+/// fn my_function(arg: usize, non_debug: NonDebug) {
+/// // ...
+/// }
+///
+/// // These arguments are huge
+/// #[instrument(skip_all)]
+/// fn my_big_data_function(large: Vec<u8>, also_large: HashMap<String, String>) {
+/// // ...
+/// }
+/// ```
+///
+/// Skipping the `self` parameter:
+///
+/// ```
+/// # use tracing_attributes::instrument;
+/// #[derive(Debug)]
+/// struct MyType {
+/// data: Vec<u8>, // Suppose this buffer is often quite long...
+/// }
+///
+/// impl MyType {
+/// // Suppose we don't want to print an entire kilobyte of `data`
+/// // every time this is called...
+/// #[instrument(skip(self))]
+/// pub fn my_method(&mut self, an_interesting_argument: usize) {
+/// // ... do something (hopefully, using all that `data`!)
+/// }
+/// }
+/// ```
+///
+/// # Adding Fields
+///
/// Additional fields (key-value pairs with arbitrary data) can be passed to
/// to the generated span through the `fields` argument on the
/// `#[instrument]` macro. Strings, integers or boolean literals are accepted values
/// for each field. The name of the field must be a single valid Rust
-/// identifier, nested (dotted) field names are not supported.
+/// identifier, nested (dotted) field names are not supported. Any
+/// Rust expression can be used as a field value in this manner. These
+/// expressions will be evaluated at the beginning of the function's body, so
+/// arguments to the function may be used in these expressions. Field names may
+/// also be specified *without* values. Doing so will result in an [empty field]
+/// whose value may be recorded later within the function body.
///
/// Note that overlap between the names of fields and (non-skipped) arguments
/// will result in a compile error.
///
+/// ## Examples
+///
+/// Adding a new field based on the value of an argument:
+///
+/// ```
+/// # use tracing_attributes::instrument;
+///
+/// // This will record a field named "i" with the value of `i` *and* a field
+/// // named "next" with the value of `i` + 1.
+/// #[instrument(fields(next = i + 1))]
+/// pub fn my_function(i: usize) {
+/// // ...
+/// }
+/// ```
+///
+/// Recording specific properties of a struct as their own fields:
+///
+/// ```
+/// # mod http {
+/// # pub struct Error;
+/// # pub struct Response<B> { pub(super) _b: std::marker::PhantomData<B> }
+/// # pub struct Request<B> { _b: B }
+/// # impl<B> std::fmt::Debug for Request<B> {
+/// # fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+/// # f.pad("request")
+/// # }
+/// # }
+/// # impl<B> Request<B> {
+/// # pub fn uri(&self) -> &str { "fake" }
+/// # pub fn method(&self) -> &str { "GET" }
+/// # }
+/// # }
+/// # use tracing_attributes::instrument;
+///
+/// // This will record the request's URI and HTTP method as their own separate
+/// // fields.
+/// #[instrument(fields(http.uri = req.uri(), http.method = req.method()))]
+/// pub fn handle_request<B>(req: http::Request<B>) -> http::Response<B> {
+/// // ... handle the request ...
+/// # http::Response { _b: std::marker::PhantomData }
+/// }
+/// ```
+///
+/// This can be used in conjunction with `skip` or `skip_all` to record only
+/// some fields of a struct:
+/// ```
+/// # use tracing_attributes::instrument;
+/// // Remember the struct with the very large `data` field from the earlier
+/// // example? Now it also has a `name`, which we might want to include in
+/// // our span.
+/// #[derive(Debug)]
+/// struct MyType {
+/// name: &'static str,
+/// data: Vec<u8>,
+/// }
+///
+/// impl MyType {
+/// // This will skip the `data` field, but will include `self.name`,
+/// // formatted using `fmt::Display`.
+/// #[instrument(skip(self), fields(self.name = %self.name))]
+/// pub fn my_method(&mut self, an_interesting_argument: usize) {
+/// // ... do something (hopefully, using all that `data`!)
+/// }
+/// }
+/// ```
+///
+/// Adding an empty field to be recorded later:
+///
+/// ```
+/// # use tracing_attributes::instrument;
+///
+/// // This function does a very interesting and important mathematical calculation.
+/// // Suppose we want to record both the inputs to the calculation *and* its result...
+/// #[instrument(fields(result))]
+/// pub fn do_calculation(input_1: usize, input_2: usize) -> usize {
+/// // Rerform the calculation.
+/// let result = input_1 + input_2;
+///
+/// // Record the result as part of the current span.
+/// tracing::Span::current().record("result", &result);
+///
+/// // Now, the result will also be included on this event!
+/// tracing::info!("calculation complete!");
+///
+/// // ... etc ...
+/// # 0
+/// }
+/// ```
+///
/// # Examples
+///
/// Instrumenting a function:
+///
/// ```
/// # use tracing_attributes::instrument;
/// #[instrument]
@@ -229,8 +422,8 @@ mod expand;
/// 42
/// }
/// ```
-/// The level of the return value event defaults to the same level as the span generated by `#[instrument]`.
-/// By default, this will be `TRACE`, but if the span level is overridden, the event will be at the same
+/// The return value event will have the same level as the span generated by `#[instrument]`.
+/// By default, this will be [`INFO`], but if the level is overridden, the event will be at the same
/// level.
///
/// It's also possible to override the level for the `ret` event independently:
@@ -353,6 +546,13 @@ mod expand;
/// ```
///
/// [span]: https://docs.rs/tracing/latest/tracing/span/index.html
+/// [name]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.name
+/// [target]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.target
+/// [level]: https://docs.rs/tracing/latest/tracing/struct.Level.html
+/// [module path]: https://docs.rs/tracing/latest/tracing/struct.Metadata.html#method.module_path
+/// [`INFO`]: https://docs.rs/tracing/latest/tracing/struct.Level.html#associatedconstant.INFO
+/// [empty field]: https://docs.rs/tracing/latest/tracing/field/struct.Empty.html
+/// [field syntax]: https://docs.rs/tracing/latest/tracing/#recording-fields
/// [`follows_from`]: https://docs.rs/tracing/latest/tracing/struct.Span.html#method.follows_from
/// [`tracing`]: https://github.com/tokio-rs/tracing
/// [`fmt::Debug`]: std::fmt::Debug
diff --git a/tests/async_fn.rs b/tests/async_fn.rs
index c899636..1d92734 100644
--- a/tests/async_fn.rs
+++ b/tests/async_fn.rs
@@ -17,7 +17,6 @@ async fn test_async_fn(polls: usize) -> Result<(), ()> {
#[allow(dead_code)] // this is just here to test whether it compiles.
#[instrument]
async fn test_ret_impl_trait(n: i32) -> Result<impl Iterator<Item = i32>, ()> {
- let n = n;
Ok((0..10).filter(move |x| *x < n))
}
@@ -84,14 +83,16 @@ fn repro_1831_2() -> impl Future<Output = Result<(), Infallible>> {
#[test]
fn async_fn_only_enters_for_polls() {
let (subscriber, handle) = subscriber::mock()
- .new_span(span::mock().named("test_async_fn"))
- .enter(span::mock().named("test_async_fn"))
- .event(event::mock().with_fields(field::mock("awaiting").with_value(&true)))
- .exit(span::mock().named("test_async_fn"))
- .enter(span::mock().named("test_async_fn"))
- .exit(span::mock().named("test_async_fn"))
- .drop_span(span::mock().named("test_async_fn"))
- .done()
+ .new_span(expect::span().named("test_async_fn"))
+ .enter(expect::span().named("test_async_fn"))
+ .event(expect::event().with_fields(expect::field("awaiting").with_value(&true)))
+ .exit(expect::span().named("test_async_fn"))
+ .enter(expect::span().named("test_async_fn"))
+ .exit(expect::span().named("test_async_fn"))
+ .enter(expect::span().named("test_async_fn"))
+ .exit(expect::span().named("test_async_fn"))
+ .drop_span(expect::span().named("test_async_fn"))
+ .only()
.run_with_handle();
with_default(subscriber, || {
block_on_future(async { test_async_fn(2).await }).unwrap();
@@ -111,19 +112,23 @@ fn async_fn_nested() {
tracing::trace!(nested = true);
}
- let span = span::mock().named("test_async_fns_nested");
- let span2 = span::mock().named("test_async_fns_nested_other");
+ let span = expect::span().named("test_async_fns_nested");
+ let span2 = expect::span().named("test_async_fns_nested_other");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.new_span(span2.clone())
.enter(span2.clone())
- .event(event::mock().with_fields(field::mock("nested").with_value(&true)))
+ .event(expect::event().with_fields(expect::field("nested").with_value(&true)))
+ .exit(span2.clone())
+ .enter(span2.clone())
.exit(span2.clone())
.drop_span(span2)
.exit(span.clone())
+ .enter(span.clone())
+ .exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -185,29 +190,35 @@ fn async_fn_with_async_trait() {
}
}
- let span = span::mock().named("foo");
- let span2 = span::mock().named("bar");
- let span3 = span::mock().named("baz");
+ let span = expect::span().named("foo");
+ let span2 = expect::span().named("bar");
+ let span3 = expect::span().named("baz");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone()
- .with_field(field::mock("self"))
- .with_field(field::mock("v")),
+ .with_field(expect::field("self"))
+ .with_field(expect::field("v")),
)
.enter(span.clone())
.new_span(span3.clone())
.enter(span3.clone())
- .event(event::mock().with_fields(field::mock("val").with_value(&2u64)))
+ .event(expect::event().with_fields(expect::field("val").with_value(&2u64)))
+ .exit(span3.clone())
+ .enter(span3.clone())
.exit(span3.clone())
.drop_span(span3)
- .new_span(span2.clone().with_field(field::mock("self")))
+ .new_span(span2.clone().with_field(expect::field("self")))
+ .enter(span2.clone())
+ .event(expect::event().with_fields(expect::field("val").with_value(&5u64)))
+ .exit(span2.clone())
.enter(span2.clone())
- .event(event::mock().with_fields(field::mock("val").with_value(&5u64)))
.exit(span2.clone())
.drop_span(span2)
.exit(span.clone())
+ .enter(span.clone())
+ .exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -243,21 +254,23 @@ fn async_fn_with_async_trait_and_fields_expressions() {
async fn call(&mut self, _v: usize) {}
}
- let span = span::mock().named("call");
+ let span = expect::span().named("call");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_field(
- field::mock("_v")
+ expect::field("_v")
.with_value(&5usize)
- .and(field::mock("test").with_value(&tracing::field::debug(10)))
- .and(field::mock("val").with_value(&42u64))
- .and(field::mock("val2").with_value(&42u64)),
+ .and(expect::field("test").with_value(&tracing::field::debug(10)))
+ .and(expect::field("val").with_value(&42u64))
+ .and(expect::field("val2").with_value(&42u64)),
),
)
.enter(span.clone())
.exit(span.clone())
+ .enter(span.clone())
+ .exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -309,40 +322,46 @@ fn async_fn_with_async_trait_and_fields_expressions_with_generic_parameter() {
}
//let span = span::mock().named("call");
- let span2 = span::mock().named("call_with_self");
- let span3 = span::mock().named("call_with_mut_self");
- let span4 = span::mock().named("sync_fun");
+ let span2 = expect::span().named("call_with_self");
+ let span3 = expect::span().named("call_with_mut_self");
+ let span4 = expect::span().named("sync_fun");
let (subscriber, handle) = subscriber::mock()
/*.new_span(span.clone()
.with_field(
- field::mock("Self").with_value(&"TestImpler")))
+ expect::field("Self").with_value(&"TestImpler")))
.enter(span.clone())
.exit(span.clone())
.drop_span(span)*/
.new_span(
span2
.clone()
- .with_field(field::mock("Self").with_value(&std::any::type_name::<TestImpl>())),
+ .with_field(expect::field("Self").with_value(&std::any::type_name::<TestImpl>())),
)
.enter(span2.clone())
.new_span(
span4
.clone()
- .with_field(field::mock("Self").with_value(&std::any::type_name::<TestImpl>())),
+ .with_field(expect::field("Self").with_value(&std::any::type_name::<TestImpl>())),
)
.enter(span4.clone())
+ .exit(span4.clone())
+ .enter(span4.clone())
.exit(span4)
.exit(span2.clone())
+ .enter(span2.clone())
+ .exit(span2.clone())
.drop_span(span2)
.new_span(
span3
.clone()
- .with_field(field::mock("Self").with_value(&std::any::type_name::<TestImpl>())),
+ .with_field(expect::field("Self").with_value(&std::any::type_name::<TestImpl>())),
)
.enter(span3.clone())
.exit(span3.clone())
+ .enter(span3.clone())
+ .exit(span3.clone())
.drop_span(span3)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -377,13 +396,15 @@ fn out_of_scope_fields() {
}
}
- let span = span::mock().named("call");
+ let span = expect::span().named("call");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.exit(span.clone())
+ .enter(span.clone())
+ .exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -408,8 +429,8 @@ fn manual_impl_future() {
}
}
- let span = span::mock().named("manual_impl_future");
- let poll_event = || event::mock().with_fields(field::mock("poll").with_value(&true));
+ let span = expect::span().named("manual_impl_future");
+ let poll_event = || expect::event().with_fields(expect::field("poll").with_value(&true));
let (subscriber, handle) = subscriber::mock()
// await manual_impl_future
@@ -417,8 +438,10 @@ fn manual_impl_future() {
.enter(span.clone())
.event(poll_event())
.exit(span.clone())
+ .enter(span.clone())
+ .exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -439,8 +462,8 @@ fn manual_box_pin() {
})
}
- let span = span::mock().named("manual_box_pin");
- let poll_event = || event::mock().with_fields(field::mock("poll").with_value(&true));
+ let span = expect::span().named("manual_box_pin");
+ let poll_event = || expect::event().with_fields(expect::field("poll").with_value(&true));
let (subscriber, handle) = subscriber::mock()
// await manual_box_pin
@@ -448,8 +471,10 @@ fn manual_box_pin() {
.enter(span.clone())
.event(poll_event())
.exit(span.clone())
+ .enter(span.clone())
+ .exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
diff --git a/tests/destructuring.rs b/tests/destructuring.rs
index 09cf1ad..cc4fecf 100644
--- a/tests/destructuring.rs
+++ b/tests/destructuring.rs
@@ -7,21 +7,21 @@ fn destructure_tuples() {
#[instrument]
fn my_fn((arg1, arg2): (usize, usize)) {}
- let span = span::mock().named("my_fn");
+ let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_field(
- field::mock("arg1")
+ expect::field("arg1")
.with_value(&format_args!("1"))
- .and(field::mock("arg2").with_value(&format_args!("2")))
+ .and(expect::field("arg2").with_value(&format_args!("2")))
.only(),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -36,23 +36,23 @@ fn destructure_nested_tuples() {
#[instrument]
fn my_fn(((arg1, arg2), (arg3, arg4)): ((usize, usize), (usize, usize))) {}
- let span = span::mock().named("my_fn");
+ let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_field(
- field::mock("arg1")
+ expect::field("arg1")
.with_value(&format_args!("1"))
- .and(field::mock("arg2").with_value(&format_args!("2")))
- .and(field::mock("arg3").with_value(&format_args!("3")))
- .and(field::mock("arg4").with_value(&format_args!("4")))
+ .and(expect::field("arg2").with_value(&format_args!("2")))
+ .and(expect::field("arg3").with_value(&format_args!("3")))
+ .and(expect::field("arg4").with_value(&format_args!("4")))
.only(),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -67,17 +67,17 @@ fn destructure_refs() {
#[instrument]
fn my_fn(&arg1: &usize) {}
- let span = span::mock().named("my_fn");
+ let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone()
- .with_field(field::mock("arg1").with_value(&1usize).only()),
+ .with_field(expect::field("arg1").with_value(&1usize).only()),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -94,21 +94,21 @@ fn destructure_tuple_structs() {
#[instrument]
fn my_fn(Foo(arg1, arg2): Foo) {}
- let span = span::mock().named("my_fn");
+ let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_field(
- field::mock("arg1")
+ expect::field("arg1")
.with_value(&format_args!("1"))
- .and(field::mock("arg2").with_value(&format_args!("2")))
+ .and(expect::field("arg2").with_value(&format_args!("2")))
.only(),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -135,21 +135,21 @@ fn destructure_structs() {
let _ = (arg1, arg2);
}
- let span = span::mock().named("my_fn");
+ let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_field(
- field::mock("arg1")
+ expect::field("arg1")
.with_value(&format_args!("1"))
- .and(field::mock("arg2").with_value(&format_args!("2")))
+ .and(expect::field("arg2").with_value(&format_args!("2")))
.only(),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -180,23 +180,23 @@ fn destructure_everything() {
let _ = (arg1, arg2, arg3, arg4);
}
- let span = span::mock().named("my_fn");
+ let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_field(
- field::mock("arg1")
+ expect::field("arg1")
.with_value(&format_args!("1"))
- .and(field::mock("arg2").with_value(&format_args!("2")))
- .and(field::mock("arg3").with_value(&format_args!("3")))
- .and(field::mock("arg4").with_value(&format_args!("4")))
+ .and(expect::field("arg2").with_value(&format_args!("2")))
+ .and(expect::field("arg3").with_value(&format_args!("3")))
+ .and(expect::field("arg4").with_value(&format_args!("4")))
.only(),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
diff --git a/tests/err.rs b/tests/err.rs
index 9e6d6b7..bee7aa5 100644
--- a/tests/err.rs
+++ b/tests/err.rs
@@ -21,20 +21,41 @@ fn err_suspicious_else() -> Result<u8, TryFromIntError> {
#[test]
fn test() {
- let span = span::mock().named("err");
+ let span = expect::span().named("err");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
- .event(event::mock().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::ERROR))
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || err().ok());
handle.assert_finished();
}
#[instrument(err)]
+fn err_early_return() -> Result<u8, TryFromIntError> {
+ u8::try_from(1234)?;
+ Ok(5)
+}
+
+#[test]
+fn test_early_return() {
+ let span = expect::span().named("err_early_return");
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(span.clone())
+ .enter(span.clone())
+ .event(expect::event().at_level(Level::ERROR))
+ .exit(span.clone())
+ .drop_span(span)
+ .only()
+ .run_with_handle();
+ with_default(subscriber, || err_early_return().ok());
+ handle.assert_finished();
+}
+
+#[instrument(err)]
async fn err_async(polls: usize) -> Result<u8, TryFromIntError> {
let future = PollN::new_ok(polls);
tracing::trace!(awaiting = true);
@@ -44,21 +65,23 @@ async fn err_async(polls: usize) -> Result<u8, TryFromIntError> {
#[test]
fn test_async() {
- let span = span::mock().named("err_async");
+ let span = expect::span().named("err_async");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
- event::mock()
- .with_fields(field::mock("awaiting").with_value(&true))
+ expect::event()
+ .with_fields(expect::field("awaiting").with_value(&true))
.at_level(Level::TRACE),
)
.exit(span.clone())
.enter(span.clone())
- .event(event::mock().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::ERROR))
+ .exit(span.clone())
+ .enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
block_on_future(async { err_async(2).await }).ok();
@@ -74,14 +97,14 @@ fn err_mut(out: &mut u8) -> Result<(), TryFromIntError> {
#[test]
fn test_mut() {
- let span = span::mock().named("err_mut");
+ let span = expect::span().named("err_mut");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
- .event(event::mock().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::ERROR))
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || err_mut(&mut 0).ok());
handle.assert_finished();
@@ -98,21 +121,23 @@ async fn err_mut_async(polls: usize, out: &mut u8) -> Result<(), TryFromIntError
#[test]
fn test_mut_async() {
- let span = span::mock().named("err_mut_async");
+ let span = expect::span().named("err_mut_async");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
- event::mock()
- .with_fields(field::mock("awaiting").with_value(&true))
+ expect::event()
+ .with_fields(expect::field("awaiting").with_value(&true))
.at_level(Level::TRACE),
)
.exit(span.clone())
.enter(span.clone())
- .event(event::mock().at_level(Level::ERROR))
+ .event(expect::event().at_level(Level::ERROR))
+ .exit(span.clone())
+ .enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
block_on_future(async { err_mut_async(2, &mut 0).await }).ok();
@@ -129,17 +154,17 @@ fn impl_trait_return_type() {
Ok(0..x)
}
- let span = span::mock().named("returns_impl_trait");
+ let span = expect::span().named("returns_impl_trait");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone()
- .with_field(field::mock("x").with_value(&10usize).only()),
+ .with_field(expect::field("x").with_value(&10usize).only()),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -158,13 +183,13 @@ fn err_dbg() -> Result<u8, TryFromIntError> {
#[test]
fn test_err_dbg() {
- let span = span::mock().named("err_dbg");
+ let span = expect::span().named("err_dbg");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
- event::mock().at_level(Level::ERROR).with_fields(
- field::mock("error")
+ expect::event().at_level(Level::ERROR).with_fields(
+ expect::field("error")
// use the actual error value that will be emitted, so
// that this test doesn't break if the standard library
// changes the `fmt::Debug` output from the error type
@@ -174,7 +199,7 @@ fn test_err_dbg() {
)
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || err_dbg().ok());
handle.assert_finished();
@@ -182,20 +207,20 @@ fn test_err_dbg() {
#[test]
fn test_err_display_default() {
- let span = span::mock().named("err");
+ let span = expect::span().named("err");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
- event::mock().at_level(Level::ERROR).with_fields(
- field::mock("error")
+ expect::event().at_level(Level::ERROR).with_fields(
+ expect::field("error")
// by default, errors will be emitted with their display values
.with_value(&tracing::field::display(u8::try_from(1234).unwrap_err())),
),
)
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || err().ok());
handle.assert_finished();
@@ -204,19 +229,19 @@ fn test_err_display_default() {
#[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 span = expect::span().named("error_span").with_target("my_target");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
- event::mock()
+ expect::event()
.at_level(Level::ERROR)
.with_target("my_target"),
)
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
@@ -231,3 +256,72 @@ fn test_err_custom_target() {
});
handle.assert_finished();
}
+
+#[instrument(err(level = "info"))]
+fn err_info() -> Result<u8, TryFromIntError> {
+ u8::try_from(1234)
+}
+
+#[test]
+fn test_err_info() {
+ let span = expect::span().named("err_info");
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(span.clone())
+ .enter(span.clone())
+ .event(expect::event().at_level(Level::INFO))
+ .exit(span.clone())
+ .drop_span(span)
+ .only()
+ .run_with_handle();
+ with_default(subscriber, || err_info().ok());
+ handle.assert_finished();
+}
+
+#[instrument(err(Debug, level = "info"))]
+fn err_dbg_info() -> Result<u8, TryFromIntError> {
+ u8::try_from(1234)
+}
+
+#[test]
+fn test_err_dbg_info() {
+ let span = expect::span().named("err_dbg_info");
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(span.clone())
+ .enter(span.clone())
+ .event(
+ expect::event().at_level(Level::INFO).with_fields(
+ expect::field("error")
+ // use the actual error value that will be emitted, so
+ // that this test doesn't break if the standard library
+ // changes the `fmt::Debug` output from the error type
+ // in the future.
+ .with_value(&tracing::field::debug(u8::try_from(1234).unwrap_err())),
+ ),
+ )
+ .exit(span.clone())
+ .drop_span(span)
+ .only()
+ .run_with_handle();
+ with_default(subscriber, || err_dbg_info().ok());
+ handle.assert_finished();
+}
+
+#[instrument(level = "warn", err(level = "info"))]
+fn err_warn_info() -> Result<u8, TryFromIntError> {
+ u8::try_from(1234)
+}
+
+#[test]
+fn test_err_warn_info() {
+ let span = expect::span().named("err_warn_info").at_level(Level::WARN);
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(span.clone())
+ .enter(span.clone())
+ .event(expect::event().at_level(Level::INFO))
+ .exit(span.clone())
+ .drop_span(span)
+ .only()
+ .run_with_handle();
+ with_default(subscriber, || err_warn_info().ok());
+ handle.assert_finished();
+}
diff --git a/tests/fields.rs b/tests/fields.rs
index c178fbb..a3b23d7 100644
--- a/tests/fields.rs
+++ b/tests/fields.rs
@@ -1,8 +1,6 @@
use tracing::subscriber::with_default;
use tracing_attributes::instrument;
-use tracing_mock::field::mock;
-use tracing_mock::span::NewSpan;
-use tracing_mock::*;
+use tracing_mock::{expect, span::NewSpan, subscriber};
#[instrument(fields(foo = "bar", dsa = true, num = 1))]
fn fn_no_param() {}
@@ -48,11 +46,11 @@ impl HasField {
#[test]
fn fields() {
- let span = span::mock().with_field(
- mock("foo")
+ let span = expect::span().with_field(
+ expect::field("foo")
.with_value(&"bar")
- .and(mock("dsa").with_value(&true))
- .and(mock("num").with_value(&1))
+ .and(expect::field("dsa").with_value(&true))
+ .and(expect::field("num").with_value(&1))
.only(),
);
run_test(span, || {
@@ -62,10 +60,10 @@ fn fields() {
#[test]
fn expr_field() {
- let span = span::mock().with_field(
- mock("s")
+ let span = expect::span().with_field(
+ expect::field("s")
.with_value(&"hello world")
- .and(mock("len").with_value(&"hello world".len()))
+ .and(expect::field("len").with_value(&"hello world".len()))
.only(),
);
run_test(span, || {
@@ -75,11 +73,11 @@ fn expr_field() {
#[test]
fn two_expr_fields() {
- let span = span::mock().with_field(
- mock("s")
+ let span = expect::span().with_field(
+ expect::field("s")
.with_value(&"hello world")
- .and(mock("s.len").with_value(&"hello world".len()))
- .and(mock("s.is_empty").with_value(&false))
+ .and(expect::field("s.len").with_value(&"hello world".len()))
+ .and(expect::field("s.is_empty").with_value(&false))
.only(),
);
run_test(span, || {
@@ -89,19 +87,19 @@ fn two_expr_fields() {
#[test]
fn clashy_expr_field() {
- let span = span::mock().with_field(
+ let span = expect::span().with_field(
// Overriding the `s` field should record `s` as a `Display` value,
// rather than as a `Debug` value.
- mock("s")
+ expect::field("s")
.with_value(&tracing::field::display("hello world"))
- .and(mock("s.len").with_value(&"hello world".len()))
+ .and(expect::field("s.len").with_value(&"hello world".len()))
.only(),
);
run_test(span, || {
fn_clashy_expr_field("hello world");
});
- let span = span::mock().with_field(mock("s").with_value(&"s").only());
+ let span = expect::span().with_field(expect::field("s").with_value(&"s").only());
run_test(span, || {
fn_clashy_expr_field2("hello world");
});
@@ -109,7 +107,8 @@ fn clashy_expr_field() {
#[test]
fn self_expr_field() {
- let span = span::mock().with_field(mock("my_field").with_value(&"hello world").only());
+ let span =
+ expect::span().with_field(expect::field("my_field").with_value(&"hello world").only());
run_test(span, || {
let has_field = HasField {
my_field: "hello world",
@@ -120,10 +119,10 @@ fn self_expr_field() {
#[test]
fn parameters_with_fields() {
- let span = span::mock().with_field(
- mock("foo")
+ let span = expect::span().with_field(
+ expect::field("foo")
.with_value(&"bar")
- .and(mock("param").with_value(&1u32))
+ .and(expect::field("param").with_value(&1u32))
.only(),
);
run_test(span, || {
@@ -133,7 +132,7 @@ fn parameters_with_fields() {
#[test]
fn empty_field() {
- let span = span::mock().with_field(mock("foo").with_value(&"bar").only());
+ let span = expect::span().with_field(expect::field("foo").with_value(&"bar").only());
run_test(span, || {
fn_empty_field();
});
@@ -141,7 +140,7 @@ fn empty_field() {
#[test]
fn string_field() {
- let span = span::mock().with_field(mock("s").with_value(&"hello world").only());
+ let span = expect::span().with_field(expect::field("s").with_value(&"hello world").only());
run_test(span, || {
fn_string(String::from("hello world"));
});
@@ -150,9 +149,9 @@ fn string_field() {
fn run_test<F: FnOnce() -> T, T>(span: NewSpan, fun: F) {
let (subscriber, handle) = subscriber::mock()
.new_span(span)
- .enter(span::mock())
- .exit(span::mock())
- .done()
+ .enter(expect::span())
+ .exit(expect::span())
+ .only()
.run_with_handle();
with_default(subscriber, fun);
diff --git a/tests/follows_from.rs b/tests/follows_from.rs
index da0eec6..6b5526b 100644
--- a/tests/follows_from.rs
+++ b/tests/follows_from.rs
@@ -13,10 +13,10 @@ 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 cause_a = expect::span().named("cause_a");
+ let cause_b = expect::span().named("cause_b");
+ let cause_c = expect::span().named("cause_c");
+ let consequence = expect::span().named("with_follows_from_sync");
let (subscriber, handle) = subscriber::mock()
.new_span(cause_a.clone())
@@ -28,7 +28,7 @@ fn follows_from_sync_test() {
.follows_from(consequence.clone(), cause_c)
.enter(consequence.clone())
.exit(consequence)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -44,10 +44,10 @@ fn follows_from_sync_test() {
#[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 cause_a = expect::span().named("cause_a");
+ let cause_b = expect::span().named("cause_b");
+ let cause_c = expect::span().named("cause_c");
+ let consequence = expect::span().named("with_follows_from_async");
let (subscriber, handle) = subscriber::mock()
.new_span(cause_a.clone())
@@ -58,8 +58,10 @@ fn follows_from_async_test() {
.follows_from(consequence.clone(), cause_b)
.follows_from(consequence.clone(), cause_c)
.enter(consequence.clone())
+ .exit(consequence.clone())
+ .enter(consequence.clone())
.exit(consequence)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -77,8 +79,8 @@ fn follows_from_async_test() {
#[test]
fn follows_from_current_test() {
- let cause = span::mock().named("cause");
- let consequence = span::mock().named("follows_from_current");
+ let cause = expect::span().named("cause");
+ let consequence = expect::span().named("follows_from_current");
let (subscriber, handle) = subscriber::mock()
.new_span(cause.clone())
@@ -88,7 +90,7 @@ fn follows_from_current_test() {
.enter(consequence.clone())
.exit(consequence)
.exit(cause)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
diff --git a/tests/instrument.rs b/tests/instrument.rs
index 7686927..f751eeb 100644
--- a/tests/instrument.rs
+++ b/tests/instrument.rs
@@ -17,14 +17,14 @@ 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()
+ let span = expect::span()
.named("my_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
- let span2 = span::mock()
+ let span2 = expect::span()
.named("my_other_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
@@ -37,7 +37,7 @@ fn override_everything() {
.enter(span2.clone())
.exit(span2.clone())
.drop_span(span2)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -53,21 +53,21 @@ fn fields() {
#[instrument(target = "my_target", level = "debug")]
fn my_fn(arg1: usize, arg2: bool) {}
- let span = span::mock()
+ let span = expect::span()
.named("my_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
- let span2 = span::mock()
+ let span2 = expect::span()
.named("my_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_field(
- field::mock("arg1")
+ expect::field("arg1")
.with_value(&2usize)
- .and(field::mock("arg2").with_value(&false))
+ .and(expect::field("arg2").with_value(&false))
.only(),
),
)
@@ -76,16 +76,16 @@ fn fields() {
.drop_span(span)
.new_span(
span2.clone().with_field(
- field::mock("arg1")
+ expect::field("arg1")
.with_value(&3usize)
- .and(field::mock("arg2").with_value(&true))
+ .and(expect::field("arg2").with_value(&true))
.only(),
),
)
.enter(span2.clone())
.exit(span2.clone())
.drop_span(span2)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -106,17 +106,17 @@ fn skip() {
#[instrument(target = "my_target", level = "debug", skip_all)]
fn my_fn2(_arg1: usize, _arg2: UnDebug, _arg3: UnDebug) {}
- let span = span::mock()
+ let span = expect::span()
.named("my_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
- let span2 = span::mock()
+ let span2 = expect::span()
.named("my_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
- let span3 = span::mock()
+ let span3 = expect::span()
.named("my_fn2")
.at_level(Level::DEBUG)
.with_target("my_target");
@@ -124,7 +124,7 @@ fn skip() {
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone()
- .with_field(field::mock("arg1").with_value(&2usize).only()),
+ .with_field(expect::field("arg1").with_value(&2usize).only()),
)
.enter(span.clone())
.exit(span.clone())
@@ -132,7 +132,7 @@ fn skip() {
.new_span(
span2
.clone()
- .with_field(field::mock("arg1").with_value(&3usize).only()),
+ .with_field(expect::field("arg1").with_value(&3usize).only()),
)
.enter(span2.clone())
.exit(span2.clone())
@@ -141,7 +141,7 @@ fn skip() {
.enter(span3.clone())
.exit(span3.clone())
.drop_span(span3)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -165,20 +165,20 @@ fn generics() {
{
}
- let span = span::mock().named("my_fn");
+ let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_field(
- field::mock("arg1")
+ expect::field("arg1")
.with_value(&format_args!("Foo"))
- .and(field::mock("arg2").with_value(&format_args!("false"))),
+ .and(expect::field("arg2").with_value(&format_args!("false"))),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -198,20 +198,20 @@ fn methods() {
fn my_fn(&self, arg1: usize) {}
}
- let span = span::mock().named("my_fn");
+ let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_field(
- field::mock("self")
+ expect::field("self")
.with_value(&format_args!("Foo"))
- .and(field::mock("arg1").with_value(&42usize)),
+ .and(expect::field("arg1").with_value(&42usize)),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -229,17 +229,17 @@ fn impl_trait_return_type() {
0..x
}
- let span = span::mock().named("returns_impl_trait");
+ let span = expect::span().named("returns_impl_trait");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone()
- .with_field(field::mock("x").with_value(&10usize).only()),
+ .with_field(expect::field("x").with_value(&10usize).only()),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
diff --git a/tests/levels.rs b/tests/levels.rs
index b074ea4..ed80dc1 100644
--- a/tests/levels.rs
+++ b/tests/levels.rs
@@ -20,22 +20,22 @@ fn named_levels() {
#[instrument(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()
+ .new_span(expect::span().named("trace").at_level(Level::TRACE))
+ .enter(expect::span().named("trace").at_level(Level::TRACE))
+ .exit(expect::span().named("trace").at_level(Level::TRACE))
+ .new_span(expect::span().named("debug").at_level(Level::DEBUG))
+ .enter(expect::span().named("debug").at_level(Level::DEBUG))
+ .exit(expect::span().named("debug").at_level(Level::DEBUG))
+ .new_span(expect::span().named("info").at_level(Level::INFO))
+ .enter(expect::span().named("info").at_level(Level::INFO))
+ .exit(expect::span().named("info").at_level(Level::INFO))
+ .new_span(expect::span().named("warn").at_level(Level::WARN))
+ .enter(expect::span().named("warn").at_level(Level::WARN))
+ .exit(expect::span().named("warn").at_level(Level::WARN))
+ .new_span(expect::span().named("error").at_level(Level::ERROR))
+ .enter(expect::span().named("error").at_level(Level::ERROR))
+ .exit(expect::span().named("error").at_level(Level::ERROR))
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -66,22 +66,68 @@ fn numeric_levels() {
#[instrument(level = 5)]
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()
+ .new_span(expect::span().named("trace").at_level(Level::TRACE))
+ .enter(expect::span().named("trace").at_level(Level::TRACE))
+ .exit(expect::span().named("trace").at_level(Level::TRACE))
+ .new_span(expect::span().named("debug").at_level(Level::DEBUG))
+ .enter(expect::span().named("debug").at_level(Level::DEBUG))
+ .exit(expect::span().named("debug").at_level(Level::DEBUG))
+ .new_span(expect::span().named("info").at_level(Level::INFO))
+ .enter(expect::span().named("info").at_level(Level::INFO))
+ .exit(expect::span().named("info").at_level(Level::INFO))
+ .new_span(expect::span().named("warn").at_level(Level::WARN))
+ .enter(expect::span().named("warn").at_level(Level::WARN))
+ .exit(expect::span().named("warn").at_level(Level::WARN))
+ .new_span(expect::span().named("error").at_level(Level::ERROR))
+ .enter(expect::span().named("error").at_level(Level::ERROR))
+ .exit(expect::span().named("error").at_level(Level::ERROR))
+ .only()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ trace();
+ debug();
+ info();
+ warn();
+ error();
+ });
+
+ 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(expect::span().named("trace").at_level(Level::TRACE))
+ .enter(expect::span().named("trace").at_level(Level::TRACE))
+ .exit(expect::span().named("trace").at_level(Level::TRACE))
+ .new_span(expect::span().named("debug").at_level(Level::DEBUG))
+ .enter(expect::span().named("debug").at_level(Level::DEBUG))
+ .exit(expect::span().named("debug").at_level(Level::DEBUG))
+ .new_span(expect::span().named("info").at_level(Level::INFO))
+ .enter(expect::span().named("info").at_level(Level::INFO))
+ .exit(expect::span().named("info").at_level(Level::INFO))
+ .new_span(expect::span().named("warn").at_level(Level::WARN))
+ .enter(expect::span().named("warn").at_level(Level::WARN))
+ .exit(expect::span().named("warn").at_level(Level::WARN))
+ .new_span(expect::span().named("error").at_level(Level::ERROR))
+ .enter(expect::span().named("error").at_level(Level::ERROR))
+ .exit(expect::span().named("error").at_level(Level::ERROR))
+ .only()
.run_with_handle();
with_default(subscriber, || {
diff --git a/tests/names.rs b/tests/names.rs
index d97dece..03e3dbf 100644
--- a/tests/names.rs
+++ b/tests/names.rs
@@ -17,10 +17,10 @@ fn custom_name_no_equals() {}
#[test]
fn default_name_test() {
let (subscriber, handle) = subscriber::mock()
- .new_span(span::mock().named("default_name"))
- .enter(span::mock().named("default_name"))
- .exit(span::mock().named("default_name"))
- .done()
+ .new_span(expect::span().named("default_name"))
+ .enter(expect::span().named("default_name"))
+ .exit(expect::span().named("default_name"))
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -33,10 +33,10 @@ fn default_name_test() {
#[test]
fn custom_name_test() {
let (subscriber, handle) = subscriber::mock()
- .new_span(span::mock().named("my_name"))
- .enter(span::mock().named("my_name"))
- .exit(span::mock().named("my_name"))
- .done()
+ .new_span(expect::span().named("my_name"))
+ .enter(expect::span().named("my_name"))
+ .exit(expect::span().named("my_name"))
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -49,10 +49,10 @@ fn custom_name_test() {
#[test]
fn custom_name_no_equals_test() {
let (subscriber, handle) = subscriber::mock()
- .new_span(span::mock().named("my_other_name"))
- .enter(span::mock().named("my_other_name"))
- .exit(span::mock().named("my_other_name"))
- .done()
+ .new_span(expect::span().named("my_other_name"))
+ .enter(expect::span().named("my_other_name"))
+ .exit(expect::span().named("my_other_name"))
+ .only()
.run_with_handle();
with_default(subscriber, || {
diff --git a/tests/parents.rs b/tests/parents.rs
index 7069b98..d455941 100644
--- a/tests/parents.rs
+++ b/tests/parents.rs
@@ -14,8 +14,8 @@ where
#[test]
fn default_parent_test() {
- let contextual_parent = span::mock().named("contextual_parent");
- let child = span::mock().named("with_default_parent");
+ let contextual_parent = expect::span().named("contextual_parent");
+ let child = expect::span().named("with_default_parent");
let (subscriber, handle) = subscriber::mock()
.new_span(
@@ -42,7 +42,7 @@ fn default_parent_test() {
.enter(child.clone())
.exit(child)
.exit(contextual_parent)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -60,9 +60,9 @@ fn default_parent_test() {
#[test]
fn explicit_parent_test() {
- let contextual_parent = span::mock().named("contextual_parent");
- let explicit_parent = span::mock().named("explicit_parent");
- let child = span::mock().named("with_explicit_parent");
+ let contextual_parent = expect::span().named("contextual_parent");
+ let explicit_parent = expect::span().named("explicit_parent");
+ let child = expect::span().named("with_explicit_parent");
let (subscriber, handle) = subscriber::mock()
.new_span(
@@ -86,7 +86,7 @@ fn explicit_parent_test() {
.enter(child.clone())
.exit(child)
.exit(contextual_parent)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
diff --git a/tests/ret.rs b/tests/ret.rs
index cfd2de1..90bd9e1 100644
--- a/tests/ret.rs
+++ b/tests/ret.rs
@@ -19,18 +19,18 @@ fn ret_with_target() -> i32 {
#[test]
fn test() {
- let span = span::mock().named("ret");
+ let span = expect::span().named("ret");
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)))
+ expect::event()
+ .with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::INFO),
)
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, ret);
@@ -40,7 +40,7 @@ fn test() {
#[test]
fn test_custom_target() {
let filter: EnvFilter = "my_target=info".parse().expect("filter should parse");
- let span = span::mock()
+ let span = expect::span()
.named("ret_with_target")
.with_target("my_target");
@@ -48,14 +48,14 @@ fn test_custom_target() {
.new_span(span.clone())
.enter(span.clone())
.event(
- event::mock()
- .with_fields(field::mock("return").with_value(&tracing::field::debug(42)))
+ expect::event()
+ .with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::INFO)
.with_target("my_target"),
)
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
let subscriber = subscriber.with(filter);
@@ -71,18 +71,18 @@ fn ret_warn() -> i32 {
#[test]
fn test_warn() {
- let span = span::mock().named("ret_warn");
+ let span = expect::span().named("ret_warn");
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)))
+ expect::event()
+ .with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::WARN),
)
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, ret_warn);
@@ -98,23 +98,23 @@ fn ret_mut(a: &mut i32) -> i32 {
#[test]
fn test_mut() {
- let span = span::mock().named("ret_mut");
+ let span = expect::span().named("ret_mut");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
- event::mock()
- .with_fields(field::mock("a").with_value(&tracing::field::display(2)))
+ expect::event()
+ .with_fields(expect::field("a").with_value(&tracing::field::display(2)))
.at_level(Level::INFO),
)
.event(
- event::mock()
- .with_fields(field::mock("return").with_value(&tracing::field::debug(2)))
+ expect::event()
+ .with_fields(expect::field("return").with_value(&tracing::field::debug(2)))
.at_level(Level::INFO),
)
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || ret_mut(&mut 1));
@@ -128,18 +128,20 @@ async fn ret_async() -> i32 {
#[test]
fn test_async() {
- let span = span::mock().named("ret_async");
+ let span = expect::span().named("ret_async");
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)))
+ expect::event()
+ .with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::INFO),
)
.exit(span.clone())
+ .enter(span.clone())
+ .exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || block_on_future(async { ret_async().await }));
@@ -153,18 +155,18 @@ fn ret_impl_type() -> impl Copy {
#[test]
fn test_impl_type() {
- let span = span::mock().named("ret_impl_type");
+ let span = expect::span().named("ret_impl_type");
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)))
+ expect::event()
+ .with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::INFO),
)
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, ret_impl_type);
@@ -178,18 +180,18 @@ fn ret_display() -> i32 {
#[test]
fn test_dbg() {
- let span = span::mock().named("ret_display");
+ let span = expect::span().named("ret_display");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
- event::mock()
- .with_fields(field::mock("return").with_value(&tracing::field::display(42)))
+ expect::event()
+ .with_fields(expect::field("return").with_value(&tracing::field::display(42)))
.at_level(Level::INFO),
)
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, ret_display);
@@ -203,14 +205,14 @@ fn ret_and_err() -> Result<u8, TryFromIntError> {
#[test]
fn test_ret_and_err() {
- let span = span::mock().named("ret_and_err");
+ let span = expect::span().named("ret_and_err");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
- event::mock()
+ expect::event()
.with_fields(
- field::mock("error")
+ expect::field("error")
.with_value(&tracing::field::display(u8::try_from(1234).unwrap_err()))
.only(),
)
@@ -218,7 +220,7 @@ fn test_ret_and_err() {
)
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || ret_and_err().ok());
@@ -232,14 +234,14 @@ fn ret_and_ok() -> Result<u8, TryFromIntError> {
#[test]
fn test_ret_and_ok() {
- let span = span::mock().named("ret_and_ok");
+ let span = expect::span().named("ret_and_ok");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
- event::mock()
+ expect::event()
.with_fields(
- field::mock("return")
+ expect::field("return")
.with_value(&tracing::field::debug(u8::try_from(123).unwrap()))
.only(),
)
@@ -247,9 +249,59 @@ fn test_ret_and_ok() {
)
.exit(span.clone())
.drop_span(span)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || ret_and_ok().ok());
handle.assert_finished();
}
+
+#[instrument(level = "warn", ret(level = "info"))]
+fn ret_warn_info() -> i32 {
+ 42
+}
+
+#[test]
+fn test_warn_info() {
+ let span = expect::span().named("ret_warn_info").at_level(Level::WARN);
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(span.clone())
+ .enter(span.clone())
+ .event(
+ expect::event()
+ .with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
+ .at_level(Level::INFO),
+ )
+ .exit(span.clone())
+ .drop_span(span)
+ .only()
+ .run_with_handle();
+
+ with_default(subscriber, ret_warn_info);
+ handle.assert_finished();
+}
+
+#[instrument(ret(level = "warn", Debug))]
+fn ret_dbg_warn() -> i32 {
+ 42
+}
+
+#[test]
+fn test_dbg_warn() {
+ let span = expect::span().named("ret_dbg_warn").at_level(Level::INFO);
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(span.clone())
+ .enter(span.clone())
+ .event(
+ expect::event()
+ .with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
+ .at_level(Level::WARN),
+ )
+ .exit(span.clone())
+ .drop_span(span)
+ .only()
+ .run_with_handle();
+
+ with_default(subscriber, ret_dbg_warn);
+ handle.assert_finished();
+}
diff --git a/tests/targets.rs b/tests/targets.rs
index 363f628..0e70287 100644
--- a/tests/targets.rs
+++ b/tests/targets.rs
@@ -24,36 +24,36 @@ mod my_mod {
fn default_targets() {
let (subscriber, handle) = subscriber::mock()
.new_span(
- span::mock()
+ expect::span()
.named("default_target")
.with_target(module_path!()),
)
.enter(
- span::mock()
+ expect::span()
.named("default_target")
.with_target(module_path!()),
)
.exit(
- span::mock()
+ expect::span()
.named("default_target")
.with_target(module_path!()),
)
.new_span(
- span::mock()
+ expect::span()
.named("default_target")
.with_target(my_mod::MODULE_PATH),
)
.enter(
- span::mock()
+ expect::span()
.named("default_target")
.with_target(my_mod::MODULE_PATH),
)
.exit(
- span::mock()
+ expect::span()
.named("default_target")
.with_target(my_mod::MODULE_PATH),
)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
@@ -67,25 +67,37 @@ fn default_targets() {
#[test]
fn custom_targets() {
let (subscriber, handle) = subscriber::mock()
- .new_span(span::mock().named("custom_target").with_target("my_target"))
- .enter(span::mock().named("custom_target").with_target("my_target"))
- .exit(span::mock().named("custom_target").with_target("my_target"))
.new_span(
- span::mock()
+ expect::span()
+ .named("custom_target")
+ .with_target("my_target"),
+ )
+ .enter(
+ expect::span()
+ .named("custom_target")
+ .with_target("my_target"),
+ )
+ .exit(
+ expect::span()
+ .named("custom_target")
+ .with_target("my_target"),
+ )
+ .new_span(
+ expect::span()
.named("custom_target")
.with_target("my_other_target"),
)
.enter(
- span::mock()
+ expect::span()
.named("custom_target")
.with_target("my_other_target"),
)
.exit(
- span::mock()
+ expect::span()
.named("custom_target")
.with_target("my_other_target"),
)
- .done()
+ .only()
.run_with_handle();
with_default(subscriber, || {
diff --git a/tests/ui.rs b/tests/ui.rs
index f11cc01..73d7fdc 100644
--- a/tests/ui.rs
+++ b/tests/ui.rs
@@ -5,3 +5,10 @@ fn async_instrument() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/async_instrument.rs");
}
+
+#[rustversion::stable]
+#[test]
+fn const_instrument() {
+ let t = trybuild::TestCases::new();
+ t.compile_fail("tests/ui/const_instrument.rs");
+}
diff --git a/tests/ui/async_instrument.stderr b/tests/ui/async_instrument.stderr
index db6f6b4..2c64b0c 100644
--- a/tests/ui/async_instrument.stderr
+++ b/tests/ui/async_instrument.stderr
@@ -16,7 +16,7 @@ error[E0308]: mismatched types
10 | ""
| ^^- help: try using a conversion method: `.to_string()`
| |
- | expected struct `String`, found `&str`
+ | expected `String`, found `&str`
|
note: return type inferred to be `String` here
--> tests/ui/async_instrument.rs:9:31
@@ -47,7 +47,7 @@ error[E0308]: mismatched types
--> tests/ui/async_instrument.rs:23:5
|
23 | ""
- | ^^ expected struct `Wrapper`, found `&str`
+ | ^^ expected `Wrapper<_>`, found `&str`
|
= note: expected struct `Wrapper<_>`
found reference `&'static str`
@@ -79,7 +79,7 @@ error[E0308]: mismatched types
36 | return "";
| ^^- help: try using a conversion method: `.to_string()`
| |
- | expected struct `String`, found `&str`
+ | expected `String`, found `&str`
|
note: return type inferred to be `String` here
--> tests/ui/async_instrument.rs:34:28
@@ -93,6 +93,6 @@ error[E0308]: mismatched types
42 | async fn extra_semicolon() -> i32 {
| ___________________________________^
43 | | 1;
- | | - help: remove this semicolon
+ | | - help: remove this semicolon to return this value
44 | | }
| |_^ expected `i32`, found `()`
diff --git a/tests/ui/const_instrument.rs b/tests/ui/const_instrument.rs
new file mode 100644
index 0000000..a251e8f
--- /dev/null
+++ b/tests/ui/const_instrument.rs
@@ -0,0 +1,8 @@
+#![allow(unreachable_code)]
+
+#[tracing::instrument]
+const fn unit() {
+ ""
+}
+
+fn main() {}
diff --git a/tests/ui/const_instrument.stderr b/tests/ui/const_instrument.stderr
new file mode 100644
index 0000000..e76d4ac
--- /dev/null
+++ b/tests/ui/const_instrument.stderr
@@ -0,0 +1,15 @@
+error: macros that expand to items must be delimited with braces or followed by a semicolon
+ --> tests/ui/const_instrument.rs:3:1
+ |
+3 | #[tracing::instrument]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the attribute macro `tracing::instrument` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: the `#[instrument]` attribute may not be used with `const fn`s
+ --> tests/ui/const_instrument.rs:3:1
+ |
+3 | #[tracing::instrument]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the attribute macro `tracing::instrument` (in Nightly builds, run with -Z macro-backtrace for more info)