-
Notifications
You must be signed in to change notification settings - Fork 731
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
subscriber: fix spans never being removed from the registry #435
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
hawkw
added
kind/bug
Something isn't working
crate/subscriber
Related to the `tracing-subscriber` crate
labels
Nov 18, 2019
davidbarsky
approved these changes
Nov 18, 2019
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.
Nice catch!
This fixes an issue where the test `span_is_removed_from_registry` did not actually ensure the correct behavior. This test asserts that a span extension was dropped after the span closes. Previously, the test used `subscriber::with_default`, and then made the assertion _outside_ of the `with_default` block. However, this was incorrect, as even if the `Registry` fails to drop the span, the span extension will be dropped when the whole `Registry` itself is dropped, at the end of the `with_default` block. This commit changes the test to use an explicit `Dispatch` to keep the registry alive until the end of the test. This reveals that the span is _not_ being removed as it should be. Thanks to @jtescher for catching this bug! Signed-off-by: Eliza Weisman <[email protected]>
Signed-off-by: Eliza Weisman <[email protected]>
Signed-off-by: Eliza Weisman <[email protected]>
hawkw
force-pushed
the
eliza/fix-on-close
branch
from
November 18, 2019 22:26
8000951
to
e248703
Compare
@davidbarsky this branch now fixes several bugs that I found after fixing the first one (it was preventing them from ever occurring). I've updated the PR description to reflect this. |
hawkw
added a commit
that referenced
this pull request
Feb 4, 2020
0.2.0 (February 4, 2020) Breaking Changes: - **fmt**: Renamed `Context` to `FmtContext` (#420, #425) - **fmt**: Renamed `Builder` to `SubscriberBuilder` (#420) - **filter**: Removed `Filter`. Use `EnvFilter` instead (#434) Added: - **registry**: `Registry`, a reusable span store that `Layer`s can use a high-performance, in-memory store. (#420, #425, #432, #433, #435) - **registry**: Added `LookupSpan` trait, implemented by `Subscriber`s to expose stored span data to `Layer`s (#420) - **fmt**: Added `fmt::Layer`, to allow composing log formatting with other `Layer`s (#420) - **fmt**: Added support for JSON field and event formatting (#377, #415) - **filter**: Documentation for filtering directives (#554) Changed: - **fmt**: Renamed `Context` to `FmtContext` (#420, #425) (BREAKING) - **fmt**: Renamed `Builder` to `SubscriberBuilder` (#420) (BREAKING) - **fmt**: Reimplemented `fmt::Subscriber` in terms of the `Registry` and `Layer`s (#420) Removed: - **filter**: Removed `Filter`. Use `EnvFilter` instead (#434) (BREAKING) Fixed: - **fmt**: Fixed memory leaks in the slab used to store per-span data (3c35048) - **fmt**: `fmt::SubscriberBuilder::init` not setting up `log` compatibility (#489) - **fmt**: Spans closed by a child span closing not also closing _their_ parents (#514) - **Layer**: Fixed `Layered` subscribers failing to downcast to their own type (#549) - **Layer**: Fixed `Layer::downcast_ref` returning invalid references (#454) Signed-off-by: Eliza Weisman <[email protected]>
hawkw
added a commit
that referenced
this pull request
Feb 4, 2020
# 0.2.0 (February 4, 2020) ### Breaking Changes - **fmt**: Renamed `Context` to `FmtContext` (#420, #425) - **fmt**: Renamed `Builder` to `SubscriberBuilder` (#420) - **filter**: Removed `Filter`. Use `EnvFilter` instead (#434) ### Added - **registry**: `Registry`, a `Subscriber` implementation that `Layer`s can use as a high-performance, in-memory span store. (#420, #425, #432, #433, #435) - **registry**: Added `LookupSpan` trait, implemented by `Subscriber`s to expose stored span data to `Layer`s (#420) - **fmt**: Added `fmt::Layer`, to allow composing log formatting with other `Layer`s - **fmt**: Added support for JSON field and event formatting (#377, #415) - **filter**: Documentation for filtering directives (#554) ### Changed - **fmt**: Renamed `Context` to `FmtContext` (#420, #425) (BREAKING) - **fmt**: Renamed `Builder` to `SubscriberBuilder` (#420) (BREAKING) - **fmt**: Reimplemented `fmt::Subscriber` in terms of the `Registry` and `Layer`s (#420) ### Removed - **filter**: Removed `Filter`. Use `EnvFilter` instead (#434) (BREAKING) ### Fixed - **fmt**: Fixed memory leaks in the slab used to store per-span data (3c35048) - **fmt**: `fmt::SubscriberBuilder::init` not setting up `log` compatibility (#489) - **fmt**: Spans closed by a child span closing not also closing _their_ parents (#514) - **Layer**: Fixed `Layered` subscribers failing to downcast to their own type (#549) - **Layer**: Fixed `Layer::downcast_ref` returning invalid references (#454) Fixes #515 Fixes #458 Signed-off-by: Eliza Weisman <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation
This branch fixes several bugs in the
Registry
span close logic, andadds new tests for these issues.
Solutions
on_close
There is currently a bug in the
Registry
that prevents spans frombeing removed, even when all
on_close
callbacks are complete. The testfor this behavior (
span_is_removed_from_registry
) fails to catch thebug, since there is a bug in the test as well.
The test asserts that a span extension was dropped after the span
closes. Current, the test uses
subscriber::with_default
, and thenmade the assertion outside of the
with_default
block. However, thiswas incorrect, as even if the
Registry
fails to drop the span, thespan extension will be dropped when the whole
Registry
itself isdropped, at the end of the
with_default
block.This branch fixes the test, and the bug in the close logic. I've changed
the test to use an explicit
Dispatch
to keep the registry alive untilthe end of the test. This reveals that the span is not being removed
as it should be.
The reason the span fails to be removed is that the
Drop
implementation for
CloseGuard
drops the span if the value of theCLOSE_COUNT
cell is 0. However, theif
statement that tests for thiscompares the value returned by
Cell::get
with 0. The value returned byCell::get
is the previous value, not the current one after droppingthis guard; if the guard being dropped is the final guard, then the
value returned by
Cell::get
will be 1, rather than 0.I've fixed this logic, and refactored it slightly to hopefully make it
easier to understand in the future.
Thanks to @jtescher for catching this bug!
on_close
In addition, I've fixed a bug where the remove after close logic would
only work for the first span to close on each thread. This is because
dropping a
CloseGuard
does not currently subtract from CLOSE_COUNTwhen it is the final guard. This means that when the next span is
closed, the count will start at 1, rather than 0. I've fixed this by
ensuring that the close count is always decremented, and changed the
tests to close multiple spans.
try_close
Finally, there is also an issue where the removal logic is run on
every call to
try_close
, regardless of whether or not the subscriberactually indicates that the span closes. This means that a span will be
removed from the registry even when there are one or more span handles
that reference it.
This is due to the
start_close
method being called beforeSubscriber::try_close
is called. When a close guard is dropped, thespan is currently always removed. However, since we call
start_close
at the beginning of the
Layered::try_close
method, we may bedecrementing a ref count without closing the span, but the close guard
is unaware of this.
I've fixed this bug by updating the
CloseGuard
struct to track whetherthe span is closed. It now has a bool that is set only when the
Subscriber::try_close
call returns true.Only creating the
CloseGuard
iftry_close
returns true may seem likea simpler solution, but that won't work, since the call to
try_close
may call into another
Layered
subscriber. In order to handlesituations where many layers are nested, we need to construct the
CloseGuard
for each stack frame before calling into the next one, soit's necessary to set whether the span is closing only after the call to
try_close
returns.