## Motivation
Fix minimal-versions failure.
## Solution
Upgrade all the dependencies to their most recent semver-compatible
version, adjusting back down as necessary for MSRV.
## Context
[cargo-minimal-versions](https://lib.rs/crates/cargo-minimal-versions)
is wonderful. With this PR, the full repo passes under all of
- `cargo hack --workspace minimal-versions check --all-features`
- `cargo +1.49 hack --workspace --exclude tracing-appender
minimal-versions check --all-features`
- `cargo +1.53 hack -p tracing-appender minimal-versions check
--all-features`
- All of CI 😇
This patch adds a bit more context around why we are creating a smaller
scope for the spans, and also what happens when we call
`global::shutdown_tracer_provider()` (that comment was copied from
the`rust-opentelemetry` repo).
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
`Value` was already implemented for `dyn Error + 'static`, but rust
doesn't silently coerce trait objects. This means that passing an error
of type `dyn Error + Send + Sync + 'static` would not work. This is
related to #1308.
## Solution
Add impls for `dyn Error + …` variants for `Send`, `Sync`, and `Send +
Sync`. These extra impls just delegate to the existing `dyn Error +
'static` impl.
Also update one of the examples to use `dyn Error + Send + Sync` to
demonstrate that this works.
Refs: #1308
This updates all crates' MSRVs to 1.49 if they were not already greater
than that (`tracing-appender` is at 1.53). Rust 1.49+ is required to
update `parking_lot` to v0.12 (see #1878). Also, `futures-task` (which I
believe is only needed as a transitive dep) now needs 1.45+, so this
also fixes our CI build.
Because `tracing-opentelemetry` previously required 1.46.0, it had a
separate CI MSRV job. Since 1.49.0 is greater than 1.46.0, the separate
check for `tracing-opentelemetry` is no longer needed.
In the process, I removed deprecated uses of
`core::atomic::spin_loop_hint`, which is replaced with
`core::hint::spin_loop` in 1.49.
## Motivation
Support the latest OpenTelemetry specification.
## Solution
Update `opentelemetry` to the latest `0.17.x` release. Breaking changes
upstream in the tracking of parent contexts in otel's `SpanBuilder` have
necessitated a new `OtelData` struct to continue pairing tracing spans
with their associated otel `Context`.
## Motivation
Logging line numbers and file names can be useful for debugging. This
feature was suggested by #1326
## Solution
As per @hawkw's suggestions, fields were added on `Format`, along with
builder methods. Filename and line number information was gathered from
the `meta` variable.
The `Pretty` formatter already supports printing source locations, but
this is configured separately on the `Pretty` formatter rather than on
the `Format` type. This branch also changes `Pretty` to honor the
`Format`-level configurations and deprecates the `Pretty`-specific
method.
Fixes#1326Closes#1804
Co-authored-by: David Barsky <me@davidbarsky.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Currently, `tracing-appender`'s `RollingFileAppender` does not implement
the `MakeWriter` trait. This means it can only be used by either
wrapping it in `NonBlocking`, or by wrapping it in a `Mutex`. However,
this shouldn't be strictly necessary, as `&File` implements `io::Write`.
It should thus only be necessary to introduce locking when we are in the
process of _rotating_ the log file.
## Solution
This branch adds a `MakeWriter` implementation for
`RollingFileAppender`. This is done by moving the file itself inside of
an `RwLock`, so that a read lock is acquired to write to the file. This
allows multiple threads to write to the file without contention. When
the file needs to be rolled, the rolling thread acquires the write lock
to replace the file. Acquiring the write lock is guarded by an atomic
CAS on the timestamp, so that only a single thread will try to roll the
file. This prevents other threads from immediately rolling the file
_again_ when the write lock is released.
I...should probably write tests for that, though.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This changes `tracing-subscriber` so that the `env-filter`, `json`,
and `chrono` features are not enabled by default, and instead require
users to opt in. This should significantly reduce the default
dependency footprint.
Of course, this is a breaking change, and therefore will be part of
`tracing-subscriber` v0.3.
Fixes#1258
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Currently, `tracing-subscriber` supports the `chrono` crate for
timestamp formatting, via a default-on feature flag. When this code was
initially added to `tracing-subscriber`, the `time` crate did not have
support for the timestamp formatting options we needed.
Unfortunately, the `chrono` crate's maintainance status is now in
question (see #1598). Furthermore, `chrono` depends on version 0.1 of
the `time` crate, which contains a security vulnerability
(https://rustsec.org/advisories/RUSTSEC-2020-0071.html). This
vulnerability is fixed in more recent releases of `time`, but `chrono`
still uses v0.1.
## Solution
Fortunately, the `time` crate now has its own timestamp formatting
support.
This branch replaces the `ChronoLocal` and `ChronoUtc` timestamp
formatters with new `LocalTime` and `UtcTime` formatters. These
formatters use the `time` crate's formatting APIs rather than
`chrono`'s. This removes the vulnerable dependency on `time` 0.1
Additionally, the new `time` APIs are feature flagged as an _opt-in_
feature, rather than as an _opt-out_ feature. This should make it easier
to avoid accidentally depending on the `time` crate when more
sophisticated timestamp formatting is _not_ required.
In a follow-up branch, we could also add support for `humantime` as an
option for timestamp formatting.
Naturally, since this removes existing APIs, this is a breaking change,
and will thus require publishing `tracing-subscriber` 0.3. We'll want to
do some other breaking changes as well.
Fixes#1598.
This adds a new `Span::or_current` method that returns the span it's
called on, if that span is enabled, or the current span if that span
is not enabled.
This should provide a more efficient alternative to writing code like
```rust
tokio::spawn(
future
.instrument(some_span)
.in_current_span()
);
```
since it doesn't wrap the future in two different spans which are
(potentially) both entered on polls. It's also a little more concise
to write, which (hopefully) will encourage people to use it instead
of the less efficient alternative.
`Span::or_current` may be useful in other cases as well.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This commit updates the `inferno-flame` example to use the `tempfile`
crate as a replacement
for the unmaintained `tempdir` crate.
Also, the previous version of the example output the flamegraph inside
the temporary directory. Since the temporary directory is cleaned up
when the program exits, this means the user can't actually look at the
flamegraph when running this example. I've changed the example to put the
flamegraph in the current working dir instead, so the user can look at
it.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This version includes patches for a couple of RUSTSEC advisories that
`cargo audit` is mad about. These aren't actually security-critical,
since the affected hyper versions are only used in examples, not in
actual`tracing` crates, but bumping makes `cargo audit` chill out. And
we should keep up to date regardless.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Currently, there are a few examples that include CLI argument parsing.
These currently use the `clap` crate. `clap` is one of the most flexible
and full-featured argument parsing libraries in Rust. However, or
perhaps *because* of this, `clap` is also a fairly heavy-weight
dependency which pulls in a lot of transitive deps.
We don't *need* most of `clap`'s features for the very simple argument
parsing in these examples. Therefore, this commit replaces `clap` with
`argh`, which is a much lighter dependency.
Also, `clap` is currently pulling a version of `bitflags` that breaks
our MSRV...
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Forward-port of #1460 to the 0.2.x (master) branch.
## Motivation
Fixes#1347
## Solution
Change the format from `err=message, err: source1` to `err=message
err.sources=[source1, source2, source3, ...]`, as suggested in
#1347 (comment)
(still leaving out the sources if there are none).
## Caveats
Haven't changed the JSON formatter, since I'm not really sure about how
to do that. The current format is `{.., "fields": {.., "err":
"message"}}`, disregarding the sources entirely.
We could change that to `{.., "fields": {.., "err": "message",
"err.sources": ["source1", "source2", "source3", ..]}}`, which would
keep backwards compatibility but looks pretty ugly.
Another option would be `{.., "fields": {.., "err": {"message":
"message", "sources": ["source1", "source2", "source3", ..]}}}` which
leaves room for future expansion.
Then again, that begs the question about why the first error is special,
so maybe it ought to be `{.., "fields": {.., "err": {"message":
"message", "source": {"message": "source1", "source": ..}}}}`.
But that style of linked list is pretty annoying to parse, so maybe it
ought to be flattened to `{.., "fields": {.., "err": [{"message":
"message"}, {"message": "source1"}, ..]}}`?
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
Clippy added a new lint detecting unnecessary borrows in expressions
where the borrowed thing is already a reference...which is nice, and
all, but the downside is that now we have to fix this.
This PR fixes it.
## Motivation
Newest versions of opentelemetry and opentelemetry-jaeger don't work
with the tracing-opentelemtry due to the latter still depending on a
0.14 version.
## Solution
Adjust dependencies and use new TraceFlags struct instead of constants
- Removes the default implementation.
- Makes tracing_core::span::Current::unknown public so that implementers
of Collect can use it if they didn't implement current_span() before.
- Copy the old default implementation to all implementers of Collect.
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
I dislike using `*` imports in my code, so I'm not using prelude modules
provided by libraries. With the way the examples in the
`tracing-subscriber` docs are currently set up, there is no hint on
where some methods are coming from. Just removing the prelude import
unfortunately doesn't lead to a solution. The compiler prefers the
prelude re-export:
```
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
3 | use crate::tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt;
|
```
## Solution
Use the traits directly in the documentation examples.
Since the compiler hints around this are currently very bad, it's good
to have a hint where methods in doc examples could come from in there,
for users who prefer not using the prelude.
## Motivation
Support the latest OpenTelemetry specification.
## Solution
Update `opentelemetry` to the latest `0.14.x` release. Despite breaking
changes upstream, no additional public API or behavioral changes are
necessary in `tracing-opentelemetry`, but simplifications in the
propagation of span information have removed the need for the current
internal `CompatSpan` and custom parent context construction.
Performance has improved by ~30% on current benchmarks.
It turns out that when using the global dispatcher, emitting tracing
events in a panic hook will capture the span in which the program
panicked. This is very handy for debugging panics! Thanks a lot to
@nate_mara for pointing this out to me on twitter --- I hadn't even
thought of it!
Since it isn't necessarily immediately obvious that this works, I
thought it would be nice to add an example.
* opentelemetry: support otel 0.13.0
Switches to `Cow<'static, str>` for otel event names and updates docs to
show simplified install methods.
Resolves#1323, resolves#1324
* Add simple vs batch comment
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
Not sure that there's a issue tracking this, but anyways. Here's an
update to Tokio 1.0!
This closes the various Dependabot dependency update PRs that we can't
just merge due to breaking changes.
Closes#1149Closes#1164Closes#1177
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Support the latest OpenTelemetry specification
## Solution
In order to support the latest spec, this patch makes the following
breaking API changes:
* Update `opentelemetry` to 0.11.x
* Update `OpenTelemetrySpanExt::set_parent` to take a context by value
as it is now stored and propagated.
* Rename `PreSampledTracer::sampled_span_context` to
`PreSampledTracer::sampled_context` as it now returns a full otel
context
Additionally the following doc and example changes:
* Show w3c trace context propagator as recommendation in examples
## Motivation
Currently, the `tracing-subscriber` crate has the `MakeWriter` trait for
customizing the io writer used by `fmt`. This trait is necessary (rather
than simply using a `Write` instance) because the default implementation
performs the IO on the thread where an event was recorded, meaning that
a separate writer needs to be acquired by each thread (either by calling
a function like `io::stdout`, by locking a shared `Write` instance,
etc).
Right now there is a blanket impl for `Fn() -> T where T: Write`. This
works fine with functions like `io::stdout`. However, the _other_ common
case for this trait is locking a shared writer.
Therefore, it makes sense to see an implementation like this:
``` rust
impl<'a, W: io::Write> MakeWriter for Mutex<W>
where
W: io::Write,
{
type Writer = MutexWriter<'a, W>;
fn make_writer(&self) -> Self::Writer {
MutexWriter(self.lock().unwrap())
}
}
pub struct MutexWriter<'a, W>(MutexGuard<'a, W>);
impl<W: io::Write> io::Write for MutexWriter<'_, W> {
// write to the shared writer in the `MutexGuard`...
}
```
Unfortunately, it's impossible to write this. Since `MakeWriter` always
takes an `&self` parameter and returns `Self::Writer`, the generic
parameter is unbounded:
```
Checking tracing-subscriber v0.2.4 (/home/eliza/code/tracing/tracing-subscriber)
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> tracing-subscriber/src/fmt/writer.rs:61:6
|
61 | impl<'a, W: io::Write> MakeWriter for Mutex<W>
| ^^ unconstrained lifetime parameter
error: aborting due to previous error
```
This essentially precludes any `MakeWriter` impl where the writer is
borrowed from the type implementing `MakeWriter`. This is a significant
blow to the usefulness of the trait. For example, it prevented the use
of `MakeWriter` in `tracing-flame` as suggested in
https://github.com/tokio-rs/tracing/pull/631#discussion_r391138233.
## Proposal
This PR changes `MakeWriter` to be generic over a lifetime `'a`:
```rust
pub trait MakeWriter<'a> {
type Writer: io::Write;
fn make_writer(&'a self) -> Self::Writer;
}
```
The `self` parameter is now borrowed for the `&'a` lifetime, so it is
okay to return a writer borrowed from `self`, such as in the `Mutex`
case.
I've also added an impl of `MakeWriter` for `Mutex<T> where T: Writer`.
Unfortunately, this is a breaking change and will need to wait until we
release `tracing-subscriber` 0.3.
Fixes#675.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This PR:
* Adds an example demonstrating how `fmt::Subscriber` can be used to write to stdout and a file simultaneously.
* Removes a few mentions of "Layers" in the examples directory; opting for "Subscribers" instead.
Resolves#1091
The trait being augmented is the 'Collect' trait, so name the trait
that extends should be called 'CollectExt'.
This is in keeping with the extension trait naming conventions
documented in RFC 445 and the spirit of the discussion in
tokio-rs/tracing PR #1015.
## Motivation
Support the latest OpenTelemetry specification
## Solution
In order to support the latest spec, this patch makes the following
breaking API changes:
* Update `opentelemetry` to 0.10.x
* Update `CompatSpan` to reflect changes to `Span` trait
* Record `u64` values as strings as they are no longer supported in
OpenTelemetry.
Additionally the following non-public api, doc, and example changes:
* Update examples and docs to use new simplified pipeline builder.
* As `opentelemetry::api` no longer exports trace types, internally use
`opentelemetry::trace as otel` to disambiguate from tracing types.
* Remove `rand` dependency as it is no longer needed
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Right now TracedError is pretty much incompatible with enum heavy error
handling implementations. The way its currently designed you'd have to make
sure that each leaf error independently is wrapped in a `TracedError` so that
all sources end up capturing a SpanTrace.
## Solution
To resolve this I've added a `map` method for transforming the inner type of a
TracedError while preserving the existing SpanTrace. This is still a bit
cumbersome, where before you'd be able to write `result.map_err(|source|
MyError { source, some_context })` now you'll have to write
`result.map_err(|source| source.map(|source| MyError { source, some_context
}))`. To fix this we should probably eventually add an extension trait on
`Result` but I want to experiment with that half of the change in `zebra`
before committing to an API, since it can easily be done out of tree.
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
Depends on #1067
## Motivation
Currently, the `Compact` event formatter in `tracing-subscriber`
is...kind of bad, and nobody seems to use it. It outputs the names of
all the spans in the current context, and (inexplicably) the _names_ of
all the fields on the current span, but not their values. This isn't
very useful.
## Solution
This branch rewrites the `Compact` formatter to be a little less bad.
Now, we output all the fields from the current span context, but skip
span names, and we shorten the level to a single character when it's
enabled. Additionally, using the `compact` formatter disables targets by
default. Now, the lines are nicely short, but maybe still useful.
Example output before this change:

...and after:

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Currently, the `tracing_subscriber::fmt` module contains only
single-line event formatters. Some users have requested a
human-readable, pretty-printing event formatter optimized for
aesthetics.
## Solution
This branch adds a new `Pretty` formatter which uses an _excessively_
pretty output format. It's neither compact, single-line oriented, nor
easily machine-readable, but it looks _quite_ nice, in my opinion. This
is well suited for local development or potentially for user-facing logs
in a CLI application.
Additionally, I tried to improve the docs for the different formatters
currently provided, including example output. Check out [the Netlify
preview][1]!
[1]: https://deploy-preview-1067--tracing-rs.netlify.app/tracing_subscriber/fmt/index.html#formatters
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This PR renames the following:
- `tracing_core::Subscriber` to `tracing_core::Collect`
- `tracing_subscriber::layer::Layer` to `tracing_subscriber::layer::Subscribe`
Authored-by: David Barsksy <dbarsky@amazon.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Currently, the `reload` layer is generic over both the type of the layer
being reloaded, *and* the type of the subscriber that the layer is
layered onto. This means that the `reload::Handle` type that's used to
reload the value of the layer *also* is parameterized over the
subscriber's type.
The subscriber type parameter makes the `reload` API significantly
harder to use. Any time a `reload::Handle` is returned by a function,
taken as an argument, or stored in a struct, the full type of the
subscriber under the layer must be written out --- and often, it is
quite long. What makes this worse is that sometimes the type of the
subscriber may vary at runtime based on some configuration, while the
type of the layer that's reloaded remains the same. For example, in
Linkerd, we've had to do [this][1], which is really not ideal.
## Solution
This branch removes the `Subscriber` type parameter from `reload::Layer`
and `reload::Handle`. Now, the `Handle` type is only generic over the
type of the inner layer that's being reloaded. It turns out that the
`Subscriber` type parameter was only necessary to add a `L: Layer<S>`
bound to `reload::Layer`'s constructor, which isn't really necessary ---
if the layer does not implement `Layer<S>`, the type error will occur
when `Subscriber::with` is actually used to layer it, which is fine.
I also changed the `with_filter_reloading` option on the `FmtSubscriber`
builder to also work with `LevelFilter`s, since there's no reason for it
not to, and added an example.
Since this breaks existing code, this change has to be made as part of
0.3.
[1]: 6c484f6dcd/linkerd/app/core/src/trace.rs (L19-L36)
## Motivation
The `Entered` guard returned by `Span::enter` represents entering and
exiting a span _on the current thread_. Calling `Span::enter` enters the
span, returning an `Entered`, and dropping the `Entered` ensures that
the span is exited. This ensures that all spans, once entered, are
eventually exited.
However, `Entered` has an auto-impl of `Send`, because it doesn't
contain any `!Send` types. This means that the `Entered` guard _could_
be sent to another thread and dropped. This would cause the original
thread to never exit the span,. and the thread to which the `Entered`
guard was sent would exit a span that it never observed an enter for.
This is incorrect.
## Solution
This PR adds a `*mut ()` field to `Entered` so that it no longer
implements `Send`. There's now a manual `Sync` impl so structs holding
an `Entered` can still be `Sync`.
Fixes#698
Signed-off-by: Eliza Weisman <eliza@buoyant.io>