1550 Commits

Author SHA1 Message Date
Eliza Weisman
4d6e334053
Cache the result of evaluating filters (#38)
Fixes #27.

Currently, every time a `Span` or `Event` is constructed, we test if the
current subscriber cares about it, by calling `Subscriber::enabled` with
the `Span`/`Event`'s metadata. If this function returns false, we don't
construct the span or send the event. However, this means that the
implementation of `enabled` has to be run every time a span or event is
created. If the filtering is expensive (such as a regular expression or
string comparison), this can have a noticeable performance cost.

This branch changes the `span!` and `event!` macros to cache the result
of previous calls to `Subscriber::enabled`, so that filters don't have
to be re-evaluated. Subscribers are given the ability to invalidate
their previously cached filter results, which they may do for various
reasons --- such as if the filter can be dynamically reconfigured at
runtime.

This introduces some potential "gotchas", such as that switching
subscribers will require complete invalidation of all filters. However,
we should be able to address this while making further changes such as
#30.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
2018-10-04 16:38:31 -07:00
Eliza Weisman
c8b3d2ad7e
Remove timestamps from spans and events (#35)
Fixes #24.
Requires #34.

Currently, spans and events both have `std::time::Instant` fields that
record a timestamp of when the span or event was created. Furthermore,
the `Subscriber::enter` and `Subscriber::exit` trait methods take an
`Instant` argument representing a timestamp of when the span was entered
or exited. As described in #24, this is a potential performance issue,
as `Instant::now` may result in an expensive syscall. Since some
subscriber implementations may not need timestamps, or may not need to
record them for _all_ possible events, we should not perform these
syscalls by default.

This branch removes the timestamps from spans and events, and from the
`Subscriber` API. If subscribers require timestamps for events or spans,
they can call `Instant::now` or `SystemTime::now`. This has the side
benefit of allowing subscriber implementations to choose what timestamp
type is appropriate for their use case. 

Since event and span entry/exit notifications are broadcast to
subscribers synchronously as they occur, if a subscriber records a
timestamp itself, it should still be sufficiently accurate.

This branch requires PR #34 to be merged first, so that span 
identifiers may be used for testing span equality, rather than the 
timestamps.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
2018-10-04 14:12:10 -07:00
Eliza Weisman
d7830eba02 Turn new_span_id into new_span (#37)
This branch changes the semantics of that function to be "notifying the
subscriber of the creation of a new span", rather than simply
"requesting a new ID".

This introduces some new guarantees to the `new_span` API (as discussed
in
f7bc34651e (r30777026)),
but I think they can reasonably addressed as part of future changes.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
2018-10-04 14:01:04 -07:00
Eliza Weisman
d389b87cf4 Add span IDs that uniquely identify spans
This branch introduces a `span::Id` type and changes span equality to be
based on the span's `Id`. The `Id` type is used to identify the span
within the context of the process.

These span IDs are intended to be used as a source of truth for
determining whether two span handles are equal. Previously, this
was done based on the span's creation timestamp and metadata, but the
creation timestamps are slated for removal (see #24). When they are
removed, the metadata alone will not be sufficient to uniquely identify
the span, since that would mean two distinct spans created at the same
call site would be "equal".

Similarly, we cannot base span equality on their field values, for a
number of reasons:
+ Two spans with the same metadata and no fields would be equal,
  even if they are distinct periods of time.
+ Similarly, two spans which happen to have the same field values, but
  represent distinct periods of time would also be incorrectly equal.
+ Using field values for equality and hashing would require that
 `Value`s implement `Hash` and `PartialEq`, which they cannot do when
  they are represented by trait objects (as these traits are not object
  safe).
+ Also, comparing the field values would require iterating across all
  the fields.

Currently, the `Id` type is represented by a `u64`. However, the `Id`
type is opaque to downstream users, beyond the contract of implementing
`Clone`, `Hash`, and `PartialEq`, and being able to be _constructed_
from a `u64`, so we could swap out this implementation with something
else later fairly transparently, as long as we can construct it from a
`u64`.

`Subscriber`s are responsible for generating the IDs for each span
(through the `Subscriber::new_span_id` trait method), allowing them to
choose the span ID generation strategy that supports their use case.

Required for #24
2018-10-04 14:01:04 -07:00
Eliza Weisman
374d374b9d
Use fmt::DebugStruct in DebugFields so field names aren't quoted 2018-10-03 14:57:32 -07:00
Eliza Weisman
d782db13b8
Move futures compatibility code to a new tokio-trace-futures crate (#33)
Closes #20. Also needed for #23.

This PR moves the instrumented future types to their own separate crate.
2018-10-02 12:44:29 -07:00
Eliza Weisman
d2f5590e7f
Move log compatibility code to its own crate (#22)
This means that the core `tokio_trace` crate no longer has to depend on `log`; see #20.

* Move `LogSubscriber` to the tokio-trace-log crate

* Add nicer conversion traits

* Replace log::Level re-export with our own type
2018-10-01 15:33:27 -07:00
Eliza Weisman
8f10485803
Remove implicit root span (#21)
Fixes #10. Also required for #20.

Currently, any span created at the top level is implicitly a child of
the "root span" that is created when the program starts and lasts for
its entire lifespan. Removing the implicit root span would allow
subscribers to more easily distinguish between "separate" traces, such
as per-request traces in a server application. 

See also:
+ https://github.com/hawkw/tokio-trace-prototype/issues/4#issuecomment-424165691  
+ https://github.com/hawkw/tokio-trace-prototype/issues/4#issuecomment-424167537

Also, the implicit root span is an artifact of prior implementation 
constraints and it is no longer required.

This branch removes the implicit root span. It also removes the
dependency on the `lazy_static` crate.

Note that this also changes the `event.parent` field to an
`Option<SpanData>` rather than just a `SpanData`.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
2018-10-01 14:04:05 -07:00
Eliza Weisman
14e87beaff
Implement span filtering (#17)
Fixes #14, #15.

Since span creation is relatively expensive (it causes multiple
allocations, for the span itself and for any associated values), spans
which no subscribers will record should never be created. 

This branch implements this feature by adding an `enabled` method to the
`Subscriber` trait, similar to the method of the same name on the `log`
crate's `Log` trait. This method is called to determine whether a
`Subscriber` is interested in a particular span or event, based on its
metadata. If no `Subscriber`s return true, the span or event is never
constructed. Metadata construction is significantly less expensive than
`Span` construction (especially since for `Span`s, it can always be
constructed statically), so the filtering is based on metadata only. To
allow spans to be filtered by name (as span names are also always
`'static`), the name field was moved to the `Meta` type as well.

In order to make the `span!` macro API function the same as it did prior
to this PR, the internals of the `Span` type were changed somewhat to
allow spans which are disabled to be created. Disabled spans will not 
allocate, and entering a disabled span does nothing. 

This means that code like
```rust
span!("foo").enter(|| {
    // do stuff
})
```
still works, even if no subscriber expresses interest in the span.

This makes the span internals somewhat more complex, but it seemed
better than the alternative of having the `span!` macro evaluate to
`None` if the span is not enabled, as that required additional complexity
at the _call site_ rather than internally to `tokio-trace`

In addition, a `with_filter` method was added to `Subscriber`, to allow
composing subscribers from external crates with a user-defined filtering
predicate.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>

* Move span names to metadata for filtering

* Add `enabled` function to `Subscriber` trait

* Only construct events that are enabled

* Only create spans if a subscriber currently cares about them

* Add `Subscriber::with_filter` for composing Subscribers with predicates

Signed-off-by: Eliza Weisman <eliza@buoyant.io>

* Reduce `#[doc(hidden)] pub` internal API surface

These undocumented pub functions are used by the `span!`  and `event!` macros. Since they are technically public API even though they are hidden and not intended for external use, they should be kept as limited as possible.

* Add docs
2018-09-30 17:19:35 -07:00
Eliza Weisman
b2e60146aa
fix span entry in hyper example 2018-09-30 14:39:07 -07:00
Eliza Weisman
9008d14497
Add doctests for span macro 2018-09-30 13:02:50 -07:00
Eliza Weisman
ef2edd1b95
Fix span creation with no fields requiring a trailing comma 2018-09-30 13:02:37 -07:00
Eliza Weisman
1d33decba1
make hyper-echo demo fancier 2018-09-28 15:59:00 -07:00
Eliza Weisman
bff434aa24
improve span structure in hyper-echo example 2018-09-28 15:52:42 -07:00
Eliza Weisman
9de9eab1d7
rename tower-h2-server example so it works with logger scopes 2018-09-28 15:24:09 -07:00
Eliza Weisman
e9efe92ac6
fix Parents iterator skipping immediate parent 2018-09-28 15:24:09 -07:00
Eliza Weisman
ff850726ca
fix tower-h2 example not entering server span 2018-09-28 15:24:07 -07:00
Eliza Weisman
0ca0e79772
Make tower-h2 example more like the tower-ts/tower-h2@master version 2018-09-28 14:51:03 -07:00
Eliza Weisman
99e31376ff Add parents and all_fields methods to span::Data refs 2018-09-28 14:10:12 -07:00
Eliza Weisman
df40463a38 Improve Event::parents RustDoc 2018-09-28 14:10:12 -07:00
Eliza Weisman
e3276d8a0a Fix Event::all_fields doctest 2018-09-28 14:10:12 -07:00
Eliza Weisman
90f03157f9 Add RustDoc to span::Data methods 2018-09-28 14:10:12 -07:00
Eliza Weisman
b7a90528e3 Add RustDoc to Event methods + formatting 2018-09-28 14:10:12 -07:00
Eliza Weisman
2256962080 Add function to get an individual field on a span or event 2018-09-28 14:10:12 -07:00
Eliza Weisman
dfa8e7cd0a
Add a notion of "doneness" to Spans and allow them to mark themselves as done (#8)
Fixes #4.

This branch adds a notion of "doneness" to spans and allows spans to
mark themselves as "done" when they can no longer be entered. Spans know
when they are done by tracking the number of handles which may enter the
span; this means that the `Span::enter` API function had to be changed
to take the span by-value rather than by-reference. This meant some
other stuff had to be changed.

This branch also makes it possible to get _non-entering_ handles to a
span. These data handles keep the span's data alive, but may not
re-enter the span. This allows spans to mark themselves as done while
`Subscriber`s are still hanging on to references of their data, keeping
it alive.

Admittedly, this was a bit of a yak shave, but I also threw together a
quick mocking DSL for writing tests for this functionality. That code is
still a work in progress.

* move span to its own module

* Add states to spans

* WIP automatic span closure

* Make span module compile-y

* make core crate more compile-y

* make sloggish test compile

* whoa, something resembling unit tests!

* fix issue where span states transition _after_ notifying subscriber

* make test DSL nicer

* document span completion test

* fix test support code breaking when there's multiple tests

* add test for concurrently executing multiple threads

* Spans remain "running" as long as any thread is in the span

* add test for future span completion

* instrumented futures/streams mark their spans as done when completing

* Leave sinks be (they can't finish until the sink is dropped)

* refactor, make lock-free

* remove unused

* fix post-rebase breakage

* make everything else work with doneness API changes

* more docs

* Fix typo in comment

* Make converting from Span handles to Data handles more ergonomic

* Fix missing macro import breaking doctests

* add docs for internal span implementation types

* Clarify and factor out ActiveSpan state transition logic

* fix up rename

* fix doctest on stable compiler
2018-09-27 15:53:35 -07:00
Eliza Weisman
cfabda9aa4
fix lifetime issues with event macro 2018-09-27 15:41:52 -07:00
Eliza Weisman
e54b294de2
fix tower-h2 example 2018-09-27 13:59:19 -07:00
Eliza Weisman
0a77774d41
fix travis build on stable Rust 2018-09-27 13:51:33 -07:00
Eliza Weisman
9c7e25a23b
add travis config 2018-09-27 13:21:09 -07:00
Eliza Weisman
f660e6137a
Fix breakage in log-compat crate 2018-09-26 16:46:32 -07:00
Eliza Weisman
6e4325059c
fix non-compile-y doctest 2018-09-26 16:40:00 -07:00
Eliza Weisman
f9e2903ad1
delete non-compiley example that was comitted by mistake 2018-09-26 16:38:53 -07:00
Eliza Weisman
a79927ea8c
Start adding top-level docs to the main lib (#7)
* start adding mediocre docs

* review feedback (thanks @davidbarsky)
2018-09-25 14:29:29 -07:00
Eliza Weisman
daaa75db4e
Add compatibility crates for log and env_logger (#6)
This branch adds `tokio-trace-log` and `tokio-trace-env-logger`
compatibility crates which can be used to bring log records emitted by
crates using the `log` library into the context of a trace.

Loggers are provided which implement the `log::Log` trait by converting
log records into events in the span that is executing when the record is
logged, and propagates them to the trace dispatcher. This conversion is
not capable of parsing unstructured log messages and converting them
into a structured format (as this would require some form of
natural-language processing to implement correctly), but allows log
records to be placed within the context of a span. This is useful as a
migration path for codebases which already use unstructured logging, and
as a way for codebases using `tokio-trace` to to connect the log records
emitted by dependencies with the tracing system without requiring
upstream code changes.

* Event metadata need not be 'static, so it can be generated from log meta

* first pass on an adapter for the log crate

* add doc to log adapter

* feature-flag env-logger compat and move it to a module

* actually, just put env-logger compat in a separate crate

feature flags are more confusing for downstream users.

* improve log compat crate docs

* remove unneeded deps from tokio-trace-log Cargo.toml

* document Event lifetime parameters
2018-09-25 13:57:22 -07:00
Eliza Weisman
0cddea3ba8 make tower-h2 example prettier 2018-09-24 13:44:33 -07:00
Eliza Weisman
06a9e8a7de Fix bug where spans were sometimes not popped on exit 2018-09-24 13:44:33 -07:00
Eliza Weisman
46c54ea0d1 Make SloggishSubscriber smarter about span re-entry (and make Span Hash) 2018-09-24 13:44:33 -07:00
Eliza Weisman
6191b515c2 Quick demo of instrumenting Futures and Tower with spans 2018-09-24 13:44:33 -07:00
Eliza Weisman
deb5f5e1ac Tower services are now instrumentable 2018-09-24 13:44:33 -07:00
Eliza Weisman
13e3260439 Futures, Streams, and Sinks can now be instrumented with spans 2018-09-24 13:44:33 -07:00
Eliza Weisman
04864e0d24 use Instants rather than SystemTime for monotonicity (#3) 2018-09-21 18:14:53 -04:00
Eliza Weisman
5227152797
split out sloggish formatter for future use in other examples 2018-09-21 14:43:27 -07:00
Eliza Weisman
fc2e07e883
rustfmt all the things 2018-09-21 14:43:06 -07:00
Eliza Weisman
b7e932a8a7 make sloggish example formatting more slog-ish 2018-09-21 14:06:12 -07:00
Eliza Weisman
2acfb3f7d1 replace instants with SystemTime 2018-09-21 14:06:12 -07:00
Eliza Weisman
f2f3cdfbe4 working slog-style example 2018-09-21 14:06:12 -07:00
Eliza Weisman
655121dd3f add stuff needed for sloglike example 2018-09-21 14:06:12 -07:00
Eliza Weisman
5b903b9002 start on fake Slog example 2018-09-21 14:06:12 -07:00
David Barsky
e50e244915
Created a workspace and an empty slog package.
Signed-off-by: David Barsky <dbarsky@amazon.com>
2018-09-21 11:21:37 -07:00
Eliza Weisman
6a99b1093c
sketch core types 2018-09-21 11:21:37 -07:00