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

Multiple ownership of tracing_subscriber::Registry not possible #1356

Closed
jacobmarble opened this issue Apr 15, 2021 · 2 comments
Closed

Multiple ownership of tracing_subscriber::Registry not possible #1356

jacobmarble opened this issue Apr 15, 2021 · 2 comments

Comments

@jacobmarble
Copy link

Bug Report

Happy to learn that I'm doing it wrong. :)

Version

tracing 0.1.24
tracing-subscriber 0.2.17

Platform

Darwin Orient.local 20.3.0 Darwin Kernel Version 20.3.0: Thu Jan 21 00:07:06 PST 2021; root:xnu-7195.81.3~1/RELEASE_X86_64 x86_64

Crates

tracing-subscriber

Description

I need tracing to send some events to stdout logs, and some events to Jaeger. These two sets of events may intersect, or may be disjoint.

My solution is to write a ForkingLayer, which wraps (1) a stdout/logs layer and (2) an OpenTelemetry/Jaeger layer. These two layers need to share a Registry (or some other Subscriber + LookupSpan).

I tried multiple ownership like this:

    let subscriber = Rc::new(tracing_subscriber::Registry::default());
    let log_layer = log_layer.with_subscriber(Rc::clone(&subscriber));
    let traces_layer = traces_layer.with_subscriber(Rc::clone(&subscriber));

I expect the trait implementations of Registry to be exposed by Rc<Registry>.

However the traits of Registry are not available. Furthermore, the orphan rule prevents me from writing wrapper implementations for Subscriber and LookupSpan:

error[E0277]: the trait bound `Rc<observability_deps::tracing_subscriber::Registry>: observability_deps::tracing::Subscriber` is not satisfied
  --> src/commands/tracing.rs:63:47
   |
63 |     let log_layer = log_layer.with_subscriber(Rc::clone(&subscriber));
   |                                               ^^^^^^^^^^^^^^^^^^^^^^ the trait `observability_deps::tracing::Subscriber` is not implemented for `Rc<observability_deps::tracing_subscriber::Registry>`

error[E0277]: the trait bound `for<'a> Rc<observability_deps::tracing_subscriber::Registry>: LookupSpan<'a>` is not satisfied
  --> src/commands/tracing.rs:63:47
   |
63 |     let log_layer = log_layer.with_subscriber(Rc::clone(&subscriber));
   |                                               ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> LookupSpan<'a>` is not implemented for `Rc<observability_deps::tracing_subscriber::Registry>`
   |
   = note: required because of the requirements on the impl of `__tracing_subscriber_Layer<Rc<observability_deps::tracing_subscriber::Registry>>` for `observability_deps::tracing_subscriber::fmt::Layer<Rc<observability_deps::tracing_subscriber::Registry>, JsonFields, observability_deps::tracing_subscriber::fmt::format::Format<Json>>`
   = note: required because of the requirements on the impl of `__tracing_subscriber_Layer<Rc<observability_deps::tracing_subscriber::Registry>>` for `std::option::Option<observability_deps::tracing_subscriber::fmt::Layer<Rc<observability_deps::tracing_subscriber::Registry>, JsonFields, observability_deps::tracing_subscriber::fmt::format::Format<Json>>>`
   = note: required because of the requirements on the impl of `__tracing_subscriber_Layer<Rc<observability_deps::tracing_subscriber::Registry>>` for `Layered<std::option::Option<observability_deps::tracing_subscriber::fmt::Layer<Rc<observability_deps::tracing_subscriber::Registry>, JsonFields, observability_deps::tracing_subscriber::fmt::format::Format<Json>>>, Layered<std::option::Option<observability_deps::tracing_subscriber::fmt::Layer<Rc<observability_deps::tracing_subscriber::Registry>, observability_deps::tracing_subscriber::fmt::format::Pretty, observability_deps::tracing_subscriber::fmt::format::Format<observability_deps::tracing_subscriber::fmt::format::Pretty>>>, Layered<std::option::Option<observability_deps::tracing_subscriber::fmt::Layer<Rc<observability_deps::tracing_subscriber::Registry>>>, observability_deps::tracing_subscriber::EnvFilter, Rc<observability_deps::tracing_subscriber::Registry>>, Rc<observability_deps::tracing_subscriber::Registry>>, Rc<observability_deps::tracing_subscriber::Registry>>`
@jacobmarble
Copy link
Author

Closing as duplicate of #1348

@hawkw
Copy link
Member

hawkw commented Apr 19, 2021

As a workaround, you could write a newtype around Arc<Registry>, and implement the appropriate traits for that. For example,

#[derive(Clone, Debug)]
pub struct SharedRegistry(Arc<Registry>);

impl<'a> LookupSpan<'a> for SharedRegistry {
    // ... forward implementation to the inner `Registry`'s methods...
}

impl Subscriber for SharedRegistry {
    // ... forward implementation to the inner `Registry`'s methods...
}

Note that you will need to use Arc rather than Rc, because Subscriber requires Send + Sync, as it may be shared across threads. Also, it's important to ensure your implementation forwards all of the Subscriber trait methods, even the ones with default implementations.

We could also add an implementation of Subscriber for Arc<T> where T: Subscriber in tracing-core, to make this easier in the future.

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

No branches or pull requests

2 participants