New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tokio: Enable trace subscriber propagation in the runtime #966
Conversation
I'm +1 on this, though would we want to put it behind a |
@LucioFranco The thinking re: feature flag is adding a feature flag includes it permanently in the public dependency (feature flags are public). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine w/ me. I would like to get reviews from @seanmonstar and @stjepang.
src/runtime/threadpool/builder.rs
Outdated
.around_worker(move |w, enter| { | ||
let index = w.id().to_usize(); | ||
let dispatch = dispatch.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this clone required? It seems like most of the other with_default
things are fine with a reference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seanmonstar A Dispatch
is internally just an Arc
--- we could potentially make with_default
take an &Dispatch
and perform the clone itself. I thought it was better to take it by value since the dispatcher might not always need to be cloned when with_default
is used in other cases`...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s a good point. with_dispatch should probably take a ref to follow the pattern.
The fn can clone internally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've opened #971 to make this change. As I had suspected, it has the downside of requiring the arc to be cloned twice when entering a span using the tokio-trace::Span
type. If we decide this is acceptable, I can rebase onto that branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting the dispatcher every time a span is entered is unexpected to me. Can you expand on that decision?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting the dispatcher every time a span is entered is unexpected to me. Can you expand on that decision?
Setting the default dispatcher on span entry is a relic of when spans tracked their parent's ID. At that time, it was necessary to ensure that any spans created inside a span were observed by the same subscriber that originally provided the entered span with an ID, as otherwise, new spans would be created with parent IDs that did not originate from that subscriber.
Now that spans don't track their parent ID, this is no longer necessary. However, removing this behavior does mean that if a span is entered outside of the subscriber context it was created in, any subsequent spans will be observed by the current default subscriber and thus will not be part of the original span's trace tree. Since subscribers are not expected to change frequently, and spans are not expected to move between them, this is likely acceptable.
I've removed this on my branch for #971 in commit 345567d.
Not setting the dispatcher on entry does make span entry/exit significantly faster. Here are the results of running a benchmark that enters a span, does nothing, and immediately exits it, before this change:
test enter_span ... bench: 93 ns/iter (+/- 14)
...and after:
test enter_span ... bench: 51 ns/iter (+/- 9)
To expand just a little bit on Carl's comment, I just wanted to point out that since the dispatcher propagation is (currently) only done implicitly, this branch doesn't actually expose anything from In this case, the main reason users might want to disable a |
* trace-core: Pass dispatcher by ref to `dispatcher::with_default` As requested by @carllerche in #966 (comment), this branch changes the `dispatcher::with_default` function in `tokio-trace-core` to take the dispatcher by ref and perform the clone internally. This makes this function more consistant with other `with_default` functions in other crates. Signed-off-by: Eliza Weisman <eliza@buoyant.io> * trace: Don't set the default dispatcher on entering a span Setting the default dispatcher on span entry is a relic of when spans tracked their parent's ID. At that time, it was necessary to ensure that any spans created inside a span were observed by the same subscriber that originally provided the entered span with an ID, as otherwise, new spans would be created with parent IDs that did not originate from that subscriber. Now that spans don't track their parent ID, this is no longer necessary. However, removing this behavior does mean that if a span is entered outside of the subscriber context it was created in, any subsequent spans will be observed by the current default subscriber and thus will not be part of the original span's trace tree. Since subscribers are not expected to change frequently, and spans are not expected to move between them, this is likely acceptable. I've removed the tests for the old behavior. Note that this change improves the performance of span entry/exit fairly significantly. Here are the results of running a benchmark that enters a span, does nothing, and immediately exits it, before this change: ``` test enter_span ... bench: 93 ns/iter (+/- 14) ``` ...and after: ``` test enter_span ... bench: 51 ns/iter (+/- 9) ``` Signed-off-by: Eliza Weisman <eliza@buoyant.io>
f4e2ff1
to
d289d35
Compare
I've rebased this branch onto master and marked it as "ready for review", but I think we'll want to actually get a |
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
d289d35
to
8c6c972
Compare
src/runtime/threadpool/builder.rs
Outdated
|
||
tokio_reactor::with_default(&reactor_handles[index], enter, |enter| { | ||
clock::with_default(&clock, enter, |enter| { | ||
timer::with_default(&timer_handles[index], enter, |_| { | ||
w.run(); | ||
dispatcher::with_default(dispatch, || { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noting, out of context, "dispatcher" sounds like a task dispatcher, not something about traces...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seanmonstar in f409c12, I changed the way the Dispatch
type and the dispatcher
module are imported so that they're all namespaced as trace::dispatcher
--- hopefully that's clearer!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do agree w/ sean... trace::dispatcher
helps some. IMO it would be better if it was trace::subscriber
, but I also know why it isn't subscriber (Dispatcher::new(subscriber)
).
I'm not going to make a request either way. I just wanted to provide these thoughts to @seanmonstar and @hawkw
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
87b6ec3
to
e31d5d1
Compare
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
e31d5d1
to
f409c12
Compare
* trace-core: Pass dispatcher by ref to `dispatcher::with_default` As requested by @carllerche in tokio-rs/tokio#966 (comment), this branch changes the `dispatcher::with_default` function in `tokio-trace-core` to take the dispatcher by ref and perform the clone internally. This makes this function more consistant with other `with_default` functions in other crates. Signed-off-by: Eliza Weisman <eliza@buoyant.io> * trace: Don't set the default dispatcher on entering a span Setting the default dispatcher on span entry is a relic of when spans tracked their parent's ID. At that time, it was necessary to ensure that any spans created inside a span were observed by the same subscriber that originally provided the entered span with an ID, as otherwise, new spans would be created with parent IDs that did not originate from that subscriber. Now that spans don't track their parent ID, this is no longer necessary. However, removing this behavior does mean that if a span is entered outside of the subscriber context it was created in, any subsequent spans will be observed by the current default subscriber and thus will not be part of the original span's trace tree. Since subscribers are not expected to change frequently, and spans are not expected to move between them, this is likely acceptable. I've removed the tests for the old behavior. Note that this change improves the performance of span entry/exit fairly significantly. Here are the results of running a benchmark that enters a span, does nothing, and immediately exits it, before this change: ``` test enter_span ... bench: 93 ns/iter (+/- 14) ``` ...and after: ``` test enter_span ... bench: 51 ns/iter (+/- 9) ``` Signed-off-by: Eliza Weisman <eliza@buoyant.io>
* trace-core: Pass dispatcher by ref to `dispatcher::with_default` As requested by @carllerche in tokio-rs/tokio#966 (comment), this branch changes the `dispatcher::with_default` function in `tokio-trace-core` to take the dispatcher by ref and perform the clone internally. This makes this function more consistant with other `with_default` functions in other crates. Signed-off-by: Eliza Weisman <eliza@buoyant.io> * trace: Don't set the default dispatcher on entering a span Setting the default dispatcher on span entry is a relic of when spans tracked their parent's ID. At that time, it was necessary to ensure that any spans created inside a span were observed by the same subscriber that originally provided the entered span with an ID, as otherwise, new spans would be created with parent IDs that did not originate from that subscriber. Now that spans don't track their parent ID, this is no longer necessary. However, removing this behavior does mean that if a span is entered outside of the subscriber context it was created in, any subsequent spans will be observed by the current default subscriber and thus will not be part of the original span's trace tree. Since subscribers are not expected to change frequently, and spans are not expected to move between them, this is likely acceptable. I've removed the tests for the old behavior. Note that this change improves the performance of span entry/exit fairly significantly. Here are the results of running a benchmark that enters a span, does nothing, and immediately exits it, before this change: ``` test enter_span ... bench: 93 ns/iter (+/- 14) ``` ...and after: ``` test enter_span ... bench: 51 ns/iter (+/- 9) ``` Signed-off-by: Eliza Weisman <eliza@buoyant.io>
* trace-core: Pass dispatcher by ref to `dispatcher::with_default` As requested by @carllerche in tokio-rs/tokio#966 (comment), this branch changes the `dispatcher::with_default` function in `tokio-trace-core` to take the dispatcher by ref and perform the clone internally. This makes this function more consistant with other `with_default` functions in other crates. Signed-off-by: Eliza Weisman <eliza@buoyant.io> * trace: Don't set the default dispatcher on entering a span Setting the default dispatcher on span entry is a relic of when spans tracked their parent's ID. At that time, it was necessary to ensure that any spans created inside a span were observed by the same subscriber that originally provided the entered span with an ID, as otherwise, new spans would be created with parent IDs that did not originate from that subscriber. Now that spans don't track their parent ID, this is no longer necessary. However, removing this behavior does mean that if a span is entered outside of the subscriber context it was created in, any subsequent spans will be observed by the current default subscriber and thus will not be part of the original span's trace tree. Since subscribers are not expected to change frequently, and spans are not expected to move between them, this is likely acceptable. I've removed the tests for the old behavior. Note that this change improves the performance of span entry/exit fairly significantly. Here are the results of running a benchmark that enters a span, does nothing, and immediately exits it, before this change: ``` test enter_span ... bench: 93 ns/iter (+/- 14) ``` ...and after: ``` test enter_span ... bench: 51 ns/iter (+/- 9) ``` Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Motivation
One of the biggest pain points in the current
tokio-trace
API is thatthe subscriber context must be propagated manually. For example, if a
user
tokio::spawn
s a future, the spawning thread's subscriber will notbe propagated to the worker thread the spawned future actually executes
on.
Users can currently get around this one of two ways:
while inside the span, this will both propagate the dispatcher
context and create a span for the future. However, if the span is
disabled, then the dispatcher will not be set, which can lead to
surprising and unexpected behavior.
instrumented with a span, and regardless of whether or not any spans
are enabled. However, it requires some extra noise and is perhaps
non-obvious.
Additionally, the following issues apply to both of these approaches:
tokio-trace-futures
crate, which is in thenursery and thus less stable than the core
tokio-trace
crates.tokio::spawn
or similar functions (areasonably common pattern!) there is nothing that user code can do
to ensure that futures spawned by libraries also propagate the
subscriber context correctly.
Solution
This branch modifies
runtime::Builder::build
so that the currenttrace subscriber context is captured, and adds a call to
tokio_trace_core::dispatcher::with_default
in the closure passedto
around_worker
in the runtime builder's threadpool builder. Thisresults in the dispatcher context being propagated to all of the worker
threads in the runtime.
Notes
tokio
to depend ontokio-trace-core
.Therefore, we should not merge this branch until a 0.1 release of
tokio-trace-core
is published to crates.io.provided dispatcher. Adding a function to allow this would require a
dependency on
tokio-trace-core
intokio
's public API surface,and I believe that we haven't yet decided that
tokio-trace-core
isstable enough for that. This can be added later.
Fixes: #947
Signed-off-by: Eliza Weisman eliza@buoyant.io