The `tracing-mock` crate provides a mock collector (and a subscriber for
use by the tests in the `tracing-subscriber` crate) which is able to
make assertions about what diagnostics are emitted.
These assertions are defined by structs that match on events, span, and
their fields and metadata. The structs that matched these objects have
been called, up until now, mocks, however this terminology may be
misleading, as the created objects don't mock anything.
There were two different names for similar functionality with `only()`
and `done()` on fields and collectors/subscribers respectively. Using a
single name for these may make it easier to onboard onto `tracing-mock`.
To reduce confusion, these structs have been split into two categories:
mocks and expectations.
Additionally, the `done()` function on the `Collector` and `Subscriber`
mocks has been replaced with `only()`. This matches the similar function
for `ExpectedField`, and may be more intuitive.
The mocks replace some component in the tracing ecosystem when a library
is under test. The expectations define the assertions we wish to make
about traces received by the mocks.
Mocks (per module):
* collector - `MockCollector`, no change
* subscriber - `MockSubscriber`, renamed from `ExpectSubscriber`
Expectations (per module):
* event - `ExpectedEvent`, renamed from `MockEvent`
* span - `ExpectedSpan`, renamed from `MockSpan`
* field - `ExpectedField` and `ExpectedFields`, renamed from `MockField`
and `Expected`. Also `ExpectedValue` renamed from `MockValue`.
* metadata - `ExpectedMetadata`, renamed from `Expected`
Refs: #539
## Motivation
Currently it is not possible to disable ANSI in `fmt::Subscriber`
without enabling the "ansi" crate feature. This makes it difficult for
users to implement interoperable settings that are controllable with
crate features without having to pull in the dependencies "ansi" does.
I hit this while writing an application with multiple logging options
set during compile-time and I wanted to cut down on dependencies if
possible.
## Solution
This changes `fmt::Subscriber::with_ansi()` to not require the "ansi"
feature flag. This way, `with_ansi(false)` can be called even when the
"ansi" feature is disabled. Calling `with_ansi(true)` when the "ansi"
feature is not enabled will panic in debug mode, or print a warning if
debug assertions are disabled.
Co-authored-by: daxpedda <daxpedda@gmail.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
When the `instrument` attribute is used on a function with inner
attributes, the proc macro generates code above the attributes within
the function block that causes compilation errors. These should be
parsed out separately and handled.
Fixes#2294
## Solution
I updated `MaybeItemFn` and `MaybeItemFnRef` to so they hold both the
outer and inner attributes for the instrumented function and updated the
codegen to inlcude them in the appropriate locations.
I couldn't preserve the existing implementation of
`From<&'_ ItemFn> for MaybeItemFnRef<'_, Box<Block>>`, because it is
now necessary to separate the inner and outer attributes of the
`ItemFn` into two separate `Vec`s. That implementation was replaced
with a `From<ItemFn> for MaybeItemFn`, which uses `Iterator::partition`
to separate out the inner and outer attributes.
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
The `async_fn` test file in `tracing-attributes` contains several
functions that exist just to test whether they _compile_, rather than
make assertions about their behavior. Because these functions are never
called, they (naturally) emit dead code warnings.
This commit adds `#[allow(dead_code)]` to the compilation tests, plus a
comment explaining why we do this.
## Motivation
When using an `async` block (as an alternative to `async fn`, e.g. when
implementing a trait), `#[instrument]` adds extra braces around the
wrapped `async` block. This causes `rustc` to emit an `unused_braces`
lint in some cases (usually for single-line `async` blocks, as far as I
can tell). See #1831 for an example.
## Solution
Since the `async` block extracted by `AsyncInfo::from_fn` already has
braces around its statements, there's no need to wrap it with additional
braces. This updates `gen_block` to remove those extra braces when
generating the code providing the value of
`__tracing_instrument_future`.
- [x] add repros for `unused_braces` issue
- [x] remove extra braces from async blocks
Fixes#1831
... instead of `#[path = ""]` importing it everywhere.
Make sure to use a diff review tool that understands file renaming 😅
(GitHub's diff view does.)
## Motivation
Transparency: I want to use the mocking functionality in the development
of a tracing component out-of-tree.
Additionally, this reduces the use of `#[path] mod` and file
multiple-inclusion, which aren't that great of a practice.
## Solution
The tracing test support module was already well self-contained, due to
being `#[path] mod` used in multiple places. As such, extracting it to
its own crate is rather mechanical, with no surprising blockers.
We additionally move the tracing-futures support module contents into
tracing_mock, for convenience. The one function which relies on
tokio-test is made optional.
It's a reasonable result for this functionality to stay unpublished, and
only used inside the repo, but pulling it out into a directly reusable
chunk instead of abusing the module system to reuse it via
multiple-inclusion is an improvement to code structure and
modularization.
This should take care of half of #1863, meaning it should instrument
functions returning an unboxed `async move` block.
This unfortunately does not cover generic `impl Future` returns, such as
`std::future::ready()` and similar :-(
## Motivation
Apparently, using `quote_spanned!` can trigger a Clippy bug where the
text `else`, even inside a comment, _may_ cause the
`suspicious_else_formatting` lint to be triggered incorrectly (see
rust-lang/rust-clippy#7760 and rust-lang/rust-clippy#6249). This causes
the lint to fire in some cases when the `#[instrument]` attribute is
used on `async fn`s. See issue #1613 for details.
## Solution
It turns out that some of the uses of `quote_spanned!` in the
`tracing-attributes` code generation are not needed. We really only need
`quote_spanned!` when actually interpolating the user provided code into
a block, not in the `tracing-attributes` code that inserts the generated
code for producing the span etc. Replacing some of these
`quote_spanned!` uses with the normal `quote!` macro still generates
correct location diagnostics for errors in the user code, but fixes the
incorrect clippy lint.
I've added a few test cases that should reproduce the bug.
Fixes#1613
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
The changes in #1607 introduced a potential compilation error when using
the `#[instrument]` attribute on `async fn`s that return a type that
includes a closure or is otherwise unnameable. This is because the
future's body code was quoted in two separate places in order to have a
separate branch when the span is statically disabled. This means that
when a closure is returned, it will technically have two distinct types
based on whether or not the span is enabled, since it originates from
two separate source code locations (although `quote_spanned!` obscures
this, so the compiler diagnostic will appear to have two closures
originating from the same location).
## Solution
This branch fixes this issue by changing the code generated for
`#[instrument]`ed async functions. Unfortunately, for async functions,
we can't have the optimization of not creating the span at all when the
level is disabled, because we need to create the span _before_ creating
the future, as it may borrow arguments.
I've also added tests reproducing issue #1615Fixes#1615
Currently, `tracing-attributes` generates a `let _ = ();` in between the
`if tracing::level_enabled!(...) {}` and the function body. This is
intended to suppress the `clippy::suspicious_else_formatting` lint,
which is generated when an `if` is followed immediately by a block with
no whitespace in between. Since we can't add whitespace in the generated
code (as `quote` produces a stream of _rust tokens_, not text), we
can't suppress the lint without adding a no-op statement.
However, unfortunately, the no-op let triggers a _different_ lint
(`clippy::let_unit_value`), when `clippy::pedantic` is enabled. This is
kind of annoying for some users.
This branch changes the code to suppress the
`suspicious_else_formatting` lint using `#[allow(...)]` attributes,
instead. The warning is turned back on inside of user code, since users
probably want the warning.
The default behavior of `tracing::instrument` attribution will record
all of the function arguments as `fmt::Debug`, which is overwhelmed and
unnecessary for those primitive types, such as `bool`, `u8`, `i8`,
`u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `usize`, and `isize`. Another
concerning reason is that we‘ll lose the type info of those primitive
types when record by a `Visitor`, while those type infos is essential to
some people. For example, I need to show my spans in Jaeger UI.
Make the `tracing::instrument` records other function arguments as
`fmt::Debug ` while not for those primitive types.
However, I'm not good at naming. Maybe the `RecordType` enum and its
variant aren't a good name? I'd love to seek suggestions. Thanks.
This backports #1297 from `master`.
Fixes#1296.
I had forgotten to use all the input statements in #1228, so we would
delete nearly all the statement of sync functions that return a boxed
future :/
This backports #1228 from `master` to `v0.1.x`.
It works with both the old and new version of async-trait (except for
one doc test that failed previously, and that works with the new
version). One nice thing is that the code is simpler (e.g.g no self
renaming to _self, which will enable some simplifications in the
future).
A minor nitpick is that I disliked the deeply nested pattern matching in
get_async_trait_kind (previously: get_async_trait_function), so I
"flattened" that a bit.
Fixes #1219.
Co-authored-by: Simon THOBY <git@nightmared.fr>
This backports PR #991 to v0.1.x. This is primarily necessary for the MSRV
bump, since some dependencies no longer compile on Rust 1.40.0.
This has already been approved on `master`, in PR #991, so it should be
fine to ship.
## Motivation
This will avoid breaking CI on new releases of clippy. It also makes the
code a little easier to read.
## Solution
- Convert `match val { pat => true, _ => false }` to `matches!(val, pat)`
- Remove unnecessary closures
- Convert `self: &mut Self` to `&mut self`
This bumps the MSRV to 1.42.0 for `matches!`.
The latest version of rust is 1.46.0, so as per
https://github.com/tokio-rs/tracing#supported-rust-versions this is not
considered a breaking change.
I didn't fix the following warning because the fix was not trivial/needed
a decision:
```
warning: you are deriving `Ord` but have implemented `PartialOrd` explicitly
--> tracing-subscriber/src/filter/env/field.rs:16:32
|
16 | #[derive(Debug, Eq, PartialEq, Ord)]
| ^^^
|
= note: `#[warn(clippy::derive_ord_xor_partial_ord)]` on by default
note: `PartialOrd` implemented here
--> tracing-subscriber/src/filter/env/field.rs:98:1
|
98 | / impl PartialOrd for Match {
99 | | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
100 | | // Ordering for `Match` directives is based first on _whether_ a value
101 | | // is matched or not. This is semantically meaningful --- we would
... |
121 | | }
122 | | }
| |_^
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
```
As a side note, this found a bug in clippy 😆https://github.com/rust-lang/rust-clippy/issues/6089
## Motivation
As outlined in #399, right now `tracing-futures` (or more precisely, the
code generated by `#[instrument]`) is not working well with async-trait.
What happens is that async-trait rewrites the trait method as a
non-async function, insides of which it pins the async method we want to
instrument, and we end up instrumenting the wrapper instead of the async
fn.
This will allow people to use traits with (seemingly) async functions
along with `#[instrument]`.
## Solution
I decided to follow the discussion at
https://github.com/dtolnay/async-trait/issues/45 and see if I could make
it working. Right now I would describe its state as "works for me, and
*should* work for everyone".
The `instrument` macro will now:
* Rewrite the block when it looks like there is async_trait involved to
wrap the internal async function instead of the wrapper generated by
`async-trait`
* Rewrite '_self' as 'self' when using #[instrument] jointly with
`async-trait`
Fixes#399
## Motivation
Currently, `tracing-futures` and `tracing-attributes` both have separate
crates for tests that require `std::future` and async/await syntax.
These date back to before these features were stable, and the tests were
separated because they could only be run on nighly Rust. This has not
been the case for a long while, and `tracing` now supports `std::future`
as the default, requiring opt-in support for `futures` 0.1. I think we
had forgotten to remove the special-cased tests when we made that
transition.
## Solution
This branch removes the special-cased test crates, and moves all
`std::future` and async/await tests into the main test dirs for these
crates. I've also removed the separate CI steps that ran these.
This should simplify things significantly!
Signed-off-by: Eliza Weisman <eliza@buoyant.io>