## Motivation
I viewed the amazing talk from Eliza Weisman on the RustConf 2019 on
Youtube. Saw that it is missing in the list of Talks.
## Solution
Add it ;)
* Add RustConf 2019 Talk to the README
* README: Adapt talk title and add link to slides
This overrides the default `Subscriber::current_span` impl
with one that forwards the inner subscribers implementation.
This fixes bugs where the current_span was not fetchable when
using the `FmtSubscriber`.
Signed-off-by: Lucio Franco <luciofranco14@gmail.com>
### Fixed
- Fixed `#[instrument]`ed async functions not compiling on
`nightly-2019-09-11` or newer (#342)
### Changed
- Significantly reduced performance impact of skipped spans and events
when a `Subscriber` is not in use (#326)
- The `log` feature will now only cause `tracing` spans and events to
emit log records when a `Subscriber` is not in use (#346)
### Added
- Added support for overriding the name of the span generated by
`#[instrument]` (#330)
- `log-always` feature flag to emit log records even when a `Subscriber`
is set (#346)
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
### Fixed
- `EnvFilter` ignoring directives with targets that are the same number
of characters (#333)
- `EnvFilter` failing to properly apply filter directives to events
generated from `log` records by`tracing-log` (#344)
### Changed
- Renamed `Filter` to `EnvFilter`, deprecated `Filter` (#339)
- Renamed "filter" feature flag to "env-filter", deprecated "filter" (#339)
- `FmtSubscriber` now defaults to enabling only the `INFO` level and
above when a max level filter or `EnvFilter` is not set (#336)
### Added:
- `EnvFilter::add_directive` to add new directives to filters after they
are constructed (#334)
- `fmt::Builder::with_max_level` to set a global level filter for a
`FmtSubscriber` without requiring the use of `EnvFilter` (#336)
- `Layer` implementation for `LevelFilter` (#336)
- `EnvFilter` now implements `fmt::Display` (#329)
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Currently, when `tracing`'s `log` feature is enabled, all spans and
events will emit `log` records as well as `tracing` events. When
`tracing-log` is being used to convert `log` records into `tracing`
events, this results in duplicate events being observed: those emitted
by the event macros directly, and those generated from the log records
they emit by `tracing-log`.
## Solution
In `tracing-core` 0.1.6, we added an internal API for checking if a
`tracing` subscriber has ever been set. In addition to the performance
optimizations which this was initially intended to enable, this also
gives us a way for `tracing` macros in libraries to check if a
downstream application that depends on those libraries is actually using
`tracing`. If `tracing` is in use and a subscriber has been set, the
macros can be disabled.
In a handful of cases, users _may_ wish to collect `log` records and
`tracing` events totally separately. For example, `log` records might be
output to the console while `tracing` is used to generate metrics or for
performance profiling. In this case, there is an additional `log-always`
feature flag which applications can set to enable all of `tracing`'s log
records regardless of whether a subscriber is in use. In most cases
where the `log` feature is currently used (libraries that want to emit
both `tracing` and `log` diagnostics for their users), this will not be
necessary.
Fixes#204
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
The `tracing-subscriber` currently depends on both the `crossbeam-util`
crate (for its `ShardedLock` type) and the `parking_lot` crate for it's
`RwLock` implementation. The Rust standard library also provides a
`RwLock` implementation, so these external dependencies are not strictly
necessary. In the past, using these crates was anecdotally observed to
result in a performance improvement, but the tradeoff is adding
additonal crates (and their transitive dependencies) to the user's
dependency tree.
## Solution
This branch removes the `crossbeam-util` dependency, and makes the
`parking_lot` dependency opt-in. The explicit use of
`parking_lot::RwLock` with a wrapper type that abstracts over the
`parking_lot::RwLock` and `std::sync::RwLock` types to provide a
matching API. This allows the `parking_lot` feature flag to
transparently replace the use of `std::sync::RwLock` with `parking_lot`,
rather than making it required for other features.
Additionally, I've added some new benchmarks for filtering performance
to `tracing-subscriber`.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Currently, the `tracing-subscriber` `EnvFilter` does not properly enable
events that originate from the `tracing-log` `LogTracer` adapter. This
is because those events are supposed to be filtered only by `enabled`,
and will not generate proper `register_callsite` metadata. `EnvFilter`'s
`enabled` method will assume that an event was not enabled statically,
since `enabled` wouldn't have been called if the callsite was given the
`Always` interest. However, this doesn't take `tracing-log` into
account.
## Solution
I've changed `EnvFilter` to always check against static filters in
`enabled` if the dynamic filters don't enable a given metadata. This
fixes the filtering of `tracing-log` events. I've also added tests that
fail against the current master.
This fixes the regression reported by @samscott89.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
This branch fixes broken builds of `tracing-futures` with the
`tokio-alpha` feature.
## Solution
I've added the missing `WithDispatch` impl for
`std::future::Future` that was breaking the build. I've also
updated the `tokio` alpha dependency, and added a CI check
that the tokio-alpha feature flag compiles.
Fixes#337
* futures: add missing `WithDispatch` impl
* futures: update tokio alphas
* chore: add CI job to ensure tokio alpha compiles
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This fixes compilation errors with `#[instrument]`ed `async fn`s on the
latest nightly. The generated `async` block was not `async move`, so the
function's attributes were not moved into it.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Feature Request
### Crates
- `tracing-subscriber`
### Motivation
Currently, the `tracing-subscriber` `FmtSubscriber::default`
implementation defaults to no filtering. This means that all
instrumentation, including extremely verbose `trace`-level diagnostics
from crates like `tokio` are enabled by default.
This is because the subscriber itself does not implement filtering, in
order to allow it to be composed with filters implemented by `Layer`s.
However, defaulting to no filtering at all is definitely a surprising
behavior. I didn't want to conditionally return a different type based
on whether or not filtering was enabled by the `filter` feature flag,
but this is probably not worth the confusion introduced by this
behavior. We should make this more intuitive.
## Solution
This branch changes `tracing-subscriber` to default to enabling
the `INFO` level and above. If the `filter` feature flag is enabled,
users may opt-in to `env_logger`-style filtering. Additionally,
regardless of feature flags, a new `with_max_level` method is
added to the `FmtSubscriber` builder, which takes a `Level` or
`LevelFilter`. `LevelFilter` now implements `Layer` by enabling
any spans and events that are less than or equal to that `Level`.
Fixes: #331Fixes: #332
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Currently, the `tracing-subscriber::Filter` type can be constructed from
an environment variable or string containing filter directives. However,
once it has been constructed, new directives may not be added.
## Solution
This commit adds an API for adding directives to a filter after it has
been constructed. Directives can be constructed either from
`LevelFilter`s or by parsing a string. Eventually, this API will also
allow us to add a programmatic builder API for directives.
This is a prerequisite for future work such as https://github.com/tokio-rs/tracing/issues/332#issuecomment-529138912
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
`tracing-subscriber` currently relies on `PartialOrd` and `Ord`
implementations for the `Directive` and `StaticDirective` types. These
are used for determining the order in which the directives that apply to
a span/event are iterated over when determining whether that span or
event is enabled, so that the most specific directives are checked
first.
Originally, the directives were stored in `Vec`s, and the `PartialOrd`
implementations were used to call [`Vec::sort_unstable`][1] on those
`Vec`s. We would then iterate over the sorted `Vec`. However, in order
to avoid having to re-sort the `Vec` every time a new directive is
inserted (as part of a potential future feature), I decided to store the
directives in [`BTreeSet`][2]s rather than `Vec`s.
Using `BTreeSet` introduces some problems. `Vec::sort_unstable` does not
require a total ordering, so the `PartialOrd` impls were based only on
comparing the length of the targets of the directive and on other
properties such as whether a span name is specified. If the directives
were the same "shape" and their targets were of the same length, then
the `PartialOrd` impls would consider them "equal". When we used
`sort_unstable`, this was fine. A `BTreeSet`, however, is a _set_ — if
two items are considered equal, the second is considered a duplicate of
the first and will not be present in the set.
@Ralith reported a bug where a filter string like
`common=trace,server=trace` would set the level for the `common` target
to `trace`, but not set the level for the `server` target. I was
mystified by this behavior — similar filters worked fine for me — until
I realized that "common" and "server" have the same number of
characters. The issue was that the two directives were considered
"equal" by the `PartialOrd` impl, and the resultant `BTreeSet` only
contained the first one.
[1]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort_unstable
[2]: https://doc.rust-lang.org/std/collections/struct.BTreeSet.html
## Solution
This branch fixes the bug by rewriting the `PartialOrd` impls for
`Directive` and `StaticDirective` to fall back to other forms of
ordering (such as comparing targets lexicographically) when the metrics
the previous impls used (e.g. target length) are the same.
Additionally, I've added some new tests for cases where two directives
are equal on one or more ordering metrics, and some debug assertions
that the `PartialOrd` impls behave correctly.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Apparently, the GitHub Actions `paths:` filtering for events uses [an
API][1] from the standard library of a known bad programming language,
which [doesn't behave the way normal unix globs do][2] and [cannot match
arbitrarily nested files][3].
This means that the filter was running the CI action only on PRs that
changed a `Cargo.toml` or `*.rs` _in the root of the repository_, rather
than _any_ `Cargo.toml` or `*.rs`, as a reasonable person might assume
it would.
## Solution
This branch removes path filtering from the CI workflow, since
apparently it is *impossible* to get the relatively simple behavior we
would want using this thing.
Since almost all `tracing` pull requests touch a `*.rs` or `Cargo.toml`
anyway, this path filtering wasn't really getting us a whole lot.
Removing it shouldn't make a huge difference. It's a shame that we have
to do a full Rust build & test run on PRs that only touch READMEs etc,
but \_(ツ)_/¯.
[1]: https://help.github.com/en/articles/workflow-syntax-for-github-actions#onpushpull_requestpaths
[2]: https://golang.org/pkg/path/#Match
[3]: https://github.com/golang/go/issues/11862
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Fixes#298
## Solution
Add a new function to either parse the name from the macro's attribute
or return the default name (instrumented method's name). Do you want to
have the previous function's name as a field? In that case, that would
require a bit of change (maybe return an option of something from
`name`).
I added some tests, please tell me if you need more (in the nightly
async/await test for example)
refs: #298
## Motivation
The `tracing-fmt::filter::EnvFilter` type implemented `fmt::Display`,
but `tracing-subscriber::filter::Filter` does not. A `fmt::Display` impl
for filters can be useful, in order to show users the currently active
filter (e.g. linkerd/linkerd2-proxy#342).
## Solution
This branch adds a `fmt::Display` implementation to `Filter`.
Since the `matchers::Pattern` type used internally for pattern matching
does not implement `fmt::Display` nor expose the string from which the
pattern was constructed, it was necessary to add a new internal type
which holds both a `matchers::Pattern` and the string representation of
that pattern. This has the side benefit of fixing a _technically_
incorrect `cmp::PartialEq` implementation for `ValueMatch`, although
this was never a problem in practice.
I've also added a test asserting that we can parse a filter string,
format the parsed filter, and parse the formatted representation to a
filter with the same directives.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
The `tokio` org is in the Github actions beta. Running our CI jobs on Actions
rather than Azure Pipelines has a few potential advantages:
- GitHub Actions allows us to conditionally run workflows based on what
files were modified. This lets us configure the Rust CI tests/checks
to only run when actual Rust source code was modified. This will let
us merge PRs that change READMEs, CI configs, etc. but don't actually
modify any source code more quickly, since they won't have to wait
for all the tests to run.
- GitHub Actions has slightly nicer integration with the GitHub UI
(IMO), and it takes fewer clicks to see the logs from a failed build
than on Azure.
- Finally, I've (anecdotally) observed GitHub Actions workflows to
start much sooner than the corresponding Azure Pipelines workflows.
Although the stages seem to take similar amounts of time to run, it
seems like there's sometimes a delay between an event that triggers
Azure Pipelines and the job actually starting. My guess is that
GitHub Actions recieves the triggering webhook a bit sooner because
it's running on the same infrastructure that actually hosts the repo?
## Solution
This branch ports the Azure Pipelines CI configs to run on GitHub
Actions. I've tried to port the config relatively faithfully, with a
few tweaks.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
When `tracing` is not in use, no default subscriber will be set, and
tracing instrumentation points can be skipped. Currently, the
instrumentation macros detect this by testing if the callsite's
`Interest` is `never`. However, this is significantly slower than how
the `log` crate detects that there is no logger: we must call a function
through a trait object, do a relaxed load, construct an `Interest` from
an integer, and then test on the value of the `Interest`. Furthermore,
we must construct the callsite _at all_ in order to do this. Meanwhile,
when no logger is set, `log` can skip log records with only a single
relaxed atomic load.
## Solution
This branch adds a new private-API method in `tracing_core::dispatcher`
that allows us to check if a dispatcher has ever been set. If this is
false, then `tracing` has not yet been initialized and the callsite can
be elided entirely. Representing this as an atomic bool lets us perform
a single relaxed load and branch, without having to mess around with
`Interest`s and callsite vtables and so on. In cases where `tracing`
will never be used, this will always be false.
This the event macro performance with no subscriber set on par with the
`log` crate's performance when no logger is set. Spans are a bit slower
because they must still construct a disabled span object, but the span
macros are somewhat faster in this case than they were previously.
## Benchmark results
Before:

After:

Note that when no subscriber is set, skipping an event previously
took an average of around 2 ns, and skipping a span took around
5 ns. Now, skipping an event takes around 850 ps (about the
same as skipping a `log` macro when there's no logger), while
skipping a span macro takes around 2 ns.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
* tracing, core: improve no-subscriber performance significantly
This branch adds a new private API to `tracing-core` for checking if a
subscriber has ever been set. If a subscriber has never been set, we can
elide almost all of the event macro, and more of the span macro than we
were previously able to. Unlike checking a cached interest, which must
synchronize with the callsite registry, checking if a subscriber has
been set may be a relaxed rather than acquire load.
The performance of the `event!` macro (and the related `trace!`,
`info!`, etc macros) when no subscriber has ever been set (i.e., tracing
is not being used) is now comparable with that of the `log` crate, at
approximately 600 picoseconds (on my MacBook). As per `criterion`:
```
no_subscriber/event time: [610.43 ps 621.06 ps 633.20 ps]
change: [-64.247% -62.295% -60.263%] (p = 0.00 < 0.05)
Performance has improved.
Found 4 outliers among 100 measurements (4.00%)
1 (1.00%) high mild
3 (3.00%) high severe
no_subscriber/log time: [689.22 ps 707.34 ps 728.25 ps]
change: [+27.149% +33.128% +40.141%] (p = 0.00 < 0.05)
Performance has regressed.
Found 4 outliers among 100 measurements (4.00%)
4 (4.00%) high mild
no_subscriber_field/event
time: [623.28 ps 635.73 ps 648.88 ps]
change: [-59.666% -58.074% -56.649%] (p = 0.00 < 0.05)
Performance has improved.
Found 2 outliers among 100 measurements (2.00%)
2 (2.00%) high mild
no_subscriber_field/log time: [621.73 ps 632.07 ps 643.30 ps]
change: [+1.6194% +4.3288% +7.1454%] (p = 0.00 < 0.05)
Performance has regressed.
Found 3 outliers among 100 measurements (3.00%)
2 (2.00%) high mild
1 (1.00%) high severe
```
The worse performance of the `log` crate without fields than with fields
is probably statistical noise that criterion failed to eliminate.
The span macros cannot achieve this level of performance currently, as
the callsite must still be constructed in order to emit `log` events
when that feature flag is enabled. Future work will involve tuning the
`span!` macro some more. However, performance is improved by this change.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
* optimize disabled spans when log support is off
* tracing: add benchmarks for getting the subscriber
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
The `ThreadLocal` struct used by `CurrentSpan` currently can cause a
double panic, since it is unclear why the current thread's slot is
unset. The `try_get` function may return `None` because that thread has
not yet been created, _or_ it may return `None` because we are
panicking. However, the code that calls this function doesn't correctly
handle this --- it assumes `None` is returned because the thread has not
yet had its local slot created, and `expect`s that it will exist after
inserting the local slot.
## Solution
I've updated this code to present a more `LocalKey`-like API, and avoid
potential double panics here. Now, when the thread is panicking, the
closure passed into `with` is not invoked.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
`tracing` currently consists of a large number of crates. The number of
crates has the potential to be quite intimidating to users.
## Solution
This branch makes the following changes:
- Delete `tracing-fmt`. This crate's functionality has already been
moved into `tracing-subscriber`, and a final version has been
published to deprecate the crate & link to the code's new home.
- Delete `tracing-tower-http`, as this functionality is now subsumed
by `tracing-tower`. Since the crate was never published, we do not
need to deprecate it.
- Delete `tracing-slog`. This crate was never implemented, so we can
just remove it from the repository. It can be re-created if we ever
implement `slog` integration.
- Move `tracing-env-logger` into a `tracing-log` module, and feature
flag it. I updated some of the APIs as well.
- Remove deleted crates from documentation.
This makes most of the changes discussed in #308.
Closes#308
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
chore: build and publish documentation for each branch.
This commit introduces support for:
- building and deploying documentation for the master branch
- building and deploying (preview) documentation for each pull request
and for each PR
- adds a link in `README.md` pointing to the generated documentation
for the master branch
- notes the per-PR documentation previews in `CONTRIBUTING.md`
Closes#210
* tracing: prepare to release 0.1.8
Changed
- Reorganized and improved API documentation (#317)
Removed
- Dev-dependencies on `ansi_term` and `humantime` crates, which were
used only for examples (#316)
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
These examples were moved in #316, but apparently I forgot to delete
the dev dependencies in some Cargo.tomls.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This branch prepares `tracing-log` for an 0.1 release.
Taking this crate out of alpha will allow us to publish
`tracing-subscriber` 0.1, as that crate depends on `tracing-log` & I
don't want to publish an 0.1 that depends on an alpha crate.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This branch updates and reorganizes the crate-level docs in `tracing`. In
particular, I've:
- moved the documentation on `span!` and `event!` macro syntax to a
single place that the macros link to, and made the differences
between the span and event macros clearer.
- added more section headers to make linking into the docs easier
- fixed some typos, broken links, and markdown errors
- simplified the "Core Concepts" section a little
- made it clearer that the `tracing` crate does not provide
subscriber impls
- added more documentation describing how to use the
instrumentation APIs
- replaced the link to `tracing-fmt` with `tracing-subscriber`
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Currently, most crates in this repository have `examples` directories
that contain demonstrations of how to use that crate. In many cases,
these examples also use APIs from _other_ crates in this repository ---
for example, the `tracing-subscriber` `FmtSubscriber` is used by many
examples to format the output generated by instrumentation APIs, so that
users can see the generated output.
The disadvantage to this approach is that it requires crates in this
repository to have dev-dependencies on each other. This is problematic
for a few reasons:
* It makes it easy to inadvertently create cyclic dependencies between
`tracing` crates.
* When building a crate that depends on a crate with dev-dependencies,
those dev-dependencies are downloaded and compiled, despite not being
linked into the dependent crate. This means that users depending on a
tracing crate will pull in a larger dependency tree, since the
dev-dependencies used by examples are also downloaded, although they
are not required by the dependent. This makes the tracing crate
appear to be a much larger dependency than it actually is, and can
make users' build times slower.
* Finally, it means that the examples are scattered throughout the
repository. In some cases, the examples demonstrate the functionality
of multiple crates, but only live in one crate's `examples` dir. This
can hurt the discoverability of the examples, especially for new
users.
## Solution
This branch moves all the examples out of individual crates and into a
new `examples` crate (which is otherwise empty and cannot be published
to crates.io). The `examples` crate is part of the root `tracing`
workspace, so it's still possible to `cargo run --example WHATEVER`.
Similarly, `cargo test --all` will still build the examples.
All dev-dependencies which were only required by examples and not tests
have been removed, which has a drastic impact on the dependency
footprint of some crates.
Finally, I've added a README to the `examples` crate, listing the
available examples and what functionality they demonstrate.
Refs: #315, #308
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Currently, the `tracing-log` crate uses the `CurrentSpan` utility in
`tracing-subscriber`. However, now that `tracing-fmt` has been moved
into `tracing-subscriber`, its `log` feature (which depends on
`tracing-log`) creates a cyclic dependency between these two crates.
This branch solves the cyclic dependency by removing the
`tracing-subscriber` dependency from `tracing-log`. Instead, the
current span is tracked manually.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
In the near future, the `tracing-subscriber` crate should be ready for a
stable 0.1 release. Before we can do that, we should do some pre-release
polish, such as denying warnings, updating idioms, and adding missing
documentation.
This branch performs most of the necessary polish for
`tracing-subscriber`. Please note the following:
* The next release will not be version 0.1, as PR #241 would be a
breaking change, and I'd like to land that first. We'll probably do
an alpha.4 first.
* I didn't add `deny(warnings)`, as that will also deny deprecation
warnings, and I've had bad experiences with deprecations breaking
CI in the past. Instead, I've denied most other warnings explicitly.
The downside to this is a *very* long list of deny attributes.
* The docs added in this branch are pretty rough. It would be good to
expand them some more in the future, hopefully before 0.1.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
As discussed in #308, there are a large number of crates in this
repository, which can be confusing for users and can increase the
maintainance burden for maintainers. Also, the `tracing-fmt` and
`tracing-subscriber` crates both contain filtering implementations with
similar behaviour and APIs, but `tracing-subscriber`'s filter module
offers more advanced features (filtering on field values), and is usable
with any subscriber implementation. Two separate filter implementations
also has the potential to be confusing for users.
## Solution
This branch moves most of the code from `tracing-fmt` into a module in
`tracing-subscriber`, and changes the `tracing-fmt` builder APIs to use
the `Filter` type in `tracing-subscriber`. The `tracing-subscriber/fmt`
feature flag can be used to disable the formatting subscriber when it is
not used.
The `tracing-fmt` crate has been updated to re-export the APIs from
`tracing-subscriber`, and marked as deprecated. Once we've published a
new version of `tracing-subscriber` with the format APIs, we can publish
a final release of `tracing-fmt` that will update the documentation &
mark all APIs as deprecated, so that users know to move to the
`tracing-subscriber` crate.
Refs: #308
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Changed:
- New (curly-brace free) event message syntax to place the message in
the first field rather than the last (#309)
Fixed:
- Fixed a regression causing macro stack exhaustion when the `log`
feature flag is enabled (#304)
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
The old syntax for macros with messages would put the message field
first, followed by all the other fields. The new (no curly braces)
syntax (added in #288) puts messages last, inconsistently with
everything else. Since message field ordering currently matters for
how some subscribers (e.g. `tracing-fmt`) display events, we should
make this somewhat more consistent.
## Solution
This branch changes the new macro syntax to put the `message`
field first, rather than last.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
#288 introduced a regression that causes infinite macro recursion when
the `log` feature is enabled. This PR fixes it (by making the macros
significantly worse).
I've also added a new test step that runs with `--all-features`, since
apparently CI doesn't already do this. Additionally, I've simplified some
of the macros a bit: it turns out we don't have to have as many match
arms if we make the macros slightly more lenient about where commas
can show up.
Fixes#303
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
There is now a handful of blog posts and conference talks about Tracing.
These external resources may be very helpful, especially for new users
or contributors learning how to use Tracing. However, they aren't
currently linked anywhere in this repository, so they can be hard to
discover.
## Solution
This PR adds an "External Resources" section to README.md.
I also considered adding a new document (maybe RESOURCES.md or
something?), instead of putting them in the README, but I thought that
it was easier to find the references in the README. Since the section is
currently quite short, I'm not concerned about making the README too
long. If, in the future, there are a lot of talks & posts listed here,
we could consider moving the list to a separate document and linking to
it in the README.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
> When logging trace data, users may wish to write to a number of
> output streams, such as to stdout, to stderr, or to a file, depending
> on their use-case. Currently, however, the IO stream that
> `tracing-fmt` writes to is hard-coded to `stdout`
## Solution
- Add a new trait, `NewWriter`, to abstract over the action of creating
a new object that implements `std::io::Write`
- Add a new type parameter to `FmtSubscriber` and its `Builder` for
that trait
- Default that type parameter to `std::io::stdout`
- Add documentation as needed
- Add tests for the new functionality
- Add example(s) to demonstrate the new functionality
Closes: #225
* fmt: abstract writer creation behind trait
- Add a new trait, `NewWriter`, that represents a type that can create a
writer (an object that implements `std::io::Writer`)
- Add an implementation of that trait that wraps `std::io::stdout`
- Add a new type parameter, `W`, to `FmtSubscriber` and it's `Builder`,
that allows overriding the default `NewWriter` implementation, which
is `NewStdout`
* fmt: generalize writer trait
- add implementation of `NewWriter` for functions that return an object
that implements `std::io::Writer`
- update the default type and value for the `W` type parameter of
`FmtSubscriber` and it's `Builder` to directly use `std::io::stdout`
* fmt: rustfmt
* fmt: add builder function for setting the writer
* fmt: add test for customizing writer
- Add `MockWriter` that proxies `io::Write` implementation to a
mutex-protected byte vector
- Add unit test that uses `MockWriter` with a shared byte buffer to test
`FmtSubscriber`'s behavior when customizing the writer
* fmt: move writer into submodule
- move `NewWriter` and related code (including the unit test) into a
`writer` submodule
- move the `extern crate` statement for `lazy_static` to the top of
`lib.rs`
- remove now-unnecessary TODO comment in `FmtSubscriber::event`
* fmt: add example for printing to stderr
* fmt: add unit test for custom writer struct
* fmt: refactor writer unit tests
- consolidate common logic for both `Builder::with_writer` unit tests
- replace wildcard `use` statement with specific types used from the
crate root
* fmt: finish writer documentation comments
* fmt: reformat
- move trait bounds for type parameter `T` in
`writer::test::test_writer` to a `where` clause
* fmt: rename writer abstraction
- rename `NewWriter` to `MakeWriter`, and its method `new_writer` to
`make_writer`
* fmt: fix links for rustdoc stable
- replace intra-rustdoc links with URL reference links
* fmt: add example for make_writer
- add a `stderr` example for `Builder::make_writer`
* fmt: move make_writer back to crate root
- move the impl block for `Builder::make_writer` back to the create root
with the other impl blocks
* fmt: refactor writer tests
- update the `Builder::make_writer` unit tests to not be dependent on
ANSI codes
- use Edition 2018 idioms for importing the `lazy_static` macro
* fmt: fix rustdoc links
- use absolute URLs for links to `FmtSubscriber`