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>
This branch updates all crate versions to 0.2.x. After this PR merges,
we can now develop `tracing`/`tracing-core` v0.2.x on `master`.
There is now a separate, protected `v0.1.x` branch. Changes backported
to 0.1 versions of `tracing` crates can be merged to that branch.
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
The `opentelemetry` crate depends on `prometheus`, which depends on
`protobuf`, a crate which doesn't compile on our MSRV (Rust 1.39). This
was missed due to issues with the MSRV CI checks, which will be fixed
fixed in #934. Therefore, once the MSRV checks work properly, the
`protobuf` dependency will break our builds.
We don't _need_ the `opentelemetry/metrics` feature, which is what
enables the `prometheus` (and thus `protobuf`) dependency.
`tracing-opentelemetry` already has a `default-features = false`
dependency on `opentelemetry`, but the examples don't. Therefore, I've
changed the examples crate to disable `opentelemetry`'s default features
as well.
## Motivation
Fixes#894
## Solution
This PR implements Layer for Option, allowing users to wrap a Layer with
an Option, allowing it to be passed internally wherever Layer is used
there by allowing by allowing layers to be enabled or disabled.
Using this with `reload` further allows a Layer to be dynamically
toggled based by using `handle.modify`
This PR also consists of a basic example.
Signed-off-by: Tarun Pothulapati <tarunpothulapati@outlook.com>
### Fixed
- **env-filter**: Incorrect max level hint when filters involving span
field values are in use (#907)
- **registry**: Fixed inconsistent span stacks when multiple registries
are in use on the same thread (#901)
### Changed
- **env-filter**: `regex` dependency enables fewer unused feature flags
(#899)
Thanks to @bdonlan and @jeromegn for contributing to this release!
### Fixed
- **docs**: Incorrect formatting (#862)
### Changed
- **filter**: `LevelFilter` is now a re-export of the
`tracing_core::LevelFilter` type, it can now be used interchangably
with the versions in `tracing` and `tracing-core` (#853)
- **filter**: Significant performance improvements when comparing
`LevelFilter`s and `Level`s (#853)
- Updated the minimum `tracing-core` dependency to 0.1.12 (#853)
### Added
- **filter**: `LevelFilter` and `EnvFilter` now participate in
`tracing-core`'s max level hinting, improving performance
significantly in some use cases where levels are disabled globally
(#853)
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Some opentracing systems use fields with : in the names, which are not
legal rust identifiers. We could special case :, but then we have
complicated double-nested patterns (repeated idents separated by : and a
nested repeat separated by .), and this may by a case of always being
one-step-behind as more cases turn up; so this patch instead just gets
in front and lets users put in whatever they want: as they are not rust
identifiers, they miss out on some niceness.
## Solution
This permits : in field names but also potentially anything
stringifiable, which may be overly liberal.
Signed-off-by: Robert Collins <robert.collins@cognite.com>
### Fixed
- **fmt**: Fixed compilation failure on MSRV when the `chrono` feature
is disabled (#844)
### Added
- **fmt**: Span lookup methods defined by `layer::Context` are now also
provided by `FmtContext` (#834)
### Changed
- **fmt**: When the `chrono` dependency is enabled, the `SystemTime`
timestamp now emits human-readable timestamps rather than using
`SystemTime`'s fmt::Debug`implementation (`chrono` is still required
for customized timestamp formatting) (#807)
- **ansi**: Updated `ansi_term` dependency to 0.12 (#816)
### Added
- **json**: `with_span_list` method to configure the JSON formatter to
include a list of all spans in the current trace in formatting events
(similarly to the text formatter) (#741)
- **json**: `with_current_span` method to configure the JSON formatter
to include a field for the _current_ span (the leaf of the trace) in
formatted events (#741)
- **fmt**: `with_thread_names` and `with_thread_ids` methods to
configure `fmt::Subscriber`s and `fmt::Layer`s to include the thread
name and/or thread ID of the current thread when formatting events
(#818)
Thanks to new contributors @mockersf, @keetonian, and @Pothulapati for
contributing to this release!
## Motivation
Fixes#809
## Solution
This PR adds two new methods i.e `with_thread_ids` and
`with_thread_names` to the fmt Layer which passed till
the pre-configured Format type, where the check is performed
and these the above values are formatted based on the flags.
The formatting is done by creating to new Types that impl Display
for Id and Name. For Thread Name, we keep track of the max length
of the thread name that occured till now using a thread safe static
type and pad accordingly. For Thread Id, we pad directly with 2
as in most cases we would see a double digit number of threads.
Signed-off-by: Tarun Pothulapati <tarunpothulapati@outlook.com>