Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/tracing-attributes/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/tracing-attributes/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"CHANGELOG.md":"e410a2cbd565bff62c52c66580bd3c7aa9bd81e4b73b5f4cdd0f7c5ab13b21de","Cargo.toml":"2cb782a6b7cb5412591a8457af156d081514ae846a81bec889a9f60f68a39dca","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"d878157a8f65779ef3d2e53d6772f99b5b79d7addccb6d04a2eb681ce1de99e1","src/attr.rs":"d0224a2a9be76743f039c86c1935622ca0b5b2e618b9323149855bf0e326fe48","src/expand.rs":"548b8d5fb5e92fe57a067bb656b88ceb403234521eed8bce4e0ec91b5fdacf78","src/lib.rs":"de2409d2cefba7a21739ac1021ea8e0dec892a342b1ecb46a81f66b782ea8f5b","tests/async_fn.rs":"66dab5e2a58119f588daae74efa47b5d8db0751cb99660856d792f352a3a263e","tests/destructuring.rs":"d920dca0b7db5b48697c1eb5a40ce676956760eb8bc2dcbe4c5ce1bc3631877b","tests/err.rs":"6b717be09a2447bcb0583a9b6a42b53361935b4a61093572c55f506f9d5f5cff","tests/fields.rs":"8babe90df46cfe9018caf20ef85060c90d611c5531b4d603f10f83a38744e7c2","tests/follows_from.rs":"d0478db45cb838d76f0d52f930847e8540b09456e2cd56591e56910c5e9985c6","tests/instrument.rs":"0c47bd9117858ecc585faab597115b7b49e2c79ae20172c32a6184674c8fd274","tests/levels.rs":"20483e9c7555991044b748f209def016d28da0a64eb9f85fabb489b0fb75a440","tests/names.rs":"2a67b33681cc7689c4d677de7a97b846df1817406a56a98ba91bf67b9f7d630a","tests/parents.rs":"95451328d8d7dba9020dc3eeb4ee56fc7f4591d5d38e793b815e621e73063da1","tests/ret.rs":"4628f562f8b0fb36a0dc13f488d70df8a545bd9b49422dfbf05fd2cab3870fc3","tests/targets.rs":"2065af7ff491be720c56d1b218b095a64e4573bf2586e49ce638c5ed4d639811","tests/ui.rs":"60ed69aba2cbf4b1a2f42b78703f7f21d8a69f62e39bb0509f6a2224cad9b9de","tests/ui/async_instrument.rs":"00fcde05841e8f9f6cc6f9434f8cc4baed5cf6e3ca73e8faddccbdace14e9485","tests/ui/async_instrument.stderr":"1d650a0914f0f59beeb88946a8ad6991feffe885016462ba917ea8e09792f866","tests/ui/const_instrument.rs":"253160848b023cbf73c3d1dece4969ff892ae9a3149e771159230733fa1cab1b","tests/ui/const_instrument.stderr":"86527fbc2410ceba8f051771fdb4bf71eb853e086a4e4d17353089c65b918c18"},"package":"34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"}
|
||||
420
third-party/vendor/tracing-attributes/CHANGELOG.md
vendored
Normal file
420
third-party/vendor/tracing-attributes/CHANGELOG.md
vendored
Normal file
|
|
@ -0,0 +1,420 @@
|
|||
# 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
|
||||
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])
|
||||
- Add fake return to improve spans generated for type errors in `async fn`s ([#2270])
|
||||
- Updated `syn` dependency to fix compilation with `-Z minimal-versions`
|
||||
([#2246])
|
||||
|
||||
Thanks to new contributors @compiler-errors and @e-nomem, as well as @CAD97, for
|
||||
contributing to this release!
|
||||
|
||||
[#2307]: https://github.com/tokio-rs/tracing/pull/2307
|
||||
[#2270]: https://github.com/tokio-rs/tracing/pull/2270
|
||||
[#2246]: https://github.com/tokio-rs/tracing/pull/2246
|
||||
|
||||
# 0.1.22 (July 1, 2022)
|
||||
|
||||
This release fixes an issue where using the `err` or `ret` arguments to
|
||||
`#[instrument]` along with an overridden target, such as
|
||||
|
||||
```rust
|
||||
#[instrument(target = "...", err, ret)]
|
||||
```
|
||||
|
||||
would not propagate the overridden target to the events generated for
|
||||
errors/return values.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Error and return value events generated by `#[instrument(err)]` or
|
||||
`#[instrument(ret)]` not inheriting an overridden target ([#2184])
|
||||
- Incorrect default level in documentation ([#2119])
|
||||
|
||||
Thanks to new contributor @tbraun96 for contributing to this release!
|
||||
|
||||
[#2184]: https://github.com/tokio-rs/tracing/pull/2184
|
||||
[#2119]: https://github.com/tokio-rs/tracing/pull/2119
|
||||
|
||||
# 0.1.21 (April 26, 2022)
|
||||
|
||||
This release adds support for setting explicit parent and follows-from spans
|
||||
in the `#[instrument]` attribute.
|
||||
|
||||
### Added
|
||||
|
||||
- `#[instrument(follows_from = ...)]` argument for setting one or more
|
||||
follows-from span ([#2093])
|
||||
- `#[instrument(parent = ...)]` argument for overriding the generated span's
|
||||
parent ([#2091])
|
||||
|
||||
### Fixed
|
||||
|
||||
- Extra braces around `async` blocks in expanded code (causes a Clippy warning)
|
||||
([#2090])
|
||||
- Broken documentation links ([#2068], [#2077])
|
||||
|
||||
Thanks to @jarrodldavis, @ben0x539, and new contributor @jswrenn for
|
||||
contributing to this release!
|
||||
|
||||
|
||||
[#2093]: https://github.com/tokio-rs/tracing/pull/2093
|
||||
[#2091]: https://github.com/tokio-rs/tracing/pull/2091
|
||||
[#2090]: https://github.com/tokio-rs/tracing/pull/2090
|
||||
[#2077]: https://github.com/tokio-rs/tracing/pull/2077
|
||||
[#2068]: https://github.com/tokio-rs/tracing/pull/2068
|
||||
|
||||
# 0.1.20 (March 8, 2022)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Compilation failure with `--minimal-versions` due to a too-permissive `syn`
|
||||
dependency ([#1960])
|
||||
|
||||
### Changed
|
||||
|
||||
- Bumped minimum supported Rust version (MSRV) to 1.49.0 ([#1913])
|
||||
|
||||
Thanks to new contributor @udoprog for contributing to this release!
|
||||
|
||||
[#1960]: https://github.com/tokio-rs/tracing/pull/1960
|
||||
[#1913]: https://github.com/tokio-rs/tracing/pull/1913
|
||||
|
||||
# 0.1.19 (February 3, 2022)
|
||||
|
||||
This release introduces a new `#[instrument(ret)]` argument to emit an event
|
||||
with the return value of an instrumented function.
|
||||
|
||||
### Added
|
||||
|
||||
- `#[instrument(ret)]` to record the return value of a function ([#1716])
|
||||
- added `err(Debug)` argument to cause `#[instrument(err)]` to record errors
|
||||
with `Debug` rather than `Display ([#1631])
|
||||
|
||||
### Fixed
|
||||
|
||||
- incorrect code generation for functions returning async blocks ([#1866])
|
||||
- incorrect diagnostics when using `rust-analyzer` ([#1634])
|
||||
|
||||
Thanks to @Swatinem, @hkmatsumoto, @cynecx, and @ciuncan for contributing to
|
||||
this release!
|
||||
|
||||
[#1716]: https://github.com/tokio-rs/tracing/pull/1716
|
||||
[#1631]: https://github.com/tokio-rs/tracing/pull/1631
|
||||
[#1634]: https://github.com/tokio-rs/tracing/pull/1634
|
||||
[#1866]: https://github.com/tokio-rs/tracing/pull/1866
|
||||
|
||||
# 0.1.18 (October 5, 2021)
|
||||
|
||||
This release fixes issues introduced in v0.1.17.
|
||||
|
||||
### Fixed
|
||||
|
||||
- fixed mismatched types compiler error that may occur when using
|
||||
`#[instrument]` on an `async fn` that returns an `impl Trait` value that
|
||||
includes a closure ([#1616])
|
||||
- fixed false positives for `clippy::suspicious_else_formatting` warnings due to
|
||||
rust-lang/rust-clippy#7760 and rust-lang/rust-clippy#6249 ([#1617])
|
||||
- fixed `clippy::let_unit_value` lints when using `#[instrument]` ([#1614])
|
||||
|
||||
[#1617]: https://github.com/tokio-rs/tracing/pull/1617
|
||||
[#1616]: https://github.com/tokio-rs/tracing/pull/1616
|
||||
[#1614]: https://github.com/tokio-rs/tracing/pull/1614
|
||||
|
||||
# 0.1.17 (YANKED) (October 1, 2021)
|
||||
|
||||
This release significantly improves performance when `#[instrument]`-generated
|
||||
spans are below the maximum enabled level.
|
||||
|
||||
### Added
|
||||
|
||||
- improve performance when skipping `#[instrument]`-generated spans below the
|
||||
max level ([#1600], [#1605])
|
||||
|
||||
Thanks to @oli-obk for contributing to this release!
|
||||
|
||||
[#1600]: https://github.com/tokio-rs/tracing/pull/1600
|
||||
[#1605]: https://github.com/tokio-rs/tracing/pull/1605
|
||||
|
||||
# 0.1.16 (September 13, 2021)
|
||||
|
||||
This release adds a new `#[instrument(skip_all)]` option to skip recording *all*
|
||||
arguments to an instrumented function as fields. Additionally, it adds support
|
||||
for recording arguments that are `tracing` primitive types as typed values,
|
||||
rather than as `fmt::Debug`.
|
||||
|
||||
### Added
|
||||
|
||||
- add `skip_all` option to `#[instrument]` ([#1548])
|
||||
- record primitive types as primitive values rather than as `fmt::Debug`
|
||||
([#1378])
|
||||
- added support for `f64`s as typed values ([#1522])
|
||||
|
||||
Thanks to @Folyd and @jsgf for contributing to this release!
|
||||
|
||||
[#1548]: https://github.com/tokio-rs/tracing/pull/1548
|
||||
[#1378]: https://github.com/tokio-rs/tracing/pull/1378
|
||||
[#1522]: https://github.com/tokio-rs/tracing/pull/1524
|
||||
|
||||
# 0.1.15 (March 12, 2021)
|
||||
|
||||
### Fixed
|
||||
|
||||
- `#[instrument]` on functions returning `Box::pin`ned futures incorrectly
|
||||
skipping function bodies prior to returning a future ([#1297])
|
||||
|
||||
Thanks to @nightmared for contributing to this release!
|
||||
|
||||
[#1297]: https://github.com/tokio-rs/tracing/pull/1297
|
||||
|
||||
# 0.1.14 (March 10, 2021)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Compatibility between `#[instrument]` and `async-trait` v0.1.43 and newer
|
||||
([#1228])
|
||||
|
||||
Thanks to @nightmared for lots of hard work on this fix!
|
||||
|
||||
[#1228]: https://github.com/tokio-rs/tracing/pull/1228
|
||||
|
||||
# 0.1.13 (February 17, 2021)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Compiler error when using `#[instrument(err)]` on functions which return `impl
|
||||
Trait` ([#1236])
|
||||
|
||||
[#1236]: https://github.com/tokio-rs/tracing/pull/1236
|
||||
|
||||
# 0.1.12 (February 4, 2021)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Compiler error when using `#[instrument(err)]` on functions with mutable
|
||||
parameters ([#1167])
|
||||
- Missing function visibility modifier when using `#[instrument]` with
|
||||
`async-trait` ([#977])
|
||||
- Multiple documentation fixes and improvements ([#965], [#981], [#1215])
|
||||
|
||||
### Changed
|
||||
|
||||
- `tracing-futures` dependency is no longer required when using `#[instrument]`
|
||||
on async functions ([#808])
|
||||
|
||||
Thanks to @nagisa, @Txuritan, @TaKO8Ki, and @okready for contributing to this
|
||||
release!
|
||||
|
||||
[#1167]: https://github.com/tokio-rs/tracing/pull/1167
|
||||
[#977]: https://github.com/tokio-rs/tracing/pull/977
|
||||
[#965]: https://github.com/tokio-rs/tracing/pull/965
|
||||
[#981]: https://github.com/tokio-rs/tracing/pull/981
|
||||
[#1215]: https://github.com/tokio-rs/tracing/pull/1215
|
||||
[#808]: https://github.com/tokio-rs/tracing/pull/808
|
||||
|
||||
# 0.1.11 (August 18, 2020)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Corrected wrong minimum supported Rust version note in docs (#941)
|
||||
- Removed unused `syn` features (#928)
|
||||
|
||||
Thanks to new contributor @jhpratt for contributing to this release!
|
||||
|
||||
# 0.1.10 (August 10, 2020)
|
||||
|
||||
### Added
|
||||
|
||||
- Support for using `self` in field expressions when instrumenting `async-trait`
|
||||
functions (#875)
|
||||
- Several documentation improvements (#832, #897, #911, #913)
|
||||
|
||||
Thanks to @anton-dutov and @nightmared for contributing to this release!
|
||||
|
||||
# 0.1.9 (July 8, 2020)
|
||||
|
||||
### Added
|
||||
|
||||
- Support for arbitrary expressions as fields in `#[instrument]` (#672)
|
||||
|
||||
### Changed
|
||||
|
||||
- `#[instrument]` now emits a compiler warning when ignoring unrecognized
|
||||
input (#672, #786)
|
||||
|
||||
# 0.1.8 (May 13, 2020)
|
||||
|
||||
### Added
|
||||
|
||||
- Support for using `#[instrument]` on methods that are part of [`async-trait`]
|
||||
trait implementations (#711)
|
||||
- Optional `#[instrument(err)]` argument to automatically emit an event if an
|
||||
instrumented function returns `Err` (#637)
|
||||
|
||||
Thanks to @ilana and @nightmared for contributing to this release!
|
||||
|
||||
[`async-trait`]: https://crates.io/crates/async-trait
|
||||
|
||||
# 0.1.7 (February 26, 2020)
|
||||
|
||||
### Added
|
||||
|
||||
- Support for adding arbitrary literal fields to spans generated by
|
||||
`#[instrument]` (#569)
|
||||
- `#[instrument]` now emits a helpful compiler error when attempting to skip a
|
||||
function parameter (#600)
|
||||
|
||||
Thanks to @Kobzol for contributing to this release!
|
||||
|
||||
# 0.1.6 (December 20, 2019)
|
||||
|
||||
### Added
|
||||
|
||||
- Updated documentation (#468)
|
||||
|
||||
# 0.1.5 (October 22, 2019)
|
||||
|
||||
### Added
|
||||
|
||||
- Support for destructuring in arguments to `#[instrument]`ed functions (#397)
|
||||
- Generated field for `self` parameters when `#[instrument]`ing methods (#397)
|
||||
|
||||
# 0.1.4 (September 26, 2019)
|
||||
|
||||
### Added
|
||||
|
||||
- Optional `skip` argument to `#[instrument]` for excluding function parameters
|
||||
from generated spans (#359)
|
||||
|
||||
# 0.1.3 (September 12, 2019)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `#[instrument]`ed async functions not compiling on `nightly-2019-09-11`
|
||||
or newer (#342)
|
||||
|
||||
# 0.1.2 (August 19, 2019)
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated `syn` and `quote` dependencies to 1.0 (#292)
|
||||
- Removed direct dependency on `proc-macro2` to avoid potential version
|
||||
conflicts (#296)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Outdated idioms in examples (#271, #273)
|
||||
|
||||
# 0.1.1 (August 9, 2019)
|
||||
|
||||
### Changed
|
||||
|
||||
- Using the `#[instrument]` attribute on `async fn`s no longer requires a
|
||||
feature flag (#258)
|
||||
|
||||
### Fixed
|
||||
|
||||
- The `#[instrument]` macro now works on generic functions (#262)
|
||||
|
||||
# 0.1.0 (August 8, 2019)
|
||||
|
||||
- Initial release
|
||||
87
third-party/vendor/tracing-attributes/Cargo.toml
vendored
Normal file
87
third-party/vendor/tracing-attributes/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
rust-version = "1.56.0"
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.27"
|
||||
authors = [
|
||||
"Tokio Contributors <team@tokio.rs>",
|
||||
"Eliza Weisman <eliza@buoyant.io>",
|
||||
"David Barsky <dbarsky@amazon.com>",
|
||||
]
|
||||
description = """
|
||||
Procedural macro attributes for automatically instrumenting functions.
|
||||
"""
|
||||
homepage = "https://tokio.rs"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"logging",
|
||||
"tracing",
|
||||
"macro",
|
||||
"instrument",
|
||||
"log",
|
||||
]
|
||||
categories = [
|
||||
"development-tools::debugging",
|
||||
"development-tools::profiling",
|
||||
"asynchronous",
|
||||
]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/tokio-rs/tracing"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies.proc-macro2]
|
||||
version = "1.0.60"
|
||||
|
||||
[dependencies.quote]
|
||||
version = "1.0.20"
|
||||
|
||||
[dependencies.syn]
|
||||
version = "2.0"
|
||||
features = [
|
||||
"full",
|
||||
"parsing",
|
||||
"printing",
|
||||
"visit-mut",
|
||||
"clone-impls",
|
||||
"extra-traits",
|
||||
"proc-macro",
|
||||
]
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.async-trait]
|
||||
version = "0.1.67"
|
||||
|
||||
[dev-dependencies.rustversion]
|
||||
version = "1.0.9"
|
||||
|
||||
[dev-dependencies.tokio-test]
|
||||
version = "0.4.2"
|
||||
|
||||
[dev-dependencies.tracing]
|
||||
version = "0.1.35"
|
||||
|
||||
[dev-dependencies.tracing-subscriber]
|
||||
version = "0.3.0"
|
||||
features = ["env-filter"]
|
||||
|
||||
[dev-dependencies.trybuild]
|
||||
version = "1.0.64"
|
||||
|
||||
[features]
|
||||
async-await = []
|
||||
|
||||
[badges.maintenance]
|
||||
status = "experimental"
|
||||
25
third-party/vendor/tracing-attributes/LICENSE
vendored
Normal file
25
third-party/vendor/tracing-attributes/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2019 Tokio Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
91
third-party/vendor/tracing-attributes/README.md
vendored
Normal file
91
third-party/vendor/tracing-attributes/README.md
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
![Tracing — Structured, application-level diagnostics][splash]
|
||||
|
||||
[splash]: https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/splash.svg
|
||||
|
||||
# tracing-attributes
|
||||
|
||||
Macro attributes for application-level tracing.
|
||||
|
||||
[![Crates.io][crates-badge]][crates-url]
|
||||
[![Documentation][docs-badge]][docs-url]
|
||||
[![Documentation (master)][docs-master-badge]][docs-master-url]
|
||||
[![MIT licensed][mit-badge]][mit-url]
|
||||
[![Build Status][actions-badge]][actions-url]
|
||||
[![Discord chat][discord-badge]][discord-url]
|
||||
|
||||
[Documentation][docs-url] | [Chat][discord-url]
|
||||
|
||||
[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.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
|
||||
[mit-url]: LICENSE
|
||||
[actions-badge]: https://github.com/tokio-rs/tracing/workflows/CI/badge.svg
|
||||
[actions-url]:https://github.com/tokio-rs/tracing/actions?query=workflow%3ACI
|
||||
[discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white
|
||||
[discord-url]: https://discord.gg/EeF3cQw
|
||||
|
||||
## Overview
|
||||
|
||||
[`tracing`] is a framework for instrumenting Rust programs to collect
|
||||
structured, event-based diagnostic information. This crate provides the
|
||||
`#[instrument]` attribute for automatically instrumenting functions using
|
||||
`tracing`.
|
||||
|
||||
Note that this macro is also re-exported by the main `tracing` crate.
|
||||
|
||||
*Compiler support: [requires `rustc` 1.56+][msrv]*
|
||||
|
||||
[msrv]: #supported-rust-versions
|
||||
|
||||
## Usage
|
||||
|
||||
First, add this to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
tracing-attributes = "0.1.26"
|
||||
```
|
||||
|
||||
|
||||
This crate provides the `#[instrument]` attribute for instrumenting a function
|
||||
with a `tracing` [span]. For example:
|
||||
|
||||
```rust
|
||||
use tracing_attributes::instrument;
|
||||
|
||||
#[instrument]
|
||||
pub fn my_function(my_arg: usize) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
[`tracing`]: https://crates.io/crates/tracing
|
||||
[span]: https://docs.rs/tracing/latest/tracing/span/index.html
|
||||
|
||||
## Supported Rust Versions
|
||||
|
||||
Tracing is built against the latest stable release. The minimum supported
|
||||
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.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.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the [MIT license](LICENSE).
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in Tokio by you, shall be licensed as MIT, without any additional
|
||||
terms or conditions.
|
||||
457
third-party/vendor/tracing-attributes/src/attr.rs
vendored
Normal file
457
third-party/vendor/tracing-attributes/src/attr.rs
vendored
Normal file
|
|
@ -0,0 +1,457 @@
|
|||
use std::collections::HashSet;
|
||||
use syn::{punctuated::Punctuated, Expr, Ident, LitInt, LitStr, Path, Token};
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
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>,
|
||||
pub(crate) name: Option<LitStr>,
|
||||
target: Option<LitStr>,
|
||||
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>,
|
||||
/// Errors describing any unrecognized parse inputs that we skipped.
|
||||
parse_warnings: Vec<syn::Error>,
|
||||
}
|
||||
|
||||
impl InstrumentArgs {
|
||||
pub(crate) fn level(&self) -> Level {
|
||||
self.level.clone().unwrap_or(Level::Info)
|
||||
}
|
||||
|
||||
pub(crate) fn target(&self) -> impl ToTokens {
|
||||
if let Some(ref target) = self.target {
|
||||
quote!(#target)
|
||||
} else {
|
||||
quote!(module_path!())
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate "deprecation" warnings for any unrecognized attribute inputs
|
||||
/// that we skipped.
|
||||
///
|
||||
/// For backwards compatibility, we need to emit compiler warnings rather
|
||||
/// than errors for unrecognized inputs. Generating a fake deprecation is
|
||||
/// the only way to do this on stable Rust right now.
|
||||
pub(crate) fn warnings(&self) -> impl ToTokens {
|
||||
let warnings = self.parse_warnings.iter().map(|err| {
|
||||
let msg = format!("found unrecognized input, {}", err);
|
||||
let msg = LitStr::new(&msg, err.span());
|
||||
// TODO(eliza): This is a bit of a hack, but it's just about the
|
||||
// only way to emit warnings from a proc macro on stable Rust.
|
||||
// Eventually, when the `proc_macro::Diagnostic` API stabilizes, we
|
||||
// should definitely use that instead.
|
||||
quote_spanned! {err.span()=>
|
||||
#[warn(deprecated)]
|
||||
{
|
||||
#[deprecated(since = "not actually deprecated", note = #msg)]
|
||||
const TRACING_INSTRUMENT_WARNING: () = ();
|
||||
let _ = TRACING_INSTRUMENT_WARNING;
|
||||
}
|
||||
}
|
||||
});
|
||||
quote! {
|
||||
{ #(#warnings)* }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for InstrumentArgs {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let mut args = Self::default();
|
||||
while !input.is_empty() {
|
||||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(kw::name) {
|
||||
if args.name.is_some() {
|
||||
return Err(input.error("expected only a single `name` argument"));
|
||||
}
|
||||
let name = input.parse::<StrArg<kw::name>>()?.value;
|
||||
args.name = Some(name);
|
||||
} else if lookahead.peek(LitStr) {
|
||||
// XXX: apparently we support names as either named args with an
|
||||
// sign, _or_ as unnamed string literals. That's weird, but
|
||||
// changing it is apparently breaking.
|
||||
if args.name.is_some() {
|
||||
return Err(input.error("expected only a single `name` argument"));
|
||||
}
|
||||
args.name = Some(input.parse()?);
|
||||
} else if lookahead.peek(kw::target) {
|
||||
if args.target.is_some() {
|
||||
return Err(input.error("expected only a single `target` argument"));
|
||||
}
|
||||
let target = input.parse::<StrArg<kw::target>>()?.value;
|
||||
args.target = Some(target);
|
||||
} else if lookahead.peek(kw::parent) {
|
||||
if args.target.is_some() {
|
||||
return Err(input.error("expected only a single `parent` argument"));
|
||||
}
|
||||
let parent = input.parse::<ExprArg<kw::parent>>()?;
|
||||
args.parent = Some(parent.value);
|
||||
} else if lookahead.peek(kw::follows_from) {
|
||||
if args.target.is_some() {
|
||||
return Err(input.error("expected only a single `follows_from` argument"));
|
||||
}
|
||||
let follows_from = input.parse::<ExprArg<kw::follows_from>>()?;
|
||||
args.follows_from = Some(follows_from.value);
|
||||
} else if lookahead.peek(kw::level) {
|
||||
if args.level.is_some() {
|
||||
return Err(input.error("expected only a single `level` argument"));
|
||||
}
|
||||
args.level = Some(input.parse()?);
|
||||
} else if lookahead.peek(kw::skip) {
|
||||
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"));
|
||||
}
|
||||
args.fields = Some(input.parse()?);
|
||||
} else if lookahead.peek(kw::err) {
|
||||
let _ = input.parse::<kw::err>();
|
||||
let err_args = EventArgs::parse(input)?;
|
||||
args.err_args = Some(err_args);
|
||||
} else if lookahead.peek(kw::ret) {
|
||||
let _ = input.parse::<kw::ret>()?;
|
||||
let ret_args = EventArgs::parse(input)?;
|
||||
args.ret_args = Some(ret_args);
|
||||
} else if lookahead.peek(Token![,]) {
|
||||
let _ = input.parse::<Token![,]>()?;
|
||||
} else {
|
||||
// We found a token that we didn't expect!
|
||||
// We want to emit warnings for these, rather than errors, so
|
||||
// we'll add it to the list of unrecognized inputs we've seen so
|
||||
// far and keep going.
|
||||
args.parse_warnings.push(lookahead.error());
|
||||
// Parse the unrecognized token tree to advance the parse
|
||||
// stream, and throw it away so we can keep parsing.
|
||||
let _ = input.parse::<proc_macro2::TokenTree>();
|
||||
}
|
||||
}
|
||||
Ok(args)
|
||||
}
|
||||
}
|
||||
|
||||
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>,
|
||||
}
|
||||
|
||||
impl<T: Parse> Parse for StrArg<T> {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let _ = input.parse::<T>()?;
|
||||
let _ = input.parse::<Token![=]>()?;
|
||||
let value = input.parse()?;
|
||||
Ok(Self {
|
||||
value,
|
||||
_p: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct ExprArg<T> {
|
||||
value: Expr,
|
||||
_p: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: Parse> Parse for ExprArg<T> {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let _ = input.parse::<T>()?;
|
||||
let _ = input.parse::<Token![=]>()?;
|
||||
let value = input.parse()?;
|
||||
Ok(Self {
|
||||
value,
|
||||
_p: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct Skips(HashSet<Ident>);
|
||||
|
||||
impl Parse for Skips {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let _ = input.parse::<kw::skip>();
|
||||
let content;
|
||||
let _ = syn::parenthesized!(content in input);
|
||||
let names = content.parse_terminated(Ident::parse_any, Token![,])?;
|
||||
let mut skips = HashSet::new();
|
||||
for name in names {
|
||||
if skips.contains(&name) {
|
||||
return Err(syn::Error::new(
|
||||
name.span(),
|
||||
"tried to skip the same field twice",
|
||||
));
|
||||
} else {
|
||||
skips.insert(name);
|
||||
}
|
||||
}
|
||||
Ok(Self(skips))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub(crate) enum FormatMode {
|
||||
Default,
|
||||
Display,
|
||||
Debug,
|
||||
}
|
||||
|
||||
impl Default for FormatMode {
|
||||
fn default() -> Self {
|
||||
FormatMode::Default
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct Fields(pub(crate) Punctuated<Field, Token![,]>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct Field {
|
||||
pub(crate) name: Punctuated<Ident, Token![.]>,
|
||||
pub(crate) value: Option<Expr>,
|
||||
pub(crate) kind: FieldKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub(crate) enum FieldKind {
|
||||
Debug,
|
||||
Display,
|
||||
Value,
|
||||
}
|
||||
|
||||
impl Parse for Fields {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let _ = input.parse::<kw::fields>();
|
||||
let content;
|
||||
let _ = syn::parenthesized!(content in input);
|
||||
let fields = content.parse_terminated(Field::parse, Token![,])?;
|
||||
Ok(Self(fields))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Fields {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.0.to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Field {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let mut kind = FieldKind::Value;
|
||||
if input.peek(Token![%]) {
|
||||
input.parse::<Token![%]>()?;
|
||||
kind = FieldKind::Display;
|
||||
} else if input.peek(Token![?]) {
|
||||
input.parse::<Token![?]>()?;
|
||||
kind = FieldKind::Debug;
|
||||
};
|
||||
let name = Punctuated::parse_separated_nonempty_with(input, Ident::parse_any)?;
|
||||
let value = if input.peek(Token![=]) {
|
||||
input.parse::<Token![=]>()?;
|
||||
if input.peek(Token![%]) {
|
||||
input.parse::<Token![%]>()?;
|
||||
kind = FieldKind::Display;
|
||||
} else if input.peek(Token![?]) {
|
||||
input.parse::<Token![?]>()?;
|
||||
kind = FieldKind::Debug;
|
||||
};
|
||||
Some(input.parse()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Self { name, value, kind })
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Field {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
if let Some(ref value) = self.value {
|
||||
let name = &self.name;
|
||||
let kind = &self.kind;
|
||||
tokens.extend(quote! {
|
||||
#name = #kind #value
|
||||
})
|
||||
} else if self.kind == FieldKind::Value {
|
||||
// XXX(eliza): I don't like that fields without values produce
|
||||
// empty fields rather than local variable shorthand...but,
|
||||
// we've released a version where field names without values in
|
||||
// `instrument` produce empty field values, so changing it now
|
||||
// is a breaking change. agh.
|
||||
let name = &self.name;
|
||||
tokens.extend(quote!(#name = tracing::field::Empty))
|
||||
} else {
|
||||
self.kind.to_tokens(tokens);
|
||||
self.name.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for FieldKind {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self {
|
||||
FieldKind::Debug => tokens.extend(quote! { ? }),
|
||||
FieldKind::Display => tokens.extend(quote! { % }),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum Level {
|
||||
Trace,
|
||||
Debug,
|
||||
Info,
|
||||
Warn,
|
||||
Error,
|
||||
Path(Path),
|
||||
}
|
||||
|
||||
impl Parse for Level {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let _ = input.parse::<kw::level>()?;
|
||||
let _ = input.parse::<Token![=]>()?;
|
||||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(LitStr) {
|
||||
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) {
|
||||
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 {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
syn::custom_keyword!(follows_from);
|
||||
syn::custom_keyword!(name);
|
||||
syn::custom_keyword!(err);
|
||||
syn::custom_keyword!(ret);
|
||||
}
|
||||
827
third-party/vendor/tracing-attributes/src/expand.rs
vendored
Normal file
827
third-party/vendor/tracing-attributes/src/expand.rs
vendored
Normal file
|
|
@ -0,0 +1,827 @@
|
|||
use std::iter;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, quote_spanned, ToTokens};
|
||||
use syn::visit_mut::VisitMut;
|
||||
use syn::{
|
||||
punctuated::Punctuated, spanned::Spanned, Block, Expr, ExprAsync, ExprCall, FieldPat, FnArg,
|
||||
Ident, Item, ItemFn, Pat, PatIdent, PatReference, PatStruct, PatTuple, PatTupleStruct, PatType,
|
||||
Path, ReturnType, Signature, Stmt, Token, Type, TypePath,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
attr::{Field, Fields, FormatMode, InstrumentArgs, Level},
|
||||
MaybeItemFn, MaybeItemFnRef,
|
||||
};
|
||||
|
||||
/// Given an existing function, generate an instrumented version of that function
|
||||
pub(crate) fn gen_function<'a, B: ToTokens + 'a>(
|
||||
input: MaybeItemFnRef<'a, B>,
|
||||
args: InstrumentArgs,
|
||||
instrumented_function_name: &str,
|
||||
self_type: Option<&TypePath>,
|
||||
) -> proc_macro2::TokenStream {
|
||||
// these are needed ahead of time, as ItemFn contains the function body _and_
|
||||
// isn't representable inside a quote!/quote_spanned! macro
|
||||
// (Syn's ToTokens isn't implemented for ItemFn)
|
||||
let MaybeItemFnRef {
|
||||
outer_attrs,
|
||||
inner_attrs,
|
||||
vis,
|
||||
sig,
|
||||
block,
|
||||
} = input;
|
||||
|
||||
let Signature {
|
||||
output,
|
||||
inputs: params,
|
||||
unsafety,
|
||||
asyncness,
|
||||
constness,
|
||||
abi,
|
||||
ident,
|
||||
generics:
|
||||
syn::Generics {
|
||||
params: gen_params,
|
||||
where_clause,
|
||||
..
|
||||
},
|
||||
..
|
||||
} = sig;
|
||||
|
||||
let warnings = args.warnings();
|
||||
|
||||
let (return_type, return_span) = if let ReturnType::Type(_, return_type) = &output {
|
||||
(erase_impl_trait(return_type), return_type.span())
|
||||
} else {
|
||||
// Point at function name if we don't have an explicit return type
|
||||
(syn::parse_quote! { () }, ident.span())
|
||||
};
|
||||
// Install a fake return statement as the first thing in the function
|
||||
// body, so that we eagerly infer that the return type is what we
|
||||
// declared in the async fn signature.
|
||||
// The `#[allow(..)]` is given because the return statement is
|
||||
// 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(
|
||||
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 = loop {};
|
||||
return __tracing_attr_fake_return;
|
||||
}
|
||||
};
|
||||
let block = quote! {
|
||||
{
|
||||
#fake_return_edge
|
||||
#block
|
||||
}
|
||||
};
|
||||
|
||||
let body = gen_block(
|
||||
&block,
|
||||
params,
|
||||
asyncness.is_some(),
|
||||
args,
|
||||
instrumented_function_name,
|
||||
self_type,
|
||||
);
|
||||
|
||||
quote!(
|
||||
#(#outer_attrs) *
|
||||
#vis #constness #unsafety #asyncness #abi fn #ident<#gen_params>(#params) #output
|
||||
#where_clause
|
||||
{
|
||||
#(#inner_attrs) *
|
||||
#warnings
|
||||
#body
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// Instrument a block
|
||||
fn gen_block<B: ToTokens>(
|
||||
block: &B,
|
||||
params: &Punctuated<FnArg, Token![,]>,
|
||||
async_context: bool,
|
||||
mut args: InstrumentArgs,
|
||||
instrumented_function_name: &str,
|
||||
self_type: Option<&TypePath>,
|
||||
) -> proc_macro2::TokenStream {
|
||||
// generate the span's name
|
||||
let span_name = args
|
||||
// did the user override the span's name?
|
||||
.name
|
||||
.as_ref()
|
||||
.map(|name| quote!(#name))
|
||||
.unwrap_or_else(|| quote!(#instrumented_function_name));
|
||||
|
||||
let args_level = args.level();
|
||||
let level = args_level.clone();
|
||||
|
||||
let follows_from = args.follows_from.iter();
|
||||
let follows_from = quote! {
|
||||
#(for cause in #follows_from {
|
||||
__tracing_attr_span.follows_from(cause);
|
||||
})*
|
||||
};
|
||||
|
||||
// generate this inside a closure, so we can return early on errors.
|
||||
let span = (|| {
|
||||
// Pull out the arguments-to-be-skipped first, so we can filter results
|
||||
// below.
|
||||
let param_names: Vec<(Ident, (Ident, RecordType))> = params
|
||||
.clone()
|
||||
.into_iter()
|
||||
.flat_map(|param| match param {
|
||||
FnArg::Typed(PatType { pat, ty, .. }) => {
|
||||
param_names(*pat, RecordType::parse_from_ty(&ty))
|
||||
}
|
||||
FnArg::Receiver(_) => Box::new(iter::once((
|
||||
Ident::new("self", param.span()),
|
||||
RecordType::Debug,
|
||||
))),
|
||||
})
|
||||
// Little dance with new (user-exposed) names and old (internal)
|
||||
// names of identifiers. That way, we could do the following
|
||||
// even though async_trait (<=0.1.43) rewrites "self" as "_self":
|
||||
// ```
|
||||
// #[async_trait]
|
||||
// impl Foo for FooImpl {
|
||||
// #[instrument(skip(self))]
|
||||
// async fn foo(&self, v: usize) {}
|
||||
// }
|
||||
// ```
|
||||
.map(|(x, record_type)| {
|
||||
// if we are inside a function generated by async-trait <=0.1.43, we need to
|
||||
// take care to rewrite "_self" as "self" for 'user convenience'
|
||||
if self_type.is_some() && x == "_self" {
|
||||
(Ident::new("self", x.span()), (x, record_type))
|
||||
} else {
|
||||
(x.clone(), (x, record_type))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
for skip in &args.skips {
|
||||
if !param_names.iter().map(|(user, _)| user).any(|y| y == skip) {
|
||||
return quote_spanned! {skip.span()=>
|
||||
compile_error!("attempting to skip non-existent parameter")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let target = args.target();
|
||||
|
||||
let parent = args.parent.iter();
|
||||
|
||||
// filter out skipped fields
|
||||
let quoted_fields: Vec<_> = param_names
|
||||
.iter()
|
||||
.filter(|(param, _)| {
|
||||
if args.skip_all || args.skips.contains(param) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If any parameters have the same name as a custom field, skip
|
||||
// and allow them to be formatted by the custom field.
|
||||
if let Some(ref fields) = args.fields {
|
||||
fields.0.iter().all(|Field { ref name, .. }| {
|
||||
let first = name.first();
|
||||
first != name.last() || !first.iter().any(|name| name == ¶m)
|
||||
})
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.map(|(user_name, (real_name, record_type))| match record_type {
|
||||
RecordType::Value => quote!(#user_name = #real_name),
|
||||
RecordType::Debug => quote!(#user_name = tracing::field::debug(&#real_name)),
|
||||
})
|
||||
.collect();
|
||||
|
||||
// replace every use of a variable with its original name
|
||||
if let Some(Fields(ref mut fields)) = args.fields {
|
||||
let mut replacer = IdentAndTypesRenamer {
|
||||
idents: param_names.into_iter().map(|(a, (b, _))| (a, b)).collect(),
|
||||
types: Vec::new(),
|
||||
};
|
||||
|
||||
// when async-trait <=0.1.43 is in use, replace instances
|
||||
// of the "Self" type inside the fields values
|
||||
if let Some(self_type) = self_type {
|
||||
replacer.types.push(("Self", self_type.clone()));
|
||||
}
|
||||
|
||||
for e in fields.iter_mut().filter_map(|f| f.value.as_mut()) {
|
||||
syn::visit_mut::visit_expr_mut(&mut replacer, e);
|
||||
}
|
||||
}
|
||||
|
||||
let custom_fields = &args.fields;
|
||||
|
||||
quote!(tracing::span!(
|
||||
target: #target,
|
||||
#(parent: #parent,)*
|
||||
#level,
|
||||
#span_name,
|
||||
#(#quoted_fields,)*
|
||||
#custom_fields
|
||||
|
||||
))
|
||||
})();
|
||||
|
||||
let target = args.target();
|
||||
|
||||
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)
|
||||
)),
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
// Generate the instrumented function body.
|
||||
// If the function is an `async fn`, this will wrap it in an async block,
|
||||
// which is `instrument`ed using `tracing-futures`. Otherwise, this will
|
||||
// enter the span and then perform the rest of the body.
|
||||
// If `err` is in args, instrument any resulting `Err`s.
|
||||
// If `ret` is in args, instrument any resulting `Ok`s when the function
|
||||
// returns `Result`s, otherwise instrument any resulting values.
|
||||
if async_context {
|
||||
let mk_fut = match (err_event, ret_event) {
|
||||
(Some(err_event), Some(ret_event)) => quote_spanned!(block.span()=>
|
||||
async move {
|
||||
match async move #block.await {
|
||||
#[allow(clippy::unit_arg)]
|
||||
Ok(x) => {
|
||||
#ret_event;
|
||||
Ok(x)
|
||||
},
|
||||
Err(e) => {
|
||||
#err_event;
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
(Some(err_event), None) => quote_spanned!(block.span()=>
|
||||
async move {
|
||||
match async move #block.await {
|
||||
#[allow(clippy::unit_arg)]
|
||||
Ok(x) => Ok(x),
|
||||
Err(e) => {
|
||||
#err_event;
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
(None, Some(ret_event)) => quote_spanned!(block.span()=>
|
||||
async move {
|
||||
let x = async move #block.await;
|
||||
#ret_event;
|
||||
x
|
||||
}
|
||||
),
|
||||
(None, None) => quote_spanned!(block.span()=>
|
||||
async move #block
|
||||
),
|
||||
};
|
||||
|
||||
return quote!(
|
||||
let __tracing_attr_span = #span;
|
||||
let __tracing_instrument_future = #mk_fut;
|
||||
if !__tracing_attr_span.is_disabled() {
|
||||
#follows_from
|
||||
tracing::Instrument::instrument(
|
||||
__tracing_instrument_future,
|
||||
__tracing_attr_span
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
__tracing_instrument_future.await
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
let span = quote!(
|
||||
// These variables are left uninitialized and initialized only
|
||||
// if the tracing level is statically enabled at this point.
|
||||
// While the tracing level is also checked at span creation
|
||||
// time, that will still create a dummy span, and a dummy guard
|
||||
// and drop the dummy guard later. By lazily initializing these
|
||||
// variables, Rust will generate a drop flag for them and thus
|
||||
// only drop the guard if it was created. This creates code that
|
||||
// is very straightforward for LLVM to optimize out if the tracing
|
||||
// level is statically disabled, while not causing any performance
|
||||
// regression in case the level is enabled.
|
||||
let __tracing_attr_span;
|
||||
let __tracing_attr_guard;
|
||||
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();
|
||||
}
|
||||
);
|
||||
|
||||
match (err_event, ret_event) {
|
||||
(Some(err_event), Some(ret_event)) => quote_spanned! {block.span()=>
|
||||
#span
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
match (move || #block)() {
|
||||
#[allow(clippy::unit_arg)]
|
||||
Ok(x) => {
|
||||
#ret_event;
|
||||
Ok(x)
|
||||
},
|
||||
Err(e) => {
|
||||
#err_event;
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
},
|
||||
(Some(err_event), None) => quote_spanned!(block.span()=>
|
||||
#span
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
match (move || #block)() {
|
||||
#[allow(clippy::unit_arg)]
|
||||
Ok(x) => Ok(x),
|
||||
Err(e) => {
|
||||
#err_event;
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
),
|
||||
(None, Some(ret_event)) => quote_spanned!(block.span()=>
|
||||
#span
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
let x = (move || #block)();
|
||||
#ret_event;
|
||||
x
|
||||
),
|
||||
(None, None) => quote_spanned!(block.span() =>
|
||||
// Because `quote` produces a stream of tokens _without_ whitespace, the
|
||||
// `if` and the block will appear directly next to each other. This
|
||||
// generates a clippy lint about suspicious `if/else` formatting.
|
||||
// Therefore, suppress the lint inside the generated code...
|
||||
#[allow(clippy::suspicious_else_formatting)]
|
||||
{
|
||||
#span
|
||||
// ...but turn the lint back on inside the function body.
|
||||
#[warn(clippy::suspicious_else_formatting)]
|
||||
#block
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates whether a field should be recorded as `Value` or `Debug`.
|
||||
enum RecordType {
|
||||
/// The field should be recorded using its `Value` implementation.
|
||||
Value,
|
||||
/// The field should be recorded using `tracing::field::debug()`.
|
||||
Debug,
|
||||
}
|
||||
|
||||
impl RecordType {
|
||||
/// Array of primitive types which should be recorded as [RecordType::Value].
|
||||
const TYPES_FOR_VALUE: &'static [&'static str] = &[
|
||||
"bool",
|
||||
"str",
|
||||
"u8",
|
||||
"i8",
|
||||
"u16",
|
||||
"i16",
|
||||
"u32",
|
||||
"i32",
|
||||
"u64",
|
||||
"i64",
|
||||
"f32",
|
||||
"f64",
|
||||
"usize",
|
||||
"isize",
|
||||
"NonZeroU8",
|
||||
"NonZeroI8",
|
||||
"NonZeroU16",
|
||||
"NonZeroI16",
|
||||
"NonZeroU32",
|
||||
"NonZeroI32",
|
||||
"NonZeroU64",
|
||||
"NonZeroI64",
|
||||
"NonZeroUsize",
|
||||
"NonZeroIsize",
|
||||
"Wrapping",
|
||||
];
|
||||
|
||||
/// Parse `RecordType` from [Type] by looking up
|
||||
/// the [RecordType::TYPES_FOR_VALUE] array.
|
||||
fn parse_from_ty(ty: &Type) -> Self {
|
||||
match ty {
|
||||
Type::Path(TypePath { path, .. })
|
||||
if path
|
||||
.segments
|
||||
.iter()
|
||||
.last()
|
||||
.map(|path_segment| {
|
||||
let ident = path_segment.ident.to_string();
|
||||
Self::TYPES_FOR_VALUE.iter().any(|&t| t == ident)
|
||||
})
|
||||
.unwrap_or(false) =>
|
||||
{
|
||||
RecordType::Value
|
||||
}
|
||||
Type::Reference(syn::TypeReference { elem, .. }) => RecordType::parse_from_ty(elem),
|
||||
_ => RecordType::Debug,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn param_names(pat: Pat, record_type: RecordType) -> Box<dyn Iterator<Item = (Ident, RecordType)>> {
|
||||
match pat {
|
||||
Pat::Ident(PatIdent { ident, .. }) => Box::new(iter::once((ident, record_type))),
|
||||
Pat::Reference(PatReference { pat, .. }) => param_names(*pat, record_type),
|
||||
// We can't get the concrete type of fields in the struct/tuple
|
||||
// patterns by using `syn`. e.g. `fn foo(Foo { x, y }: Foo) {}`.
|
||||
// Therefore, the struct/tuple patterns in the arguments will just
|
||||
// always be recorded as `RecordType::Debug`.
|
||||
Pat::Struct(PatStruct { fields, .. }) => Box::new(
|
||||
fields
|
||||
.into_iter()
|
||||
.flat_map(|FieldPat { pat, .. }| param_names(*pat, RecordType::Debug)),
|
||||
),
|
||||
Pat::Tuple(PatTuple { elems, .. }) => Box::new(
|
||||
elems
|
||||
.into_iter()
|
||||
.flat_map(|p| param_names(p, RecordType::Debug)),
|
||||
),
|
||||
Pat::TupleStruct(PatTupleStruct { elems, .. }) => Box::new(
|
||||
elems
|
||||
.into_iter()
|
||||
.flat_map(|p| param_names(p, RecordType::Debug)),
|
||||
),
|
||||
|
||||
// The above *should* cover all cases of irrefutable patterns,
|
||||
// but we purposefully don't do any funny business here
|
||||
// (such as panicking) because that would obscure rustc's
|
||||
// much more informative error message.
|
||||
_ => Box::new(iter::empty()),
|
||||
}
|
||||
}
|
||||
|
||||
/// The specific async code pattern that was detected
|
||||
enum AsyncKind<'a> {
|
||||
/// Immediately-invoked async fn, as generated by `async-trait <= 0.1.43`:
|
||||
/// `async fn foo<...>(...) {...}; Box::pin(foo<...>(...))`
|
||||
Function(&'a ItemFn),
|
||||
/// A function returning an async (move) block, optionally `Box::pin`-ed,
|
||||
/// as generated by `async-trait >= 0.1.44`:
|
||||
/// `Box::pin(async move { ... })`
|
||||
Async {
|
||||
async_expr: &'a ExprAsync,
|
||||
pinned_box: bool,
|
||||
},
|
||||
}
|
||||
|
||||
pub(crate) struct AsyncInfo<'block> {
|
||||
// statement that must be patched
|
||||
source_stmt: &'block Stmt,
|
||||
kind: AsyncKind<'block>,
|
||||
self_type: Option<TypePath>,
|
||||
input: &'block ItemFn,
|
||||
}
|
||||
|
||||
impl<'block> AsyncInfo<'block> {
|
||||
/// Get the AST of the inner function we need to hook, if it looks like a
|
||||
/// manual future implementation.
|
||||
///
|
||||
/// When we are given a function that returns a (pinned) future containing the
|
||||
/// user logic, it is that (pinned) future that needs to be instrumented.
|
||||
/// Were we to instrument its parent, we would only collect information
|
||||
/// regarding the allocation of that future, and not its own span of execution.
|
||||
///
|
||||
/// We inspect the block of the function to find if it matches any of the
|
||||
/// following patterns:
|
||||
///
|
||||
/// - Immediately-invoked async fn, as generated by `async-trait <= 0.1.43`:
|
||||
/// `async fn foo<...>(...) {...}; Box::pin(foo<...>(...))`
|
||||
///
|
||||
/// - A function returning an async (move) block, optionally `Box::pin`-ed,
|
||||
/// as generated by `async-trait >= 0.1.44`:
|
||||
/// `Box::pin(async move { ... })`
|
||||
///
|
||||
/// We the return the statement that must be instrumented, along with some
|
||||
/// other information.
|
||||
/// 'gen_body' will then be able to use that information to instrument the
|
||||
/// proper function/future.
|
||||
///
|
||||
/// (this follows the approach suggested in
|
||||
/// https://github.com/dtolnay/async-trait/issues/45#issuecomment-571245673)
|
||||
pub(crate) fn from_fn(input: &'block ItemFn) -> Option<Self> {
|
||||
// are we in an async context? If yes, this isn't a manual async-like pattern
|
||||
if input.sig.asyncness.is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let block = &input.block;
|
||||
|
||||
// list of async functions declared inside the block
|
||||
let inside_funs = block.stmts.iter().filter_map(|stmt| {
|
||||
if let Stmt::Item(Item::Fn(fun)) = &stmt {
|
||||
// If the function is async, this is a candidate
|
||||
if fun.sig.asyncness.is_some() {
|
||||
return Some((stmt, fun));
|
||||
}
|
||||
}
|
||||
None
|
||||
});
|
||||
|
||||
// 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, _semi) = stmt {
|
||||
Some((stmt, expr))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})?;
|
||||
|
||||
// is the last expression an async block?
|
||||
if let Expr::Async(async_expr) = last_expr {
|
||||
return Some(AsyncInfo {
|
||||
source_stmt: last_expr_stmt,
|
||||
kind: AsyncKind::Async {
|
||||
async_expr,
|
||||
pinned_box: false,
|
||||
},
|
||||
self_type: None,
|
||||
input,
|
||||
});
|
||||
}
|
||||
|
||||
// is the last expression a function call?
|
||||
let (outside_func, outside_args) = match last_expr {
|
||||
Expr::Call(ExprCall { func, args, .. }) => (func, args),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
// is it a call to `Box::pin()`?
|
||||
let path = match outside_func.as_ref() {
|
||||
Expr::Path(path) => &path.path,
|
||||
_ => return None,
|
||||
};
|
||||
if !path_to_string(path).ends_with("Box::pin") {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Does the call take an argument? If it doesn't,
|
||||
// it's not gonna compile anyway, but that's no reason
|
||||
// to (try to) perform an out of bounds access
|
||||
if outside_args.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Is the argument to Box::pin an async block that
|
||||
// captures its arguments?
|
||||
if let Expr::Async(async_expr) = &outside_args[0] {
|
||||
return Some(AsyncInfo {
|
||||
source_stmt: last_expr_stmt,
|
||||
kind: AsyncKind::Async {
|
||||
async_expr,
|
||||
pinned_box: true,
|
||||
},
|
||||
self_type: None,
|
||||
input,
|
||||
});
|
||||
}
|
||||
|
||||
// Is the argument to Box::pin a function call itself?
|
||||
let func = match &outside_args[0] {
|
||||
Expr::Call(ExprCall { func, .. }) => func,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
// "stringify" the path of the function called
|
||||
let func_name = match **func {
|
||||
Expr::Path(ref func_path) => path_to_string(&func_path.path),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
// Was that function defined inside of the current block?
|
||||
// If so, retrieve the statement where it was declared and the function itself
|
||||
let (stmt_func_declaration, func) = inside_funs
|
||||
.into_iter()
|
||||
.find(|(_, fun)| fun.sig.ident == func_name)?;
|
||||
|
||||
// If "_self" is present as an argument, we store its type to be able to rewrite "Self" (the
|
||||
// parameter type) with the type of "_self"
|
||||
let mut self_type = None;
|
||||
for arg in &func.sig.inputs {
|
||||
if let FnArg::Typed(ty) = arg {
|
||||
if let Pat::Ident(PatIdent { ref ident, .. }) = *ty.pat {
|
||||
if ident == "_self" {
|
||||
let mut ty = *ty.ty.clone();
|
||||
// extract the inner type if the argument is "&self" or "&mut self"
|
||||
if let Type::Reference(syn::TypeReference { elem, .. }) = ty {
|
||||
ty = *elem;
|
||||
}
|
||||
|
||||
if let Type::Path(tp) = ty {
|
||||
self_type = Some(tp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(AsyncInfo {
|
||||
source_stmt: stmt_func_declaration,
|
||||
kind: AsyncKind::Function(func),
|
||||
self_type,
|
||||
input,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn gen_async(
|
||||
self,
|
||||
args: InstrumentArgs,
|
||||
instrumented_function_name: &str,
|
||||
) -> Result<proc_macro::TokenStream, syn::Error> {
|
||||
// let's rewrite some statements!
|
||||
let mut out_stmts: Vec<TokenStream> = self
|
||||
.input
|
||||
.block
|
||||
.stmts
|
||||
.iter()
|
||||
.map(|stmt| stmt.to_token_stream())
|
||||
.collect();
|
||||
|
||||
if let Some((iter, _stmt)) = self
|
||||
.input
|
||||
.block
|
||||
.stmts
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_iter, stmt)| *stmt == self.source_stmt)
|
||||
{
|
||||
// instrument the future by rewriting the corresponding statement
|
||||
out_stmts[iter] = match self.kind {
|
||||
// `Box::pin(immediately_invoked_async_fn())`
|
||||
AsyncKind::Function(fun) => {
|
||||
let fun = MaybeItemFn::from(fun.clone());
|
||||
gen_function(
|
||||
fun.as_ref(),
|
||||
args,
|
||||
instrumented_function_name,
|
||||
self.self_type.as_ref(),
|
||||
)
|
||||
}
|
||||
// `async move { ... }`, optionally pinned
|
||||
AsyncKind::Async {
|
||||
async_expr,
|
||||
pinned_box,
|
||||
} => {
|
||||
let instrumented_block = gen_block(
|
||||
&async_expr.block,
|
||||
&self.input.sig.inputs,
|
||||
true,
|
||||
args,
|
||||
instrumented_function_name,
|
||||
None,
|
||||
);
|
||||
let async_attrs = &async_expr.attrs;
|
||||
if pinned_box {
|
||||
quote! {
|
||||
Box::pin(#(#async_attrs) * async move { #instrumented_block })
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#(#async_attrs) * async move { #instrumented_block }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let vis = &self.input.vis;
|
||||
let sig = &self.input.sig;
|
||||
let attrs = &self.input.attrs;
|
||||
Ok(quote!(
|
||||
#(#attrs) *
|
||||
#vis #sig {
|
||||
#(#out_stmts) *
|
||||
}
|
||||
)
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
// Return a path as a String
|
||||
fn path_to_string(path: &Path) -> String {
|
||||
use std::fmt::Write;
|
||||
// some heuristic to prevent too many allocations
|
||||
let mut res = String::with_capacity(path.segments.len() * 5);
|
||||
for i in 0..path.segments.len() {
|
||||
write!(&mut res, "{}", path.segments[i].ident)
|
||||
.expect("writing to a String should never fail");
|
||||
if i < path.segments.len() - 1 {
|
||||
res.push_str("::");
|
||||
}
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
/// A visitor struct to replace idents and types in some piece
|
||||
/// of code (e.g. the "self" and "Self" tokens in user-supplied
|
||||
/// fields expressions when the function is generated by an old
|
||||
/// version of async-trait).
|
||||
struct IdentAndTypesRenamer<'a> {
|
||||
types: Vec<(&'a str, TypePath)>,
|
||||
idents: Vec<(Ident, Ident)>,
|
||||
}
|
||||
|
||||
impl<'a> VisitMut for IdentAndTypesRenamer<'a> {
|
||||
// we deliberately compare strings because we want to ignore the spans
|
||||
// If we apply clippy's lint, the behavior changes
|
||||
#[allow(clippy::cmp_owned)]
|
||||
fn visit_ident_mut(&mut self, id: &mut Ident) {
|
||||
for (old_ident, new_ident) in &self.idents {
|
||||
if id.to_string() == old_ident.to_string() {
|
||||
*id = new_ident.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_type_mut(&mut self, ty: &mut Type) {
|
||||
for (type_name, new_type) in &self.types {
|
||||
if let Type::Path(TypePath { path, .. }) = ty {
|
||||
if path_to_string(path) == *type_name {
|
||||
*ty = Type::Path(new_type.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A visitor struct that replace an async block by its patched version
|
||||
struct AsyncTraitBlockReplacer<'a> {
|
||||
block: &'a Block,
|
||||
patched_block: Block,
|
||||
}
|
||||
|
||||
impl<'a> VisitMut for AsyncTraitBlockReplacer<'a> {
|
||||
fn visit_block_mut(&mut self, i: &mut Block) {
|
||||
if i == self.block {
|
||||
*i = self.patched_block.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replaces any `impl Trait` with `_` so it can be used as the type in
|
||||
// a `let` statement's LHS.
|
||||
struct ImplTraitEraser;
|
||||
|
||||
impl VisitMut for ImplTraitEraser {
|
||||
fn visit_type_mut(&mut self, t: &mut Type) {
|
||||
if let Type::ImplTrait(..) = t {
|
||||
*t = syn::TypeInfer {
|
||||
underscore_token: Token),
|
||||
}
|
||||
.into();
|
||||
} else {
|
||||
syn::visit_mut::visit_type_mut(self, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn erase_impl_trait(ty: &Type) -> Type {
|
||||
let mut ty = ty.clone();
|
||||
ImplTraitEraser.visit_type_mut(&mut ty);
|
||||
ty
|
||||
}
|
||||
695
third-party/vendor/tracing-attributes/src/lib.rs
vendored
Normal file
695
third-party/vendor/tracing-attributes/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,695 @@
|
|||
//! A procedural macro attribute for instrumenting functions with [`tracing`].
|
||||
//!
|
||||
//! [`tracing`] is a framework for instrumenting Rust programs to collect
|
||||
//! structured, event-based diagnostic information. This crate provides the
|
||||
//! [`#[instrument]`][instrument] procedural macro attribute.
|
||||
//!
|
||||
//! Note that this macro is also re-exported by the main `tracing` crate.
|
||||
//!
|
||||
//! *Compiler support: [requires `rustc` 1.56+][msrv]*
|
||||
//!
|
||||
//! [msrv]: #supported-rust-versions
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! In the `Cargo.toml`:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! tracing-attributes = "0.1.24"
|
||||
//! ```
|
||||
//!
|
||||
//! The [`#[instrument]`][instrument] attribute can now be added to a function
|
||||
//! to automatically create and enter `tracing` [span] when that function is
|
||||
//! called. For example:
|
||||
//!
|
||||
//! ```
|
||||
//! use tracing::instrument;
|
||||
//!
|
||||
//! #[instrument]
|
||||
//! pub fn my_function(my_arg: usize) {
|
||||
//! // ...
|
||||
//! }
|
||||
//!
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
//!
|
||||
//! [`tracing`]: https://crates.io/crates/tracing
|
||||
//! [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.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.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",
|
||||
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,
|
||||
dead_code,
|
||||
improper_ctypes,
|
||||
non_shorthand_field_patterns,
|
||||
no_mangle_generic_items,
|
||||
overflowing_literals,
|
||||
path_statements,
|
||||
patterns_in_fns_without_body,
|
||||
private_in_public,
|
||||
unconditional_recursion,
|
||||
unused_allocation,
|
||||
unused_comparisons,
|
||||
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};
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
use syn::{Attribute, ItemFn, Signature, Visibility};
|
||||
|
||||
mod attr;
|
||||
mod expand;
|
||||
/// Instruments a function to create and enter a `tracing` [span] every time
|
||||
/// the function is called.
|
||||
///
|
||||
/// 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
|
||||
/// [`Value` trait] will be recorded as fields of that type. Types which do
|
||||
/// 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:
|
||||
///
|
||||
/// - 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. 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]
|
||||
/// pub fn my_function(my_arg: usize) {
|
||||
/// // This event will be recorded inside a span named `my_function` with the
|
||||
/// // field `my_arg`.
|
||||
/// tracing::info!("inside my_function!");
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
/// Setting the level for the generated span:
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// # 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;
|
||||
/// #[instrument(name = "my_name")]
|
||||
/// pub fn my_function() {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
/// Overriding the generated span's target:
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// #[instrument(target = "my_target")]
|
||||
/// pub fn my_function() {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
/// Overriding the generated span's parent:
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// #[instrument(parent = None)]
|
||||
/// pub fn my_function() {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// // A struct which owns a span handle.
|
||||
/// struct MyStruct
|
||||
/// {
|
||||
/// span: tracing::Span
|
||||
/// }
|
||||
///
|
||||
/// impl MyStruct
|
||||
/// {
|
||||
/// // Use the struct's `span` field as the parent span
|
||||
/// #[instrument(parent = &self.span, skip(self))]
|
||||
/// fn my_method(&self) {}
|
||||
/// }
|
||||
/// ```
|
||||
/// Specifying [`follows_from`] relationships:
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// #[instrument(follows_from = causes)]
|
||||
/// pub fn my_function(causes: &[tracing::Id]) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
/// Any expression of type `impl IntoIterator<Item = impl Into<Option<Id>>>`
|
||||
/// may be provided to `follows_from`; e.g.:
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// #[instrument(follows_from = [cause])]
|
||||
/// pub fn my_function(cause: &tracing::span::EnteredSpan) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// To skip recording an argument, pass the argument's name to the `skip`:
|
||||
///
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// struct NonDebug;
|
||||
///
|
||||
/// #[instrument(skip(non_debug))]
|
||||
/// fn my_function(arg: usize, non_debug: NonDebug) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// To add additional context to the span, pass key-value pairs to `fields`:
|
||||
///
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// #[instrument(fields(foo="bar", id=1, show=true))]
|
||||
/// fn my_function(arg: usize) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Adding the `ret` argument to `#[instrument]` will emit an event with the function's
|
||||
/// return value when the function returns:
|
||||
///
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// #[instrument(ret)]
|
||||
/// fn my_function() -> i32 {
|
||||
/// 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
|
||||
/// 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`].
|
||||
///
|
||||
/// By default, returned values will be recorded using their [`std::fmt::Debug`] implementations.
|
||||
/// If a returned value implements [`std::fmt::Display`], it can be recorded using its `Display`
|
||||
/// implementation instead, by writing `ret(Display)`:
|
||||
///
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// #[instrument(ret(Display))]
|
||||
/// fn my_function() -> i32 {
|
||||
/// 42
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// 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;
|
||||
/// #[instrument(err)]
|
||||
/// fn my_function(arg: usize) -> Result<(), std::io::Error> {
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// 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)`:
|
||||
///
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// #[instrument(err(Debug))]
|
||||
/// fn my_function(arg: usize) -> Result<(), std::io::Error> {
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// If a `target` is specified, both the `ret` and `err` arguments will emit outputs to
|
||||
/// the declared target (or the default channel if `target` is not specified).
|
||||
///
|
||||
/// The `ret` and `err` arguments can be combined in order to record an event if a
|
||||
/// function returns [`Result::Ok`] or [`Result::Err`]:
|
||||
///
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// #[instrument(err, ret)]
|
||||
/// fn my_function(arg: usize) -> Result<(), std::io::Error> {
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// `async fn`s may also be instrumented:
|
||||
///
|
||||
/// ```
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// #[instrument]
|
||||
/// pub async fn my_function() -> Result<(), ()> {
|
||||
/// // ...
|
||||
/// # Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// It also works with [async-trait](https://crates.io/crates/async-trait)
|
||||
/// (a crate that allows defining async functions in traits,
|
||||
/// something not currently possible in Rust),
|
||||
/// and hopefully most libraries that exhibit similar behaviors:
|
||||
///
|
||||
/// ```
|
||||
/// # use tracing::instrument;
|
||||
/// use async_trait::async_trait;
|
||||
///
|
||||
/// #[async_trait]
|
||||
/// pub trait Foo {
|
||||
/// async fn foo(&self, arg: usize);
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Debug)]
|
||||
/// struct FooImpl(usize);
|
||||
///
|
||||
/// #[async_trait]
|
||||
/// impl Foo for FooImpl {
|
||||
/// #[instrument(fields(value = self.0, tmp = std::any::type_name::<Self>()))]
|
||||
/// async fn foo(&self, arg: usize) {}
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// `const fn` cannot be instrumented, and will result in a compilation failure:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// # use tracing_attributes::instrument;
|
||||
/// #[instrument]
|
||||
/// const fn my_const_function() {}
|
||||
/// ```
|
||||
///
|
||||
/// [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,
|
||||
item: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
let args = syn::parse_macro_input!(args as attr::InstrumentArgs);
|
||||
// Cloning a `TokenStream` is cheap since it's reference counted internally.
|
||||
instrument_precise(args.clone(), item.clone())
|
||||
.unwrap_or_else(|_err| instrument_speculative(args, item))
|
||||
}
|
||||
|
||||
/// Instrument the function, without parsing the function body (instead using the raw tokens).
|
||||
fn instrument_speculative(
|
||||
args: attr::InstrumentArgs,
|
||||
item: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
let input = syn::parse_macro_input!(item as MaybeItemFn);
|
||||
let instrumented_function_name = input.sig.ident.to_string();
|
||||
expand::gen_function(
|
||||
input.as_ref(),
|
||||
args,
|
||||
instrumented_function_name.as_str(),
|
||||
None,
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Instrument the function, by fully parsing the function body,
|
||||
/// which allows us to rewrite some statements related to async-like patterns.
|
||||
fn instrument_precise(
|
||||
args: attr::InstrumentArgs,
|
||||
item: proc_macro::TokenStream,
|
||||
) -> Result<proc_macro::TokenStream, syn::Error> {
|
||||
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) {
|
||||
return async_like.gen_async(args, instrumented_function_name.as_str());
|
||||
}
|
||||
|
||||
let input = MaybeItemFn::from(input);
|
||||
|
||||
Ok(expand::gen_function(
|
||||
input.as_ref(),
|
||||
args,
|
||||
instrumented_function_name.as_str(),
|
||||
None,
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
/// This is a more flexible/imprecise `ItemFn` type,
|
||||
/// which's block is just a `TokenStream` (it may contain invalid code).
|
||||
#[derive(Debug, Clone)]
|
||||
struct MaybeItemFn {
|
||||
outer_attrs: Vec<Attribute>,
|
||||
inner_attrs: Vec<Attribute>,
|
||||
vis: Visibility,
|
||||
sig: Signature,
|
||||
block: TokenStream,
|
||||
}
|
||||
|
||||
impl MaybeItemFn {
|
||||
fn as_ref(&self) -> MaybeItemFnRef<'_, TokenStream> {
|
||||
MaybeItemFnRef {
|
||||
outer_attrs: &self.outer_attrs,
|
||||
inner_attrs: &self.inner_attrs,
|
||||
vis: &self.vis,
|
||||
sig: &self.sig,
|
||||
block: &self.block,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This parses a `TokenStream` into a `MaybeItemFn`
|
||||
/// (just like `ItemFn`, but skips parsing the body).
|
||||
impl Parse for MaybeItemFn {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let outer_attrs = input.call(Attribute::parse_outer)?;
|
||||
let vis: Visibility = input.parse()?;
|
||||
let sig: Signature = input.parse()?;
|
||||
let inner_attrs = input.call(Attribute::parse_inner)?;
|
||||
let block: TokenStream = input.parse()?;
|
||||
Ok(Self {
|
||||
outer_attrs,
|
||||
inner_attrs,
|
||||
vis,
|
||||
sig,
|
||||
block,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ItemFn> for MaybeItemFn {
|
||||
fn from(
|
||||
ItemFn {
|
||||
attrs,
|
||||
vis,
|
||||
sig,
|
||||
block,
|
||||
}: ItemFn,
|
||||
) -> Self {
|
||||
let (outer_attrs, inner_attrs) = attrs
|
||||
.into_iter()
|
||||
.partition(|attr| attr.style == syn::AttrStyle::Outer);
|
||||
Self {
|
||||
outer_attrs,
|
||||
inner_attrs,
|
||||
vis,
|
||||
sig,
|
||||
block: block.to_token_stream(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic reference type for `MaybeItemFn`,
|
||||
/// that takes a generic block type `B` that implements `ToTokens` (eg. `TokenStream`, `Block`).
|
||||
#[derive(Debug, Clone)]
|
||||
struct MaybeItemFnRef<'a, B: ToTokens> {
|
||||
outer_attrs: &'a Vec<Attribute>,
|
||||
inner_attrs: &'a Vec<Attribute>,
|
||||
vis: &'a Visibility,
|
||||
sig: &'a Signature,
|
||||
block: &'a B,
|
||||
}
|
||||
487
third-party/vendor/tracing-attributes/tests/async_fn.rs
vendored
Normal file
487
third-party/vendor/tracing-attributes/tests/async_fn.rs
vendored
Normal file
|
|
@ -0,0 +1,487 @@
|
|||
use tracing_mock::*;
|
||||
|
||||
use std::convert::Infallible;
|
||||
use std::{future::Future, pin::Pin, sync::Arc};
|
||||
use tracing::subscriber::with_default;
|
||||
use tracing_attributes::instrument;
|
||||
|
||||
#[instrument]
|
||||
async fn test_async_fn(polls: usize) -> Result<(), ()> {
|
||||
let future = PollN::new_ok(polls);
|
||||
tracing::trace!(awaiting = true);
|
||||
future.await
|
||||
}
|
||||
|
||||
// Reproduces a compile error when returning an `impl Trait` from an
|
||||
// instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
|
||||
#[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>, ()> {
|
||||
Ok((0..10).filter(move |x| *x < n))
|
||||
}
|
||||
|
||||
// Reproduces a compile error when returning an `impl Trait` from an
|
||||
// instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
|
||||
#[allow(dead_code)] // this is just here to test whether it compiles.
|
||||
#[instrument(err)]
|
||||
async fn test_ret_impl_trait_err(n: i32) -> Result<impl Iterator<Item = i32>, &'static str> {
|
||||
Ok((0..10).filter(move |x| *x < n))
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
async fn test_async_fn_empty() {}
|
||||
|
||||
// Reproduces a compile error when an instrumented function body contains inner
|
||||
// attributes (https://github.com/tokio-rs/tracing/issues/2294).
|
||||
#[deny(unused_variables)]
|
||||
#[instrument]
|
||||
async fn repro_async_2294() {
|
||||
#![allow(unused_variables)]
|
||||
let i = 42;
|
||||
}
|
||||
|
||||
// Reproduces https://github.com/tokio-rs/tracing/issues/1613
|
||||
#[instrument]
|
||||
// LOAD-BEARING `#[rustfmt::skip]`! This is necessary to reproduce the bug;
|
||||
// with the rustfmt-generated formatting, the lint will not be triggered!
|
||||
#[rustfmt::skip]
|
||||
#[deny(clippy::suspicious_else_formatting)]
|
||||
async fn repro_1613(var: bool) {
|
||||
println!(
|
||||
"{}",
|
||||
if var { "true" } else { "false" }
|
||||
);
|
||||
}
|
||||
|
||||
// Reproduces https://github.com/tokio-rs/tracing/issues/1613
|
||||
// and https://github.com/rust-lang/rust-clippy/issues/7760
|
||||
#[instrument]
|
||||
#[deny(clippy::suspicious_else_formatting)]
|
||||
async fn repro_1613_2() {
|
||||
// hello world
|
||||
// else
|
||||
}
|
||||
|
||||
// Reproduces https://github.com/tokio-rs/tracing/issues/1831
|
||||
#[allow(dead_code)] // this is just here to test whether it compiles.
|
||||
#[instrument]
|
||||
#[deny(unused_braces)]
|
||||
fn repro_1831() -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
Box::pin(async move {})
|
||||
}
|
||||
|
||||
// This replicates the pattern used to implement async trait methods on nightly using the
|
||||
// `type_alias_impl_trait` feature
|
||||
#[allow(dead_code)] // this is just here to test whether it compiles.
|
||||
#[instrument(ret, err)]
|
||||
#[deny(unused_braces)]
|
||||
#[allow(clippy::manual_async_fn)]
|
||||
fn repro_1831_2() -> impl Future<Output = Result<(), Infallible>> {
|
||||
async { Ok(()) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn async_fn_only_enters_for_polls() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.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();
|
||||
});
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn async_fn_nested() {
|
||||
#[instrument]
|
||||
async fn test_async_fns_nested() {
|
||||
test_async_fns_nested_other().await
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
async fn test_async_fns_nested_other() {
|
||||
tracing::trace!(nested = true);
|
||||
}
|
||||
|
||||
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(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)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
block_on_future(async { test_async_fns_nested().await });
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn async_fn_with_async_trait() {
|
||||
use async_trait::async_trait;
|
||||
|
||||
// test the correctness of the metadata obtained by #[instrument]
|
||||
// (function name, functions parameters) when async-trait is used
|
||||
#[async_trait]
|
||||
pub trait TestA {
|
||||
async fn foo(&mut self, v: usize);
|
||||
}
|
||||
|
||||
// test nesting of async fns with aync-trait
|
||||
#[async_trait]
|
||||
pub trait TestB {
|
||||
async fn bar(&self);
|
||||
}
|
||||
|
||||
// test skip(self) with async-await
|
||||
#[async_trait]
|
||||
pub trait TestC {
|
||||
async fn baz(&self);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TestImpl(usize);
|
||||
|
||||
#[async_trait]
|
||||
impl TestA for TestImpl {
|
||||
#[instrument]
|
||||
async fn foo(&mut self, v: usize) {
|
||||
self.baz().await;
|
||||
self.0 = v;
|
||||
self.bar().await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl TestB for TestImpl {
|
||||
#[instrument]
|
||||
async fn bar(&self) {
|
||||
tracing::trace!(val = self.0);
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl TestC for TestImpl {
|
||||
#[instrument(skip(self))]
|
||||
async fn baz(&self) {
|
||||
tracing::trace!(val = self.0);
|
||||
}
|
||||
}
|
||||
|
||||
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(expect::field("self"))
|
||||
.with_field(expect::field("v")),
|
||||
)
|
||||
.enter(span.clone())
|
||||
.new_span(span3.clone())
|
||||
.enter(span3.clone())
|
||||
.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(expect::field("self")))
|
||||
.enter(span2.clone())
|
||||
.event(expect::event().with_fields(expect::field("val").with_value(&5u64)))
|
||||
.exit(span2.clone())
|
||||
.enter(span2.clone())
|
||||
.exit(span2.clone())
|
||||
.drop_span(span2)
|
||||
.exit(span.clone())
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
let mut test = TestImpl(2);
|
||||
block_on_future(async { test.foo(5).await });
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn async_fn_with_async_trait_and_fields_expressions() {
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
pub trait Test {
|
||||
async fn call(&mut self, v: usize);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct TestImpl;
|
||||
|
||||
impl TestImpl {
|
||||
fn foo(&self) -> usize {
|
||||
42
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Test for TestImpl {
|
||||
// check that self is correctly handled, even when using async_trait
|
||||
#[instrument(fields(val=self.foo(), val2=Self::clone(self).foo(), test=%_v+5))]
|
||||
async fn call(&mut self, _v: usize) {}
|
||||
}
|
||||
|
||||
let span = expect::span().named("call");
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone().with_field(
|
||||
expect::field("_v")
|
||||
.with_value(&5usize)
|
||||
.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)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
block_on_future(async { TestImpl.call(5).await });
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn async_fn_with_async_trait_and_fields_expressions_with_generic_parameter() {
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
pub trait Test {
|
||||
async fn call();
|
||||
async fn call_with_self(&self);
|
||||
async fn call_with_mut_self(&mut self);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct TestImpl;
|
||||
|
||||
// we also test sync functions that return futures, as they should be handled just like
|
||||
// async-trait (>= 0.1.44) functions
|
||||
impl TestImpl {
|
||||
#[instrument(fields(Self=std::any::type_name::<Self>()))]
|
||||
fn sync_fun(&self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
|
||||
let val = self.clone();
|
||||
Box::pin(async move {
|
||||
let _ = val;
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Test for TestImpl {
|
||||
// instrumenting this is currently not possible, see https://github.com/tokio-rs/tracing/issues/864#issuecomment-667508801
|
||||
//#[instrument(fields(Self=std::any::type_name::<Self>()))]
|
||||
async fn call() {}
|
||||
|
||||
#[instrument(fields(Self=std::any::type_name::<Self>()))]
|
||||
async fn call_with_self(&self) {
|
||||
self.sync_fun().await;
|
||||
}
|
||||
|
||||
#[instrument(fields(Self=std::any::type_name::<Self>()))]
|
||||
async fn call_with_mut_self(&mut self) {}
|
||||
}
|
||||
|
||||
//let span = span::mock().named("call");
|
||||
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(
|
||||
expect::field("Self").with_value(&"TestImpler")))
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)*/
|
||||
.new_span(
|
||||
span2
|
||||
.clone()
|
||||
.with_field(expect::field("Self").with_value(&std::any::type_name::<TestImpl>())),
|
||||
)
|
||||
.enter(span2.clone())
|
||||
.new_span(
|
||||
span4
|
||||
.clone()
|
||||
.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(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)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
block_on_future(async {
|
||||
TestImpl::call().await;
|
||||
TestImpl.call_with_self().await;
|
||||
TestImpl.call_with_mut_self().await
|
||||
});
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn out_of_scope_fields() {
|
||||
// Reproduces tokio-rs/tracing#1296
|
||||
|
||||
struct Thing {
|
||||
metrics: Arc<()>,
|
||||
}
|
||||
|
||||
impl Thing {
|
||||
#[instrument(skip(self, _req), fields(app_id))]
|
||||
fn call(&mut self, _req: ()) -> Pin<Box<dyn Future<Output = Arc<()>> + Send + Sync>> {
|
||||
// ...
|
||||
let metrics = self.metrics.clone();
|
||||
// ...
|
||||
Box::pin(async move {
|
||||
// ...
|
||||
metrics // cannot find value `metrics` in this scope
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
block_on_future(async {
|
||||
let mut my_thing = Thing {
|
||||
metrics: Arc::new(()),
|
||||
};
|
||||
my_thing.call(()).await;
|
||||
});
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn manual_impl_future() {
|
||||
#[allow(clippy::manual_async_fn)]
|
||||
#[instrument]
|
||||
fn manual_impl_future() -> impl Future<Output = ()> {
|
||||
async {
|
||||
tracing::trace!(poll = 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
|
||||
.new_span(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(poll_event())
|
||||
.exit(span.clone())
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
block_on_future(async {
|
||||
manual_impl_future().await;
|
||||
});
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn manual_box_pin() {
|
||||
#[instrument]
|
||||
fn manual_box_pin() -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
Box::pin(async {
|
||||
tracing::trace!(poll = 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
|
||||
.new_span(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(poll_event())
|
||||
.exit(span.clone())
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
block_on_future(async {
|
||||
manual_box_pin().await;
|
||||
});
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
213
third-party/vendor/tracing-attributes/tests/destructuring.rs
vendored
Normal file
213
third-party/vendor/tracing-attributes/tests/destructuring.rs
vendored
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
use tracing::subscriber::with_default;
|
||||
use tracing_attributes::instrument;
|
||||
use tracing_mock::*;
|
||||
|
||||
#[test]
|
||||
fn destructure_tuples() {
|
||||
#[instrument]
|
||||
fn my_fn((arg1, arg2): (usize, usize)) {}
|
||||
|
||||
let span = expect::span().named("my_fn");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone().with_field(
|
||||
expect::field("arg1")
|
||||
.with_value(&format_args!("1"))
|
||||
.and(expect::field("arg2").with_value(&format_args!("2")))
|
||||
.only(),
|
||||
),
|
||||
)
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
my_fn((1, 2));
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn destructure_nested_tuples() {
|
||||
#[instrument]
|
||||
fn my_fn(((arg1, arg2), (arg3, arg4)): ((usize, usize), (usize, usize))) {}
|
||||
|
||||
let span = expect::span().named("my_fn");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone().with_field(
|
||||
expect::field("arg1")
|
||||
.with_value(&format_args!("1"))
|
||||
.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)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
my_fn(((1, 2), (3, 4)));
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn destructure_refs() {
|
||||
#[instrument]
|
||||
fn my_fn(&arg1: &usize) {}
|
||||
|
||||
let span = expect::span().named("my_fn");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone()
|
||||
.with_field(expect::field("arg1").with_value(&1usize).only()),
|
||||
)
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
my_fn(&1);
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn destructure_tuple_structs() {
|
||||
struct Foo(usize, usize);
|
||||
|
||||
#[instrument]
|
||||
fn my_fn(Foo(arg1, arg2): Foo) {}
|
||||
|
||||
let span = expect::span().named("my_fn");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone().with_field(
|
||||
expect::field("arg1")
|
||||
.with_value(&format_args!("1"))
|
||||
.and(expect::field("arg2").with_value(&format_args!("2")))
|
||||
.only(),
|
||||
),
|
||||
)
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
my_fn(Foo(1, 2));
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn destructure_structs() {
|
||||
struct Foo {
|
||||
bar: usize,
|
||||
baz: usize,
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
fn my_fn(
|
||||
Foo {
|
||||
bar: arg1,
|
||||
baz: arg2,
|
||||
}: Foo,
|
||||
) {
|
||||
let _ = (arg1, arg2);
|
||||
}
|
||||
|
||||
let span = expect::span().named("my_fn");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone().with_field(
|
||||
expect::field("arg1")
|
||||
.with_value(&format_args!("1"))
|
||||
.and(expect::field("arg2").with_value(&format_args!("2")))
|
||||
.only(),
|
||||
),
|
||||
)
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
my_fn(Foo { bar: 1, baz: 2 });
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn destructure_everything() {
|
||||
struct Foo {
|
||||
bar: Bar,
|
||||
baz: (usize, usize),
|
||||
qux: NoDebug,
|
||||
}
|
||||
struct Bar((usize, usize));
|
||||
struct NoDebug;
|
||||
|
||||
#[instrument]
|
||||
fn my_fn(
|
||||
&Foo {
|
||||
bar: Bar((arg1, arg2)),
|
||||
baz: (arg3, arg4),
|
||||
..
|
||||
}: &Foo,
|
||||
) {
|
||||
let _ = (arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
let span = expect::span().named("my_fn");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone().with_field(
|
||||
expect::field("arg1")
|
||||
.with_value(&format_args!("1"))
|
||||
.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)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
let foo = Foo {
|
||||
bar: Bar((1, 2)),
|
||||
baz: (3, 4),
|
||||
qux: NoDebug,
|
||||
};
|
||||
let _ = foo.qux; // to eliminate unused field warning
|
||||
my_fn(&foo);
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
327
third-party/vendor/tracing-attributes/tests/err.rs
vendored
Normal file
327
third-party/vendor/tracing-attributes/tests/err.rs
vendored
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
use tracing::subscriber::with_default;
|
||||
use tracing::Level;
|
||||
use tracing_attributes::instrument;
|
||||
use tracing_mock::*;
|
||||
use tracing_subscriber::filter::EnvFilter;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::num::TryFromIntError;
|
||||
|
||||
#[instrument(err)]
|
||||
fn err() -> Result<u8, TryFromIntError> {
|
||||
u8::try_from(1234)
|
||||
}
|
||||
|
||||
#[instrument(err)]
|
||||
fn err_suspicious_else() -> Result<u8, TryFromIntError> {
|
||||
{}
|
||||
u8::try_from(1234)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let span = expect::span().named("err");
|
||||
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().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);
|
||||
future.await.ok();
|
||||
u8::try_from(1234)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_async() {
|
||||
let span = expect::span().named("err_async");
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(
|
||||
expect::event()
|
||||
.with_fields(expect::field("awaiting").with_value(&true))
|
||||
.at_level(Level::TRACE),
|
||||
)
|
||||
.exit(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(expect::event().at_level(Level::ERROR))
|
||||
.exit(span.clone())
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
with_default(subscriber, || {
|
||||
block_on_future(async { err_async(2).await }).ok();
|
||||
});
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[instrument(err)]
|
||||
fn err_mut(out: &mut u8) -> Result<(), TryFromIntError> {
|
||||
*out = u8::try_from(1234)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mut() {
|
||||
let span = expect::span().named("err_mut");
|
||||
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_mut(&mut 0).ok());
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[instrument(err)]
|
||||
async fn err_mut_async(polls: usize, out: &mut u8) -> Result<(), TryFromIntError> {
|
||||
let future = PollN::new_ok(polls);
|
||||
tracing::trace!(awaiting = true);
|
||||
future.await.ok();
|
||||
*out = u8::try_from(1234)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mut_async() {
|
||||
let span = expect::span().named("err_mut_async");
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(
|
||||
expect::event()
|
||||
.with_fields(expect::field("awaiting").with_value(&true))
|
||||
.at_level(Level::TRACE),
|
||||
)
|
||||
.exit(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(expect::event().at_level(Level::ERROR))
|
||||
.exit(span.clone())
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
with_default(subscriber, || {
|
||||
block_on_future(async { err_mut_async(2, &mut 0).await }).ok();
|
||||
});
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impl_trait_return_type() {
|
||||
// Reproduces https://github.com/tokio-rs/tracing/issues/1227
|
||||
|
||||
#[instrument(err)]
|
||||
fn returns_impl_trait(x: usize) -> Result<impl Iterator<Item = usize>, String> {
|
||||
Ok(0..x)
|
||||
}
|
||||
|
||||
let span = expect::span().named("returns_impl_trait");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone()
|
||||
.with_field(expect::field("x").with_value(&10usize).only()),
|
||||
)
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
for _ in returns_impl_trait(10).unwrap() {
|
||||
// nop
|
||||
}
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[instrument(err(Debug))]
|
||||
fn err_dbg() -> Result<u8, TryFromIntError> {
|
||||
u8::try_from(1234)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_err_dbg() {
|
||||
let span = expect::span().named("err_dbg");
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(
|
||||
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
|
||||
// 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().ok());
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_err_display_default() {
|
||||
let span = expect::span().named("err");
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(
|
||||
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)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
with_default(subscriber, || err().ok());
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_err_custom_target() {
|
||||
let filter: EnvFilter = "my_target=error".parse().expect("filter should parse");
|
||||
let span = expect::span().named("error_span").with_target("my_target");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(
|
||||
expect::event()
|
||||
.at_level(Level::ERROR)
|
||||
.with_target("my_target"),
|
||||
)
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
let subscriber = subscriber.with(filter);
|
||||
|
||||
with_default(subscriber, || {
|
||||
let error_span = tracing::error_span!(target: "my_target", "error_span");
|
||||
|
||||
{
|
||||
let _enter = error_span.enter();
|
||||
tracing::error!(target: "my_target", "This should display")
|
||||
}
|
||||
});
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[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();
|
||||
}
|
||||
159
third-party/vendor/tracing-attributes/tests/fields.rs
vendored
Normal file
159
third-party/vendor/tracing-attributes/tests/fields.rs
vendored
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
use tracing::subscriber::with_default;
|
||||
use tracing_attributes::instrument;
|
||||
use tracing_mock::{expect, span::NewSpan, subscriber};
|
||||
|
||||
#[instrument(fields(foo = "bar", dsa = true, num = 1))]
|
||||
fn fn_no_param() {}
|
||||
|
||||
#[instrument(fields(foo = "bar"))]
|
||||
fn fn_param(param: u32) {}
|
||||
|
||||
#[instrument(fields(foo = "bar", empty))]
|
||||
fn fn_empty_field() {}
|
||||
|
||||
#[instrument(fields(len = s.len()))]
|
||||
fn fn_expr_field(s: &str) {}
|
||||
|
||||
#[instrument(fields(s.len = s.len(), s.is_empty = s.is_empty()))]
|
||||
fn fn_two_expr_fields(s: &str) {
|
||||
let _ = s;
|
||||
}
|
||||
|
||||
#[instrument(fields(%s, s.len = s.len()))]
|
||||
fn fn_clashy_expr_field(s: &str) {
|
||||
let _ = s;
|
||||
}
|
||||
|
||||
#[instrument(fields(s = "s"))]
|
||||
fn fn_clashy_expr_field2(s: &str) {
|
||||
let _ = s;
|
||||
}
|
||||
|
||||
#[instrument(fields(s = &s))]
|
||||
fn fn_string(s: String) {
|
||||
let _ = s;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct HasField {
|
||||
my_field: &'static str,
|
||||
}
|
||||
|
||||
impl HasField {
|
||||
#[instrument(fields(my_field = self.my_field), skip(self))]
|
||||
fn self_expr_field(&self) {}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fields() {
|
||||
let span = expect::span().with_field(
|
||||
expect::field("foo")
|
||||
.with_value(&"bar")
|
||||
.and(expect::field("dsa").with_value(&true))
|
||||
.and(expect::field("num").with_value(&1))
|
||||
.only(),
|
||||
);
|
||||
run_test(span, || {
|
||||
fn_no_param();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expr_field() {
|
||||
let span = expect::span().with_field(
|
||||
expect::field("s")
|
||||
.with_value(&"hello world")
|
||||
.and(expect::field("len").with_value(&"hello world".len()))
|
||||
.only(),
|
||||
);
|
||||
run_test(span, || {
|
||||
fn_expr_field("hello world");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_expr_fields() {
|
||||
let span = expect::span().with_field(
|
||||
expect::field("s")
|
||||
.with_value(&"hello world")
|
||||
.and(expect::field("s.len").with_value(&"hello world".len()))
|
||||
.and(expect::field("s.is_empty").with_value(&false))
|
||||
.only(),
|
||||
);
|
||||
run_test(span, || {
|
||||
fn_two_expr_fields("hello world");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clashy_expr_field() {
|
||||
let span = expect::span().with_field(
|
||||
// Overriding the `s` field should record `s` as a `Display` value,
|
||||
// rather than as a `Debug` value.
|
||||
expect::field("s")
|
||||
.with_value(&tracing::field::display("hello world"))
|
||||
.and(expect::field("s.len").with_value(&"hello world".len()))
|
||||
.only(),
|
||||
);
|
||||
run_test(span, || {
|
||||
fn_clashy_expr_field("hello world");
|
||||
});
|
||||
|
||||
let span = expect::span().with_field(expect::field("s").with_value(&"s").only());
|
||||
run_test(span, || {
|
||||
fn_clashy_expr_field2("hello world");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn self_expr_field() {
|
||||
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",
|
||||
};
|
||||
has_field.self_expr_field();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parameters_with_fields() {
|
||||
let span = expect::span().with_field(
|
||||
expect::field("foo")
|
||||
.with_value(&"bar")
|
||||
.and(expect::field("param").with_value(&1u32))
|
||||
.only(),
|
||||
);
|
||||
run_test(span, || {
|
||||
fn_param(1);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_field() {
|
||||
let span = expect::span().with_field(expect::field("foo").with_value(&"bar").only());
|
||||
run_test(span, || {
|
||||
fn_empty_field();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_field() {
|
||||
let span = expect::span().with_field(expect::field("s").with_value(&"hello world").only());
|
||||
run_test(span, || {
|
||||
fn_string(String::from("hello world"));
|
||||
});
|
||||
}
|
||||
|
||||
fn run_test<F: FnOnce() -> T, T>(span: NewSpan, fun: F) {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(span)
|
||||
.enter(expect::span())
|
||||
.exit(expect::span())
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, fun);
|
||||
handle.assert_finished();
|
||||
}
|
||||
101
third-party/vendor/tracing-attributes/tests/follows_from.rs
vendored
Normal file
101
third-party/vendor/tracing-attributes/tests/follows_from.rs
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
use tracing::{subscriber::with_default, Id, Level, Span};
|
||||
use tracing_attributes::instrument;
|
||||
use tracing_mock::*;
|
||||
|
||||
#[instrument(follows_from = causes, skip(causes))]
|
||||
fn with_follows_from_sync(causes: impl IntoIterator<Item = impl Into<Option<Id>>>) {}
|
||||
|
||||
#[instrument(follows_from = causes, skip(causes))]
|
||||
async fn with_follows_from_async(causes: impl IntoIterator<Item = impl Into<Option<Id>>>) {}
|
||||
|
||||
#[instrument(follows_from = [&Span::current()])]
|
||||
fn follows_from_current() {}
|
||||
|
||||
#[test]
|
||||
fn follows_from_sync_test() {
|
||||
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())
|
||||
.new_span(cause_b.clone())
|
||||
.new_span(cause_c.clone())
|
||||
.new_span(consequence.clone())
|
||||
.follows_from(consequence.clone(), cause_a)
|
||||
.follows_from(consequence.clone(), cause_b)
|
||||
.follows_from(consequence.clone(), cause_c)
|
||||
.enter(consequence.clone())
|
||||
.exit(consequence)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
let cause_a = tracing::span!(Level::TRACE, "cause_a");
|
||||
let cause_b = tracing::span!(Level::TRACE, "cause_b");
|
||||
let cause_c = tracing::span!(Level::TRACE, "cause_c");
|
||||
|
||||
with_follows_from_sync(&[cause_a, cause_b, cause_c])
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn follows_from_async_test() {
|
||||
let cause_a = 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())
|
||||
.new_span(cause_b.clone())
|
||||
.new_span(cause_c.clone())
|
||||
.new_span(consequence.clone())
|
||||
.follows_from(consequence.clone(), cause_a)
|
||||
.follows_from(consequence.clone(), cause_b)
|
||||
.follows_from(consequence.clone(), cause_c)
|
||||
.enter(consequence.clone())
|
||||
.exit(consequence.clone())
|
||||
.enter(consequence.clone())
|
||||
.exit(consequence)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
block_on_future(async {
|
||||
let cause_a = tracing::span!(Level::TRACE, "cause_a");
|
||||
let cause_b = tracing::span!(Level::TRACE, "cause_b");
|
||||
let cause_c = tracing::span!(Level::TRACE, "cause_c");
|
||||
|
||||
with_follows_from_async(&[cause_a, cause_b, cause_c]).await
|
||||
})
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn follows_from_current_test() {
|
||||
let cause = expect::span().named("cause");
|
||||
let consequence = expect::span().named("follows_from_current");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(cause.clone())
|
||||
.enter(cause.clone())
|
||||
.new_span(consequence.clone())
|
||||
.follows_from(consequence.clone(), cause.clone())
|
||||
.enter(consequence.clone())
|
||||
.exit(consequence)
|
||||
.exit(cause)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
tracing::span!(Level::TRACE, "cause").in_scope(follows_from_current)
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
252
third-party/vendor/tracing-attributes/tests/instrument.rs
vendored
Normal file
252
third-party/vendor/tracing-attributes/tests/instrument.rs
vendored
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
use tracing::subscriber::with_default;
|
||||
use tracing::Level;
|
||||
use tracing_attributes::instrument;
|
||||
use tracing_mock::*;
|
||||
|
||||
// Reproduces a compile error when an instrumented function body contains inner
|
||||
// attributes (https://github.com/tokio-rs/tracing/issues/2294).
|
||||
#[deny(unused_variables)]
|
||||
#[instrument]
|
||||
fn repro_2294() {
|
||||
#![allow(unused_variables)]
|
||||
let i = 42;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn override_everything() {
|
||||
#[instrument(target = "my_target", level = "debug")]
|
||||
fn my_fn() {}
|
||||
|
||||
#[instrument(level = Level::DEBUG, target = "my_target")]
|
||||
fn my_other_fn() {}
|
||||
|
||||
let span = expect::span()
|
||||
.named("my_fn")
|
||||
.at_level(Level::DEBUG)
|
||||
.with_target("my_target");
|
||||
let span2 = expect::span()
|
||||
.named("my_other_fn")
|
||||
.at_level(Level::DEBUG)
|
||||
.with_target("my_target");
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(span.clone())
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.new_span(span2.clone())
|
||||
.enter(span2.clone())
|
||||
.exit(span2.clone())
|
||||
.drop_span(span2)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
my_fn();
|
||||
my_other_fn();
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fields() {
|
||||
#[instrument(target = "my_target", level = "debug")]
|
||||
fn my_fn(arg1: usize, arg2: bool) {}
|
||||
|
||||
let span = expect::span()
|
||||
.named("my_fn")
|
||||
.at_level(Level::DEBUG)
|
||||
.with_target("my_target");
|
||||
|
||||
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(
|
||||
expect::field("arg1")
|
||||
.with_value(&2usize)
|
||||
.and(expect::field("arg2").with_value(&false))
|
||||
.only(),
|
||||
),
|
||||
)
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.new_span(
|
||||
span2.clone().with_field(
|
||||
expect::field("arg1")
|
||||
.with_value(&3usize)
|
||||
.and(expect::field("arg2").with_value(&true))
|
||||
.only(),
|
||||
),
|
||||
)
|
||||
.enter(span2.clone())
|
||||
.exit(span2.clone())
|
||||
.drop_span(span2)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
my_fn(2, false);
|
||||
my_fn(3, true);
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip() {
|
||||
struct UnDebug(pub u32);
|
||||
|
||||
#[instrument(target = "my_target", level = "debug", skip(_arg2, _arg3))]
|
||||
fn my_fn(arg1: usize, _arg2: UnDebug, _arg3: UnDebug) {}
|
||||
|
||||
#[instrument(target = "my_target", level = "debug", skip_all)]
|
||||
fn my_fn2(_arg1: usize, _arg2: UnDebug, _arg3: UnDebug) {}
|
||||
|
||||
let span = expect::span()
|
||||
.named("my_fn")
|
||||
.at_level(Level::DEBUG)
|
||||
.with_target("my_target");
|
||||
|
||||
let span2 = expect::span()
|
||||
.named("my_fn")
|
||||
.at_level(Level::DEBUG)
|
||||
.with_target("my_target");
|
||||
|
||||
let span3 = expect::span()
|
||||
.named("my_fn2")
|
||||
.at_level(Level::DEBUG)
|
||||
.with_target("my_target");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone()
|
||||
.with_field(expect::field("arg1").with_value(&2usize).only()),
|
||||
)
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.new_span(
|
||||
span2
|
||||
.clone()
|
||||
.with_field(expect::field("arg1").with_value(&3usize).only()),
|
||||
)
|
||||
.enter(span2.clone())
|
||||
.exit(span2.clone())
|
||||
.drop_span(span2)
|
||||
.new_span(span3.clone())
|
||||
.enter(span3.clone())
|
||||
.exit(span3.clone())
|
||||
.drop_span(span3)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
my_fn(2, UnDebug(0), UnDebug(1));
|
||||
my_fn(3, UnDebug(0), UnDebug(1));
|
||||
my_fn2(2, UnDebug(0), UnDebug(1));
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generics() {
|
||||
#[derive(Debug)]
|
||||
struct Foo;
|
||||
|
||||
#[instrument]
|
||||
fn my_fn<S, T: std::fmt::Debug>(arg1: S, arg2: T)
|
||||
where
|
||||
S: std::fmt::Debug,
|
||||
{
|
||||
}
|
||||
|
||||
let span = expect::span().named("my_fn");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone().with_field(
|
||||
expect::field("arg1")
|
||||
.with_value(&format_args!("Foo"))
|
||||
.and(expect::field("arg2").with_value(&format_args!("false"))),
|
||||
),
|
||||
)
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
my_fn(Foo, false);
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn methods() {
|
||||
#[derive(Debug)]
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
#[instrument]
|
||||
fn my_fn(&self, arg1: usize) {}
|
||||
}
|
||||
|
||||
let span = expect::span().named("my_fn");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone().with_field(
|
||||
expect::field("self")
|
||||
.with_value(&format_args!("Foo"))
|
||||
.and(expect::field("arg1").with_value(&42usize)),
|
||||
),
|
||||
)
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
let foo = Foo;
|
||||
foo.my_fn(42);
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impl_trait_return_type() {
|
||||
#[instrument]
|
||||
fn returns_impl_trait(x: usize) -> impl Iterator<Item = usize> {
|
||||
0..x
|
||||
}
|
||||
|
||||
let span = expect::span().named("returns_impl_trait");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
span.clone()
|
||||
.with_field(expect::field("x").with_value(&10usize).only()),
|
||||
)
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
for _ in returns_impl_trait(10) {
|
||||
// nop
|
||||
}
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
142
third-party/vendor/tracing-attributes/tests/levels.rs
vendored
Normal file
142
third-party/vendor/tracing-attributes/tests/levels.rs
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
use tracing::subscriber::with_default;
|
||||
use tracing::Level;
|
||||
use tracing_attributes::instrument;
|
||||
use tracing_mock::*;
|
||||
|
||||
#[test]
|
||||
fn named_levels() {
|
||||
#[instrument(level = "trace")]
|
||||
fn trace() {}
|
||||
|
||||
#[instrument(level = "Debug")]
|
||||
fn debug() {}
|
||||
|
||||
#[instrument(level = "INFO")]
|
||||
fn info() {}
|
||||
|
||||
#[instrument(level = "WARn")]
|
||||
fn warn() {}
|
||||
|
||||
#[instrument(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, || {
|
||||
trace();
|
||||
debug();
|
||||
info();
|
||||
warn();
|
||||
error();
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numeric_levels() {
|
||||
#[instrument(level = 1)]
|
||||
fn trace() {}
|
||||
|
||||
#[instrument(level = 2)]
|
||||
fn debug() {}
|
||||
|
||||
#[instrument(level = 3)]
|
||||
fn info() {}
|
||||
|
||||
#[instrument(level = 4)]
|
||||
fn warn() {}
|
||||
|
||||
#[instrument(level = 5)]
|
||||
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, || {
|
||||
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, || {
|
||||
trace();
|
||||
debug();
|
||||
info();
|
||||
warn();
|
||||
error();
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
63
third-party/vendor/tracing-attributes/tests/names.rs
vendored
Normal file
63
third-party/vendor/tracing-attributes/tests/names.rs
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use tracing::subscriber::with_default;
|
||||
use tracing_attributes::instrument;
|
||||
use tracing_mock::*;
|
||||
|
||||
#[instrument]
|
||||
fn default_name() {}
|
||||
|
||||
#[instrument(name = "my_name")]
|
||||
fn custom_name() {}
|
||||
|
||||
// XXX: it's weird that we support both of these forms, but apparently we
|
||||
// managed to release a version that accepts both syntax, so now we have to
|
||||
// support it! yay!
|
||||
#[instrument("my_other_name")]
|
||||
fn custom_name_no_equals() {}
|
||||
|
||||
#[test]
|
||||
fn default_name_test() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.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, || {
|
||||
default_name();
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_name_test() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.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, || {
|
||||
custom_name();
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_name_no_equals_test() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.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, || {
|
||||
custom_name_no_equals();
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
102
third-party/vendor/tracing-attributes/tests/parents.rs
vendored
Normal file
102
third-party/vendor/tracing-attributes/tests/parents.rs
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
use tracing::{subscriber::with_default, Id, Level};
|
||||
use tracing_attributes::instrument;
|
||||
use tracing_mock::*;
|
||||
|
||||
#[instrument]
|
||||
fn with_default_parent() {}
|
||||
|
||||
#[instrument(parent = parent_span, skip(parent_span))]
|
||||
fn with_explicit_parent<P>(parent_span: P)
|
||||
where
|
||||
P: Into<Option<Id>>,
|
||||
{
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_parent_test() {
|
||||
let contextual_parent = expect::span().named("contextual_parent");
|
||||
let child = expect::span().named("with_default_parent");
|
||||
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
contextual_parent
|
||||
.clone()
|
||||
.with_contextual_parent(None)
|
||||
.with_explicit_parent(None),
|
||||
)
|
||||
.new_span(
|
||||
child
|
||||
.clone()
|
||||
.with_contextual_parent(Some("contextual_parent"))
|
||||
.with_explicit_parent(None),
|
||||
)
|
||||
.enter(child.clone())
|
||||
.exit(child.clone())
|
||||
.enter(contextual_parent.clone())
|
||||
.new_span(
|
||||
child
|
||||
.clone()
|
||||
.with_contextual_parent(Some("contextual_parent"))
|
||||
.with_explicit_parent(None),
|
||||
)
|
||||
.enter(child.clone())
|
||||
.exit(child)
|
||||
.exit(contextual_parent)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
let contextual_parent = tracing::span!(Level::TRACE, "contextual_parent");
|
||||
|
||||
with_default_parent();
|
||||
|
||||
contextual_parent.in_scope(|| {
|
||||
with_default_parent();
|
||||
});
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_parent_test() {
|
||||
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(
|
||||
contextual_parent
|
||||
.clone()
|
||||
.with_contextual_parent(None)
|
||||
.with_explicit_parent(None),
|
||||
)
|
||||
.new_span(
|
||||
explicit_parent
|
||||
.with_contextual_parent(None)
|
||||
.with_explicit_parent(None),
|
||||
)
|
||||
.enter(contextual_parent.clone())
|
||||
.new_span(
|
||||
child
|
||||
.clone()
|
||||
.with_contextual_parent(Some("contextual_parent"))
|
||||
.with_explicit_parent(Some("explicit_parent")),
|
||||
)
|
||||
.enter(child.clone())
|
||||
.exit(child)
|
||||
.exit(contextual_parent)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
let contextual_parent = tracing::span!(Level::INFO, "contextual_parent");
|
||||
let explicit_parent = tracing::span!(Level::INFO, "explicit_parent");
|
||||
|
||||
contextual_parent.in_scope(|| {
|
||||
with_explicit_parent(&explicit_parent);
|
||||
});
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
307
third-party/vendor/tracing-attributes/tests/ret.rs
vendored
Normal file
307
third-party/vendor/tracing-attributes/tests/ret.rs
vendored
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
use std::convert::TryFrom;
|
||||
use std::num::TryFromIntError;
|
||||
use tracing_mock::*;
|
||||
|
||||
use tracing::{subscriber::with_default, Level};
|
||||
use tracing_attributes::instrument;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
#[instrument(ret)]
|
||||
fn ret() -> i32 {
|
||||
42
|
||||
}
|
||||
|
||||
#[instrument(target = "my_target", ret)]
|
||||
fn ret_with_target() -> i32 {
|
||||
42
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let span = expect::span().named("ret");
|
||||
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);
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_custom_target() {
|
||||
let filter: EnvFilter = "my_target=info".parse().expect("filter should parse");
|
||||
let span = expect::span()
|
||||
.named("ret_with_target")
|
||||
.with_target("my_target");
|
||||
|
||||
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)
|
||||
.with_target("my_target"),
|
||||
)
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
let subscriber = subscriber.with(filter);
|
||||
|
||||
with_default(subscriber, ret_with_target);
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[instrument(level = "warn", ret)]
|
||||
fn ret_warn() -> i32 {
|
||||
42
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_warn() {
|
||||
let span = expect::span().named("ret_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::WARN),
|
||||
)
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, ret_warn);
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[instrument(ret)]
|
||||
fn ret_mut(a: &mut i32) -> i32 {
|
||||
*a *= 2;
|
||||
tracing::info!(?a);
|
||||
*a
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mut() {
|
||||
let span = expect::span().named("ret_mut");
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(
|
||||
expect::event()
|
||||
.with_fields(expect::field("a").with_value(&tracing::field::display(2)))
|
||||
.at_level(Level::INFO),
|
||||
)
|
||||
.event(
|
||||
expect::event()
|
||||
.with_fields(expect::field("return").with_value(&tracing::field::debug(2)))
|
||||
.at_level(Level::INFO),
|
||||
)
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || ret_mut(&mut 1));
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[instrument(ret)]
|
||||
async fn ret_async() -> i32 {
|
||||
42
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_async() {
|
||||
let span = expect::span().named("ret_async");
|
||||
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())
|
||||
.enter(span.clone())
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || block_on_future(async { ret_async().await }));
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[instrument(ret)]
|
||||
fn ret_impl_type() -> impl Copy {
|
||||
42
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_impl_type() {
|
||||
let span = expect::span().named("ret_impl_type");
|
||||
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_impl_type);
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[instrument(ret(Display))]
|
||||
fn ret_display() -> i32 {
|
||||
42
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dbg() {
|
||||
let span = expect::span().named("ret_display");
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(
|
||||
expect::event()
|
||||
.with_fields(expect::field("return").with_value(&tracing::field::display(42)))
|
||||
.at_level(Level::INFO),
|
||||
)
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, ret_display);
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[instrument(err, ret)]
|
||||
fn ret_and_err() -> Result<u8, TryFromIntError> {
|
||||
u8::try_from(1234)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ret_and_err() {
|
||||
let span = expect::span().named("ret_and_err");
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(span.clone())
|
||||
.enter(span.clone())
|
||||
.event(
|
||||
expect::event()
|
||||
.with_fields(
|
||||
expect::field("error")
|
||||
.with_value(&tracing::field::display(u8::try_from(1234).unwrap_err()))
|
||||
.only(),
|
||||
)
|
||||
.at_level(Level::ERROR),
|
||||
)
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || ret_and_err().ok());
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[instrument(err, ret)]
|
||||
fn ret_and_ok() -> Result<u8, TryFromIntError> {
|
||||
u8::try_from(123)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ret_and_ok() {
|
||||
let span = expect::span().named("ret_and_ok");
|
||||
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(u8::try_from(123).unwrap()))
|
||||
.only(),
|
||||
)
|
||||
.at_level(Level::INFO),
|
||||
)
|
||||
.exit(span.clone())
|
||||
.drop_span(span)
|
||||
.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();
|
||||
}
|
||||
109
third-party/vendor/tracing-attributes/tests/targets.rs
vendored
Normal file
109
third-party/vendor/tracing-attributes/tests/targets.rs
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
use tracing::subscriber::with_default;
|
||||
use tracing_attributes::instrument;
|
||||
use tracing_mock::*;
|
||||
|
||||
#[instrument]
|
||||
fn default_target() {}
|
||||
|
||||
#[instrument(target = "my_target")]
|
||||
fn custom_target() {}
|
||||
|
||||
mod my_mod {
|
||||
use tracing_attributes::instrument;
|
||||
|
||||
pub const MODULE_PATH: &str = module_path!();
|
||||
|
||||
#[instrument]
|
||||
pub fn default_target() {}
|
||||
|
||||
#[instrument(target = "my_other_target")]
|
||||
pub fn custom_target() {}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_targets() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
expect::span()
|
||||
.named("default_target")
|
||||
.with_target(module_path!()),
|
||||
)
|
||||
.enter(
|
||||
expect::span()
|
||||
.named("default_target")
|
||||
.with_target(module_path!()),
|
||||
)
|
||||
.exit(
|
||||
expect::span()
|
||||
.named("default_target")
|
||||
.with_target(module_path!()),
|
||||
)
|
||||
.new_span(
|
||||
expect::span()
|
||||
.named("default_target")
|
||||
.with_target(my_mod::MODULE_PATH),
|
||||
)
|
||||
.enter(
|
||||
expect::span()
|
||||
.named("default_target")
|
||||
.with_target(my_mod::MODULE_PATH),
|
||||
)
|
||||
.exit(
|
||||
expect::span()
|
||||
.named("default_target")
|
||||
.with_target(my_mod::MODULE_PATH),
|
||||
)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
default_target();
|
||||
my_mod::default_target();
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_targets() {
|
||||
let (subscriber, handle) = subscriber::mock()
|
||||
.new_span(
|
||||
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(
|
||||
expect::span()
|
||||
.named("custom_target")
|
||||
.with_target("my_other_target"),
|
||||
)
|
||||
.exit(
|
||||
expect::span()
|
||||
.named("custom_target")
|
||||
.with_target("my_other_target"),
|
||||
)
|
||||
.only()
|
||||
.run_with_handle();
|
||||
|
||||
with_default(subscriber, || {
|
||||
custom_target();
|
||||
my_mod::custom_target();
|
||||
});
|
||||
|
||||
handle.assert_finished();
|
||||
}
|
||||
14
third-party/vendor/tracing-attributes/tests/ui.rs
vendored
Normal file
14
third-party/vendor/tracing-attributes/tests/ui.rs
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// Only test on nightly, since UI tests are bound to change over time
|
||||
#[rustversion::stable]
|
||||
#[test]
|
||||
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");
|
||||
}
|
||||
46
third-party/vendor/tracing-attributes/tests/ui/async_instrument.rs
vendored
Normal file
46
third-party/vendor/tracing-attributes/tests/ui/async_instrument.rs
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#![allow(unreachable_code)]
|
||||
|
||||
#[tracing::instrument]
|
||||
async fn unit() {
|
||||
""
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
async fn simple_mismatch() -> String {
|
||||
""
|
||||
}
|
||||
|
||||
// FIXME: this span is still pretty poor
|
||||
#[tracing::instrument]
|
||||
async fn opaque_unsatisfied() -> impl std::fmt::Display {
|
||||
("",)
|
||||
}
|
||||
|
||||
struct Wrapper<T>(T);
|
||||
|
||||
#[tracing::instrument]
|
||||
async fn mismatch_with_opaque() -> Wrapper<impl std::fmt::Display> {
|
||||
""
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
async fn early_return_unit() {
|
||||
if true {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
async fn early_return() -> String {
|
||||
if true {
|
||||
return "";
|
||||
}
|
||||
String::new()
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
async fn extra_semicolon() -> i32 {
|
||||
1;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
98
third-party/vendor/tracing-attributes/tests/ui/async_instrument.stderr
vendored
Normal file
98
third-party/vendor/tracing-attributes/tests/ui/async_instrument.stderr
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
error[E0308]: mismatched types
|
||||
--> tests/ui/async_instrument.rs:5:5
|
||||
|
|
||||
5 | ""
|
||||
| ^^ expected `()`, found `&str`
|
||||
|
|
||||
note: return type inferred to be `()` here
|
||||
--> tests/ui/async_instrument.rs:4:10
|
||||
|
|
||||
4 | async fn unit() {
|
||||
| ^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/async_instrument.rs:10:5
|
||||
|
|
||||
10 | ""
|
||||
| ^^- help: try using a conversion method: `.to_string()`
|
||||
| |
|
||||
| expected `String`, found `&str`
|
||||
|
|
||||
note: return type inferred to be `String` here
|
||||
--> tests/ui/async_instrument.rs:9:31
|
||||
|
|
||||
9 | async fn simple_mismatch() -> String {
|
||||
| ^^^^^^
|
||||
|
||||
error[E0277]: `(&str,)` doesn't implement `std::fmt::Display`
|
||||
--> tests/ui/async_instrument.rs:14:1
|
||||
|
|
||||
14 | #[tracing::instrument]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ `(&str,)` cannot be formatted with the default formatter
|
||||
|
|
||||
= help: the trait `std::fmt::Display` is not implemented for `(&str,)`
|
||||
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
||||
= note: this error originates in the attribute macro `tracing::instrument` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0277]: `(&str,)` doesn't implement `std::fmt::Display`
|
||||
--> tests/ui/async_instrument.rs:15:34
|
||||
|
|
||||
15 | async fn opaque_unsatisfied() -> impl std::fmt::Display {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ `(&str,)` cannot be formatted with the default formatter
|
||||
|
|
||||
= help: the trait `std::fmt::Display` is not implemented for `(&str,)`
|
||||
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/async_instrument.rs:23:5
|
||||
|
|
||||
23 | ""
|
||||
| ^^ expected `Wrapper<_>`, found `&str`
|
||||
|
|
||||
= note: expected struct `Wrapper<_>`
|
||||
found reference `&'static str`
|
||||
note: return type inferred to be `Wrapper<_>` here
|
||||
--> tests/ui/async_instrument.rs:22:36
|
||||
|
|
||||
22 | async fn mismatch_with_opaque() -> Wrapper<impl std::fmt::Display> {
|
||||
| ^^^^^^^
|
||||
help: try wrapping the expression in `Wrapper`
|
||||
|
|
||||
23 | Wrapper("")
|
||||
| ++++++++ +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/async_instrument.rs:29:16
|
||||
|
|
||||
29 | return "";
|
||||
| ^^ expected `()`, found `&str`
|
||||
|
|
||||
note: return type inferred to be `()` here
|
||||
--> tests/ui/async_instrument.rs:27:10
|
||||
|
|
||||
27 | async fn early_return_unit() {
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/async_instrument.rs:36:16
|
||||
|
|
||||
36 | return "";
|
||||
| ^^- help: try using a conversion method: `.to_string()`
|
||||
| |
|
||||
| expected `String`, found `&str`
|
||||
|
|
||||
note: return type inferred to be `String` here
|
||||
--> tests/ui/async_instrument.rs:34:28
|
||||
|
|
||||
34 | async fn early_return() -> String {
|
||||
| ^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/async_instrument.rs:42:35
|
||||
|
|
||||
42 | async fn extra_semicolon() -> i32 {
|
||||
| ___________________________________^
|
||||
43 | | 1;
|
||||
| | - help: remove this semicolon to return this value
|
||||
44 | | }
|
||||
| |_^ expected `i32`, found `()`
|
||||
8
third-party/vendor/tracing-attributes/tests/ui/const_instrument.rs
vendored
Normal file
8
third-party/vendor/tracing-attributes/tests/ui/const_instrument.rs
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#![allow(unreachable_code)]
|
||||
|
||||
#[tracing::instrument]
|
||||
const fn unit() {
|
||||
""
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
15
third-party/vendor/tracing-attributes/tests/ui/const_instrument.stderr
vendored
Normal file
15
third-party/vendor/tracing-attributes/tests/ui/const_instrument.stderr
vendored
Normal file
|
|
@ -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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue