Skip to content
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

Remove default impl of Collect::current_span #1268

Merged

Conversation

lenaschoenburg
Copy link
Contributor

Motivation

This removes the default implementation of tracing_core::Collect::current_span, which implements part one of #1262.

Solution

  1. Removes the default implementation
  2. Makes tracing_core::span::Current::unknown public so that implementers of Collect can use it if they didn't implement current_span() before.
  3. Copy the old default implementation to all implementers of Collect

@lenaschoenburg
Copy link
Contributor Author

We could also add a re-export of tracing_core::span::Current as tracing::span::Current which would look a bit nicer when implementing Collect.

@lenaschoenburg lenaschoenburg changed the title Remove current span default impl Remove default impl of Collect::current_span Feb 25, 2021
@lenaschoenburg
Copy link
Contributor Author

I keep forgetting to run cargo check --all --bins --tests --benches so there are a bunch of places still left that now need to implement current_span.

@lenaschoenburg lenaschoenburg force-pushed the remove-current-span-default-impl branch from 9a832b7 to 2c64332 Compare February 25, 2021 21:23
Comment on lines 524 to 536
fn current_span(&self) -> tracing_core::span::Current {
todo!()
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why's this one todo'd, whereas all the others are unknown?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the test collector probably should actually implement this, it knows the ID of the current span:

current: Mutex<Vec<Id>>,

and it can look up spans by ID:
spans: Mutex<HashMap<Id, SpanState>>,

similar to the sloggish example collector, we would need to add the metadata to the stored span data to implement this properly. in this case, the stored span data is the SpanState struct:

struct SpanState {
name: &'static str,
refs: usize,
}

we could pretty easily add a &'static Metadata<'static> to that, allowing us to actually return the current span.

i think this is somewhat important; even though none of the tests currently use the mock collector's current_span method, it should probably implement the behavior correctly so that we're not surprised when writing future tests that expect it to work...

Copy link
Member

@hawkw hawkw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this feels like a good start. i think there's a few places where we probably ought to add real current_span implementations instead of just returning unknown. once that's taken care of, I'll be happy to merge this!

@@ -265,4 +266,8 @@ impl Collect for SloggishCollector {
// TODO: GC unneeded spans.
false
}

fn current_span(&self) -> Current {
Current::unknown()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this example, the collector does know the current span's ID:

current: CurrentSpanPerThread,

so, maybe this should return that span? this would require a slightly larger change, modifying the Span struct to also include a &'static Metadata<'static> that's stored in new_span, but then we could write something like this:

Suggested change
Current::unknown()
if let Some(id) = self.current.id() {
let metadata = self.spans
.lock()
.unwrap()
.get(id)
.unwrap_or_else(|| panic!("no metadata stored for span with ID {:?}", id))
.metadata;
return Current::new(id, metadata);
}
Current::none()

tracing-core/src/collect.rs Show resolved Hide resolved
@@ -853,6 +857,10 @@ impl Collect for NoCollector {

fn enter(&self, _span: &span::Id) {}
fn exit(&self, _span: &span::Id) {}

fn current_span(&self) -> span::Current {
span::Current::unknown()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, this doesn't really matter: i think it might be more correct for the no-op collector to return none rather than unknown — the intended semantics is that all spans are disabled when there's no collector, so we are never in a span. with that said, it doesn't really make a difference in practice.

Comment on lines 524 to 536
fn current_span(&self) -> tracing_core::span::Current {
todo!()
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the test collector probably should actually implement this, it knows the ID of the current span:

current: Mutex<Vec<Id>>,

and it can look up spans by ID:
spans: Mutex<HashMap<Id, SpanState>>,

similar to the sloggish example collector, we would need to add the metadata to the stored span data to implement this properly. in this case, the stored span data is the SpanState struct:

struct SpanState {
name: &'static str,
refs: usize,
}

we could pretty easily add a &'static Metadata<'static> to that, allowing us to actually return the current span.

i think this is somewhat important; even though none of the tests currently use the mock collector's current_span method, it should probably implement the behavior correctly so that we're not surprised when writing future tests that expect it to work...

@lenaschoenburg lenaschoenburg force-pushed the remove-current-span-default-impl branch from 5639206 to 87a6b13 Compare February 26, 2021 21:18
@lenaschoenburg
Copy link
Contributor Author

Sorry, I should have marked this as WIP earlier. I'll try to implement current_span properly where it makes sense but it might take me a while. I don't want to take up too much of your resources or block the release of 0.2 so feel free work on it yourself in the meantime.

@lenaschoenburg lenaschoenburg marked this pull request as draft February 26, 2021 22:08
@lenaschoenburg lenaschoenburg force-pushed the remove-current-span-default-impl branch 2 times, most recently from 654b790 to 4eeb779 Compare February 27, 2021 14:31
@lenaschoenburg lenaschoenburg marked this pull request as ready for review February 27, 2021 14:57
@lenaschoenburg
Copy link
Contributor Author

Okay, I think I implemented all suggestions. From my side there is only one open question: #1268 (comment)

@davidbarsky
Copy link
Member

@dignati Sorry for the delay in responding.

We could also add a re-export of tracing_core::span::Current as tracing::span::Current which would look a bit nicer when implementing Collect.

I think we can keep this as-is for now and not worry about it. If you could rebase again the master branch (or I can do it for you!), then I think we're clear to merge this in.

@lenaschoenburg lenaschoenburg force-pushed the remove-current-span-default-impl branch from 1931e2d to 76e6462 Compare March 21, 2021 19:54
@lenaschoenburg
Copy link
Contributor Author

No worries! I rebased without any conflicts.

@lenaschoenburg lenaschoenburg requested a review from hawkw March 23, 2021 12:57
@lenaschoenburg
Copy link
Contributor Author

Is this PR still relevant? I can rebase again if needed, otherwise feel free to close this.

Copy link
Member

@hawkw hawkw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, this looks good to me --- thanks for the ping!

@hawkw
Copy link
Member

hawkw commented Jun 7, 2021

Ah, it looks like, post-rebase, the build is failing now because new Collect impls were added on master --- for Box<dyn Collect + ...> and Arc<dyn Collect + ...>. The new impls are here:

#[cfg(feature = "alloc")]
impl Collect for alloc::boxed::Box<dyn Collect + Send + Sync + 'static> {
#[inline]
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
self.as_ref().register_callsite(metadata)
}
#[inline]
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
self.as_ref().enabled(metadata)
}
#[inline]
fn max_level_hint(&self) -> Option<LevelFilter> {
self.as_ref().max_level_hint()
}
#[inline]
fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
self.as_ref().new_span(span)
}
#[inline]
fn record(&self, span: &span::Id, values: &span::Record<'_>) {
self.as_ref().record(span, values)
}
#[inline]
fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
self.as_ref().record_follows_from(span, follows)
}
#[inline]
fn event(&self, event: &Event<'_>) {
self.as_ref().event(event)
}
#[inline]
fn enter(&self, span: &span::Id) {
self.as_ref().enter(span)
}
#[inline]
fn exit(&self, span: &span::Id) {
self.as_ref().exit(span)
}
#[inline]
fn clone_span(&self, id: &span::Id) -> span::Id {
self.as_ref().clone_span(id)
}
#[inline]
fn try_close(&self, id: span::Id) -> bool {
self.as_ref().try_close(id)
}
#[inline]
unsafe fn downcast_raw(&self, id: TypeId) -> Option<NonNull<()>> {
if id == TypeId::of::<Self>() {
return Some(NonNull::from(self).cast());
}
self.as_ref().downcast_raw(id)
}
}
#[cfg(feature = "alloc")]
impl Collect for alloc::sync::Arc<dyn Collect + Send + Sync + 'static> {
#[inline]
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
self.as_ref().register_callsite(metadata)
}
#[inline]
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
self.as_ref().enabled(metadata)
}
#[inline]
fn max_level_hint(&self) -> Option<LevelFilter> {
self.as_ref().max_level_hint()
}
#[inline]
fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
self.as_ref().new_span(span)
}
#[inline]
fn record(&self, span: &span::Id, values: &span::Record<'_>) {
self.as_ref().record(span, values)
}
#[inline]
fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
self.as_ref().record_follows_from(span, follows)
}
#[inline]
fn event(&self, event: &Event<'_>) {
self.as_ref().event(event)
}
#[inline]
fn enter(&self, span: &span::Id) {
self.as_ref().enter(span)
}
#[inline]
fn exit(&self, span: &span::Id) {
self.as_ref().exit(span)
}
#[inline]
fn clone_span(&self, id: &span::Id) -> span::Id {
self.as_ref().clone_span(id)
}
#[inline]
fn try_close(&self, id: span::Id) -> bool {
self.as_ref().try_close(id)
}
#[inline]
unsafe fn downcast_raw(&self, id: TypeId) -> Option<NonNull<()>> {
if id == TypeId::of::<Self>() {
return Some(NonNull::from(self).cast());
}
self.as_ref().downcast_raw(id)
}
}

We should add current_span methods to those new Collect impls, and then CI should pass again.

@davidbarsky davidbarsky merged commit 944abac into tokio-rs:master Jun 21, 2021
@davidbarsky
Copy link
Member

Thanks for working on this and sorry for the delay in merging!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants