Most of these changes are places where lifetimes were named, but can be
elided. Then a few cases where a lifetime was elided, but actually
resolves to a named lifetime. So lots of lifetimes.
## Motivation
There has been interest around publishing tracing-mock to crates.io
for some time. In order to make this possible, documentation and some
code clean up is needed.
The `expect` module, which contains constructor functions for many of
the other `tracing-mock` modules needs documentation and examples.
This change adds documentation to the `expect` module and all the public
APIs within it. This includes doctests on all the methods which serve as
examples.
## Solution
The lint for `missing_docs` has been enabled for the entire
`tracing-mock` crate! This has been done together with all the
other lints that are enabled on the other crates in this project.
The `event::msg("message")` constructor was removed, in favor of
requiring an explicit construction via
`expect::event().with_fields(expect::msg("message"))`. This is
appropriate to reduce the API surface that would need to be supported in
the future and also because the `event::msg` constructor could be
overridden by a subsequent usage of `with_fields`. The shorthand
`expect::message()` was renamed to `expect::msg` to make this
change less burdensome.
The `span::named("name")` constructor was removed, in favor of requiring
an explicit construction via `expect::span.with_name("name")`. The
latter isn't much longer and since #3097, a string with the name can
be passed directly everywhere that an `ExpectedSpan` is required.
This change also sets the `missing_docs` lint to warn for the entire
`tracing-mock` crate, making it ready to publish (once backported).
Refs: #539
## Motivation
The `with_ancestry` methods on `NewSpan` and `ExpectedEvent` provide a
way to match whether the span or event is a contextual or explicit root
or if it has a contextual or explicit parent span.
However, in the case of matching on a contextual or explicit parent
span, only the span name could be used for matching. This is
sufficiently precise when testing tracing instrumentation in other
libraries or applications as opposed to testing tracing itself.
It is likely that a user would like to test that some span or event has
a specific span as a parent, and not just any span with a specific name,
in many cases, all the possible parent spans may have the same name.
This is the case when testing tracing instrumentation in Tokio.
## Solution
To solve this problem, the `Ancestry` struct was renamed to
`ExpectedAncestry` and in the case of expecting an explicit or
conextual parent, an `ExpectedSpan` object can be passed in. This
provides the maximum possible flexibility.
The convenience functions in the `expect` module now take
`Into<ExpectedSpan>` so that existing tests that pass a string type
object for the parent will see the same behaviour as previously and
shorthand use for expected Ids is also available.
Additionally, the span checking code has been unified between the
`MockCollector` and `MockSubscriber` cases and the assertion
descriptions have been improved to make them more readable.
Many of the methods on `MockCollector` take an `ExpectedSpan`. This
often requires significant boilerplate. For example, to expect that a
span with a specific name enters and then exits, the following code is
needed:
```rust
let span = expect::span().named("span name");
let (collector, handle) = collector::mock()
.enter(span.clone())
.exit(span)
.run_with_handle();
```
In order to make using `tracing-mock` more ergonomic and also more
compact, the `MockCollector` and `MockSubscriber` methods that previous
took an `ExpectedSpan`, are now generic over `Into<ExpectedSpan>`.
There are currently 3 implementations of `From` for `ExpectedSpan` which
allow the following shorthand uses:
`T: Into<String>` - an `ExpectedSpan` will be created that expects to
have a name specified by `T`.
```rust
let (collector, handle) = collector::mock()
.enter("span name")
.exit("span name")
.run_with_handle();
```
`&ExpectedId` - an `ExpectedSpan` will be created that expects to have
the expected Id. A reference is taken and cloned internally because the
caller always needs to use an `ExpectedId` in at least 2 calls to the
mock collector/subscriber.
```rust
let id = expect::id();
let (collector, handle) = collector::mock()
.new_span(&id)
.enter(&id)
.run_with_handle();
```
`&ExpectedSpan` - The expected span is taken by reference and cloned.
```rust
let span = expect::span().named("span name");
let (collector, handle) = collector::mock()
.enter(&span)
.exit(&span)
.run_with_handle();
```
In Rust, taking a reference to an object and immediately cloning it is
an anti-pattern. It is considered better to force the user to clone
outside the API to make the cloning explict.
However, in the case of a testing framework, it seems reasonable to
prefer a more concise API, rather than having it more explicit.
To reduce the size of this PR and to avoid unnecessary churn in other
crates, the tests within the tracing repo which use `tracing-mock` will
not be updated to use the new `Into<ExpectedSpan>` capabilities. The new
API is backwards compatible and those tests can remain as they are.
## Motivation
When recording the parent of an event or span, the `MockCollector`
treats an explicit parent of `None` (i.e. an event or span that is an
explicit root) in the same way as if there is no explicit root. This
leads to it picking up the contextual parent or treating the event or
span as a contextual root.
## Solution
This change refactors the recording of the parent to use `is_contextual`
to distinguish whether or not an explicit parent has been specified. The
actual parent is also written into an `Ancestry` enum so that the
expected and actual values can be compared in a more explicit way.
Additionally, the `Ancestry` struct has been moved into its own module and
the check behavior has been fixed. The error message has also been
unified across all cases.
Another problem with the previous API is that the two methods
`with_contextual_parent` and `with_explicit_parent` are actually
mutually exclusive, a span or event cannot be both of them. It is also a
(small) mental leap for the user to go from `with_*_parent(None)` to
understanding that this means that a span or event is a root (either
contextual or explicit).
As such, the API has been reworked into a single method `with_ancestry`,
which takes an enum with the following four variants:
* `HasExplicitParent(String)` (parent span name)
* `IsExplicitRoot`
* `HasContextualParent(String)` (parent span name)
* `IsContextualRoot`
To make the interface as useable as possible, helper functions have been
defined in the `expect` module which can be used to create the enum
variants. Specifically, these take `Into<String>` parameter for the span
name.
Given the number of different cases involved in checking ancestry,
separate integration tests have been added to `tracing-mock`
specifically for testing all the positive and negative cases when
asserting on the ancestry of events and spans.
There were two tests in `tracing-attributes` which specified both an
explicit and a contextual parent. This behavior was never intended to
work as all events and spans are either contextual or not. The tests
have been corrected to only expect one of the two.
Fixes: #2440
## Motivation
It currently isn't possible to differentiate spans with the same name,
target, and level when setting expectations on `enter`, `exit`, and
`drop_span`. This is not an issue for `tracing-mock`'s original (and
still primary) use case, which is to test `tracing` itself. However,
when testing the tracing instrumentation in library or application code,
this can be a limitation.
For example, when testing the instrumentation in tokio
(tokio-rs/tokio#6112), it isn't possible to set an expectation on which
task span is entered first, because the name, target, and level of those
spans are always identical - in fact, the spans have the same metadata
and only the field values are different.
## Solution
To make differentiating different spans possible, `ExpectId` has been
introduced. It is an opaque struct which represents a `span::Id` and can
be used to match spans from a `new_span` expectation (where a `NewSpan`
is accepted and all fields and values can be expected) through to
subsequent `enter`, `exit`, and `drop_span` expectations.
An `ExpectedId` is passed to an `ExpectedSpan` which then needs to be
expected with `MockCollector::new_span`. A clone of the `ExpectedId` (or
a clone of the `ExpectedSpan` with the `ExpectedId` already on it) will
then match the ID assigned to the span to the other span lifecycle
expectations.
The `ExpectedId` uses an `Arc<AtomicU64>` which has the ID for the new
span assigned to it, and then its clones will be matched against that
same ID.
In future changes it will also be possible to use this `ExpectedId` to
match parent spans, currently a parent is only matched by name.
This change adds documentation to the tracing-mock `field` module and
all the public APIs within it. This includes doctests on all the methods
which serve as examples.
Additionally, the `field::msg` function (which constructs a field with
name "message" and the provided value) was moved to `expect::message`.
This is part of a unification of all expectation constructors inside the
`expect` module.
Refs: #539
Co-authored-by: David Barsky <me@davidbarsky.com>
This change adds documentation to the tracing-mock span module and all
the public APIs within it. This includes doctests on all the methods
which serve as examples.
Additionally, the validation on `ExpectedSpan` was improved so that it
validates the level and target during `enter` and `exit` as well as on
`new_span`.
The method `ExpectedSpan::with_field` was renamed to `with_fields`
(plural) to match the same method on `ExpectedEvent` (and because
multiple fields can be passed to it).
A copy-paste typo was also fixed in the documentation for
`ExpectedEvent::with_contextual_parent`.
Refs: #539
Co-authored-by: David Barsky <me@davidbarsky.com>
## Motivation
There has been interest around publishing tracing-mock to crates.io
for some time. In order to make this possible, it needs to be cleaned up.
## Solution
There are some test utils in the `tracing-mock` crate which wouldn't
make sense to publish. They provide test futures that are needed in
multiple `tracing-*` crates, but would likely not be needed outside that
context.
This change moves that functionality into a separate `tracing-test`
crate, which should never be published to crates.io.
Refs: #539
Co-authored-by: David Barsky <me@davidbarsky.com>
There has been interest around publishing `tracing-mock` to crates.io
for some time. In order to make this possible, documentation and some
code clean up is needed.
This change adds documentation to the collector module itself and to all the
public APIs in the module. This includes doctests on all the methods
that serve as examples.
Additionally the implementation for the `Expect` struct has been moved
into the module with the definition, this was missed in #2369.
Refs: #539
## Motivation
There has been interest around publishing `tracing-mock` to crates.io
for some time. In order to make this possible, documentation and some
code clean up is needed.
The `subscriber` module needs documentation and examples.
## Solution
This change adds documentation to the `subscriber` module and all the public
APIs within it. This includes doctests on all the methods which serve as
examples.
The `MockSubscriberBuilder::record` method was removed as its
functionality is not implemented.
Previously, the `MockSubscriber` would verify the scope of an
`ExpectedEvent`, even if `in_scope` hadn't been called. In this case,
that would check that an event was not in a span if `in_scope` had not
been called. `tracing-subscriber` all adhere to this pattern. However it
is different to the behavior of all other expectation methods, where an
explicit call is needed to expect something, otherwise nothing is
checked. As such, the behavior has been modified to align with the rest
of the crate. The previous behavior can be achieved by calling
`in_scope(None)` to verify that an event has no scope. The documentation
for `in_scope` has been updated with an example for this case.
The tests in `tracing-subscriber` which previously verified *implicitly*
that an event had no scope (by not calling `in_scope` at all) have *not*
been modified. It is my opinion that this implicit behavior was never
required.
Refs: #539
## Motivation
There has been interest around publishing tracing-mock to crates.io
for some time. In order to make this possible, documentation and some
code clean up is needed.
The `event` module needs documentation and examples.
## Solution
This change adds documentation to the event module and all the public
APIs within it. This includes doctests on all the methods which serve as
examples.
The following pattern was applied to the description of most methods:
- Short description of expectation
- Additional clarification (where needed)
- Description of cases that cause the expectation to fail
- Examples
- Successful validation
- Unsuccesful validation
Two changes were also made in the text provided to the user when an
assertion fails for `with_explicit_parent` or `with_contextual_parent`.
One small API changes is also included:
The method `in_scope` has been placed behind the `tracing-subscriber`
feature flag as it currently only works with the `MockSubscriber`, not
with the `MockCollector`. If the feature flag is active and it is used
to set a non-empty scope, the `MockCollector` will panic with
`unimplemented` during validation.
Refs: #539
## Motivation
There has been interest around publishing `tracing-mock` to crates.io
for some time. In order to make this possible, documentation and some
code clean up is needed.
Specifically **I** want to have access to `tracing-mock` within parts of
`tokio` to write tests that ensure that the correct calling location is
picked up for all `spawn*` functions when the `tracing` feature is
enabled.
## Solution
This change starts that process by adding a README for `tracing-mock`.
The README follows the standard format for all `tracing` crates and
includes 2 examples. The README is included in the `lib.rs` docs using
`#[doc = include_str!(...)]`, so that the same documentation is included
in the crate, and the examples are tested when running doctests.
The README describes steps when using the `tracing` 1.0 from crates.io
and `tracing-mock` from the `v0.1.x` branch. The tests target the
current branch.
Co-authored-by: David Barsky <me@davidbarsky.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
* mock: change helper functions to `expect::<thing>`
The current format of test expectations in `tracing-mock` isn't ideal.
The format `span::expect` requires importing `tracing_mock::<thing>` which
may conflict with imports from other tracing crates, especially
`tracing-core`.
So we change the order and move the functions into a module called
`expect` so that:
* `event::expect` becomes `expect::event`
* `span::expect` becomes `expect::span`
* `field::expect` becomes `expect::field`
This format has two advantages.
1. It reads as natural English, e.g "expect span"
2. It is no longer common to import the modules directly.
Regarding point (2), the following format was previously common:
```rust
use tracing_mock::field;
field::expect();
```
This import of the `field` module may then conflict with importing the
same from `tracing_core`, making it necessary to rename one of the
imports.
The same code would now be written:
```rust
use tracing_mock::expect;
expect::field();
```
Which is less likely to conflict.
This change also fixes an unused warning on `MockHandle::new` when the
`tracing-subscriber` feature is not enabled.
Refs: #539
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
The `tracing-subscriber` module `tests::support` included functionality
to mock a subscriber (via the `Subscribe` trait). This code depends on
some items from `tracing_mock::collector` which should otherwise not be
public.
This change moves the mocking functionality inside `tracing-mock` behind
a feature flag. Allowing the `Expect` enum and `MockHandle::new` from
`tracing_mock::collector` to be made `pub(crate)` instead of `pub`.
Since it's now used from two different modules, the `Expect` enum has
been moved to its own module.
This requires a lot of modifications to imports so that we're not doing
wildcard imports from another crate (i.e. in `tracing-subscriber`
importing wildcards from `tracing-mock`).
Closes: #2359
This PR extends the `#[instrument]` attribute to accept an optional
`follows_from = …` argument that supplies any number of
`Span::follows_from` relationships to the generated `Span`.
## Motivation
This PR resolves#879.
## Solution
This PR largely follows the implementation strategy articulated by
@hawkw:
https://github.com/tokio-rs/tracing/issues/879#issuecomment-668168468
In that comment, @hawkw suggests taking one of two approaches:
1. each `follows_from` relationship is supplied with a distinct
`follows_from` argument
2. the `follows_from` argument is provided once, and its value is a
**list** of indirect causes
I take the second approach, since it is slightly more flexible: it
allows for the number of indirect causes to vary at runtime.
This addition is complemented by changes to `tracing-mock` to permit
making `follows_from` assertions for testing purposes.
## Motivation
Filtering by span and field requires using `EnvFilter` rather than
`Targets`. Per-subscriber filtering requires the `Filter` trait, which
`EnvFilter` does not implement.
## Solution
Implement the `Filter` trait for `EnvFilter`. PR #1973 adds additiional
methods to the `Filter` trait, which are necessary for `EnvFilter` to
implement dynamic span filtering. Now that those methods are added, we
can provide a `Filter` impl for `EnvFilter`.
In addition, we changed the globally-scoped `thread_local!` macro to use
a `ThreadLocal` struct as a field, so that multiple `EnvFilter`s used as
per-subscriber filters don't share a single span scope.
Fixes#1868
Follow-up on #1973
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Currently, filtering with `Subscribe`s is always _global_. If a
`Subscribe` performs filtering, it will disable a span or event for
_all_ subscribers that compose the current subscriber. In some cases,
however, it is often desirable for individual subscribers to see
different spans or events than the rest of the `Subscribe` stack.
Issues in other projects, such as tokio-rs/console#64 and
tokio-rs/console#76, linkerd/linkerd2-proxy#601,
influxdata/influxdb_iox#1012 and influxdata/influxdb_iox#1681,
jackwaudby/spaghetti#86, etc; as well as `tracing` feature requests like
#302, #597, and #1348, all indicate that there is significant demand for
the ability to add filters to individual `Subscribe`s.
Unfortunately, doing this nicely is somewhat complicated. Although a
naive implementation that simply skips events/spans in
`Subscribe::on_event` and `Subscribe::new_span` based on some filter is
relatively simple, this wouldn't really be an ideal solution, for a
number of reasons. A proper per-subscriber filtering implementation
would satisfy the following _desiderata_:
* If a per-subscriber filter disables a span, it shouldn't be present
_for the subscriber that filter is attached to_ when iterating over
span contexts (such as `Context::event_scope`, `SpanRef::scope`, etc),
or when looking up a span's parents.
* When _all_ per-subscriber filters disable a span or event, it should
be completely disabled, rather than simply skipped by those particular
subscribers. This means that per-subscriber filters should participate
in `enabled`, as well as being able to skip spans and events in
`new_span` and `on_event`.
* Per-subscriber filters shouldn't interfere with non-filtered
`Subscribe`s. If a subscriber contains subscribers without any
filters, as well as subscribers with per-subscriber filters, the
non-filtered `Subscribe`s should behave exactly as they would without
any per-subscriber filters present.
* Similarly, per-subscriber filters shouldn't interfere with global
filtering. If a `Subscribe` in a stack is performing global filtering
(e.g. the current filtering behavior), per-subscriber filters should
also be effected by the global filter.
* Per-subscriber filters _should_ be able to participate in `Interest`
caching, _but only when doing so doesn't interfere with
non-per-subscriber-filtered subscribers_.
* Per-subscriber filters should be _tree-shaped_. If a `Subscriber`
consists of multiple subscribers that have been `Subscribeed` together
to form new `Subscribe`s, and some of the `Subscribeed` subscribers
have per-subscriber filters, those per-subscriber filters should
effect all subscribers in that subtree. Similarly, if `Subscribe`s in
a per-subscriber filtered subtree have their _own_ per-subscriber
filters, those subscribers should be effected by the union of their
own filters and any per-subscriber filters that wrap them at higher
levels in the tree.
Meeting all these requirements means that implementing per-subscriber
filtering correctly is somewhat more complex than simply skipping events
and spans in a `Subscribe`'s `on_event` and `new_span` callbacks.
## Solution
This branch has a basic working implementation of per-subscriber
filtering for `tracing-subscriber` v0.2. It should be possible to add
this in a point release without a breaking change --- in particular, the
new per-subscriber filtering feature _doesn't_ interfere with the global
filtering behavior that subscribers currently have when not using the
new per-subscriber filtering APIs, so existing configurations should all
behave exactly as they do now.
### Implementation
The new per-subscriber filtering API consists of a `Filter` trait that
defines a filtering strategy and a `Filtered` type that combines a
`Filter` with a `Subscribe`. When `enabled` is called on a `Filtered`
subscriber, it checks the metadata against the `Filter` and stores
whether that filter enabled the span/event in a thread-local cell. If
every per-subscriber filter disables a span/event, and there are no
non-per-subscriber-filtered subscribers in use, the `Registry`'s
`enabled` will return `false`. Otherwise, when the span/event is
recorded, each `Filtered` subscriber's `on_event` and `new_span` method
checks with the `Registry` to see whether _it_ enabled or disabled that
span/event, and skips passing it to the wrapped subscriber if it was
disabled. When a span is recorded, the `Registry` which filters disabled
it, so that they can skip it when looking up spans in other callbacks.
A new `on_subscriber` method was added to the `Subscribe` trait, which
allows running a callback when adding a `Subscribe` to a `Subscriber`.
This allows mutating both the `Subscribe` and the `Subscriber`, since
they are both passed by value when subscribering a `Subscribe` onto a
`Subscriber`, and a new `register_filter` method was added to
`LookupSpan`, which returns a `FilterId` type. When a `Filtered`
subscriber is added to a subscriber that implements `LookupSpan`, it
calls `register_filter` in its `on_subscriber` hook to generate a
unique ID for its filter. `FilterId` can be used to look up whether a
span or event was enabled by the `Filtered` subscriber.
Internally, the filter results are stored in a simple bitset to reduce
the performance overhead of adding per-subscriber filtering as much as
possible. The `FilterId` type is actually a bitmask that's used to set
the bit corresponding to a `Filtered` subscriber in that bitmap when it
disables a span or event, and check whether the bit is set when querying
if a span or event was disabled. Setting a bit in the bitset and testing
whether its set is extremely efficient --- it's just a couple of bitwise
ops. Additionally, the "filter map" that tracks which filters disabled a
span or event is just a single `u64` --- we don't need to allocate a
costly `HashSet` or similar every time we want to filter an event. This
*does* mean that we are limited to 64 unique filters per
`Registry`...however, I would be _very_ surprised if anyone _ever_
builds a subscriber with 64 subscribers, let alone 64 separate
per-subscriber filters.
Additionally, the `Context` and `SpanRef` types now also potentially
carry `FilterId`s, so that they can filter span lookups and span
traversals for `Filtered` subscribers. When `Filtered` subscribers are
nested using the `Subscribeed`, the `Context` _combines_ the filter ID
of the inner and outer subscribers so that spans can be skipped if they
were disabled by either.
Finally, an implementation of the `Filter` trait was added for
`LevelFilter`, and new `FilterFn` and `DynFilterFn` structs were added
to produce a `Filter` implementation from a function pointer or closure.
### Notes
Some other miscellaneous factors to consider when reviewing this change
include:
* I did a bit of unrelated refactoring in the `subscriber` module. Since
we were adding more code to the `Subscribe` module (the `Filter`
trait), the `subscriber.rs` file got significantly longer and was
becoming somewhat hard to navigate. Therefore, I split out the
`Context` and `Subscribeed` types into their own files. Most of the
code in those files is the same as it was before, although some of it
was changed in order to support per-subscriber filtering. Apologies in
advance to reviewers for this...
* In order to test this change, I added some new test-support code in
`tracing-subscriber`. The `tracing` test support code provides a
`Subscriber` implementation that can be configured to expect a
particular set of spans and events, and assert that they occurred as
expected. In order to test per-subscriber filtering, I added a new
`Subscribe` implementation that does the same thing, but implements
`Subscribe` rather than `Subscriber`. This allows testing
per-subscriber filter behavior in the same way we test global filter
behavior. Reviewers should feel free to just skim the test the test
support changes, or skip reviewing them entirely.
## Future Work
There is a bunch of additional stuff we can do once this change lands.
In order to limit the size of this PR, I didn't make these changes yet,
but once this merges, we will want to consider some important follow up
changes:
* [ ] Currently, _only_ `tracing-subscriber`'s `Registry` is capable of
serving as a root subscriber for per-subscriber filters. This is
in order to avoid stabilizing a lot of the per-subscriber
filtering design as public API without taking the time to ensure
there are no serious issues. In the future, we will want to add
new APIs to allow users to implement their own root `Subscriber`s
that can host subscribers with per-subscriber filtering.
* [ ] The `EnvFilter` type doesn't implement the `Filter` trait and thus
cannot currently be used as a per-subscriber filter. We should add
an implementation of `Filter` for `EnvFilter`.
* [ ] The new `FilterFn` and `DynFilterFn` types could conceivably
_also_ be used as global filters. We could consider adding
`Subscribe` implementations to allow them to be used for global
filtering.
* [ ] We could consider adding new `Filter` implementations for
performing common filtering predicates. For example, "only enable
spans/events with a particular target or a set of targets", "only
enable spans", "only enable events", etc. Then, we could add a
combinator API to combine these predicates to build new filters.
* [ ] It would be nice if the `Interest` system could be used to cache
the result of multiple individual per-subscriber filter
evaluations, so that we don't need to always use `enabled` when
there are several per-subscriber filters that disagree on whether
or not they want a given span/event. There are a lot of unused
bits in `Interest` that could potentially be used for this
purpose. However, this would require new API changes in
`tracing-core`, and is therefore out of scope for this PR.
Closes#302Closes#597Closes#1348
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
... 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.