-
Notifications
You must be signed in to change notification settings - Fork 741
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
Tracking issue for composing multiple subscribers #135
Comments
@hawkw this sounds really good. I think the layer approach will work well for decorating subscribers. I'm curious to see how composing filters might work. I think the most valuable thing we can provide right now is the data structure for tracking state. This is something ive rewritten three times. So I think by far the first step here is to produce that. Then continue to learn how wrapper subs work. |
#136 is a draft proposal for a layer trait for subscriber composition. |
currently in progress:
|
* add `Layer` trait for composing subscribers ### Motivation In many cases, it is valuable to compose multiple consumers for trace events. However, certain aspects of `tracing`'s design --- in particular, that span IDs are assigned by the subscriber, and that a single subscriber collects events from multiple threads --- make it difficult to compose the `Subscriber` trait directly. ## Solution This branch introduces a new trait, `Layer`, in `tracing-subscriber`. `Layer` represents the composable subset of the `Subscriber` functionality --- it recieves notifications of spans and events, and can filter callsites, but it does not assign IDs or manage reference counts, instead being notified on span closure by the underlying subscriber. A `Layer` can thus be wrapped around another subscriber to add additional functionality. In addition, this branch adds functionality for composing layers, and a `filter` module that provides `Layer` implementations for simple filters. ## Future Work To have a complete story for multi-subscriber fanout, we will also want to implement a performant concurrent span store, as I described in #157. To better support the use of subscriber layers, may wish to consider having a "registry" subscriber that implements _only_ span storage, ID generation, and lifecycle management, for composing layers on top of. Finally, we should consider adding `Layer` implementations to other crates that currently only expose `Subscriber` impls. Refs: #135 Signed-off-by: Eliza Weisman <[email protected]> * subscriber: remove ref-counting from Layer (#149) ## Motivation As I mentioned in #136 (comment), the `Layer` trait proposed in #136 should probably _not_ be responsible for managing ref-counts and determining span closures. Instead, the root subscriber should be responsible for this, and `Layer`s should be able to opt into a callback that's notified _when_ a span is closed. ## Solution Adding a callback that's called on closure to `Layer` required modifying the `Subscriber` trait to allow indicating when a span closes. This branch attempts to do this without a breaking change, by adding a new `try_close` trait method to `Subscriber`. `try_close` is identical to `drop_span` except that it returns a boolean value, set to `true` if the span has closed. This function was added in #153. This branch updates `tracing-subscriber::Layer` to use `try_close`. Rather than having `clone_span`/`drop_span` callbacks on `Layer`, we now have a `close` function, which is called when the inner subscriber's `try_close` returns `true`. Signed-off-by: Eliza Weisman <[email protected]> * ensure a Context always refers to a Subscriber This reworks layer composition a bit, and fixes an issue where `Context`s were not actually guaranteed to wrap a `Subscriber`, and thus implemented no methods. Layers now guarantee that `S` implements `Subscriber`. Signed-off-by: Eliza Weisman <[email protected]>
…Registry + Layers (#420) This branch introduces: - A registry build atop of https://github.com/hawkw/sharded-slab. Layers are expected to consume this registry through the traits `SpanData`, `LookupSpan`, and `LookupMetadata`. Layer-specific data, such as formatted spans and events, are stored in the `Extensions` typemap. Data is writable via the `ExtensionsMut` view struct of the typemap. This enables layers to read and write data that they are specifically interested in. - The `tracing_subscriber::fmt::Subscriber` has been re-implemented in terms of `tracing_subscriber::registry::Registry` and `tracing_subscriber::fmt::Layer`. - The event/field formatters have been modified (in a non-backwards compatible way) to accept a `tracing_subscriber::fmt::FmtContext`. A similar structure existed in `tracing_subscriber::fmt::Subscriber`, but it was not publicly exposed. Resolves #135 Resolves #157 Resolves #391 Signed-off-by: David Barsky <[email protected]> Coauthored-by: Eliza Weisman <[email protected]>
Feature Request
Crates
tracing-subscriber
Motivation
In many cases, it is valuable to compose multiple consumers for trace events. However, certain aspects of
tracing
's design --- in particular, that span IDs are assigned by the subscriber, and that a single subscriber collects events from multiple threads --- make it difficult to compose theSubscriber
trait directly.Proposal
I think it should be possible to implement subscriber composition in the
tracing-subscriber
crate without making changes totracing-core
. Here's how I think we should do this:Layer
/Middleware
-like approach for composing multiple consumers (which don't get to assign span IDs) around a single core subscriber that does assign IDs. I have a work in progress implementation of this, and will open a draft PR for discussion.Layer
interface.Mutex<HashMap<Id, MyPerSpanData>>
and similar bad ideas.Alternatives
There are other potential ways to implement subscriber fan-out.
In the past, I've considered an approach where there is a central registry that manages per-span data and provides it to multiple consumers. I think this introduces a lot of complexity and is hard to come up with a design that satisfies the needs of various subscribers --- this is a big part of why tools for subscriber composition haven't landed sooner.
@davidbarsky proposed modifying the
Dispatch
type intracing-core
to take a slice of subscribers and iterate over them. I don't think this is the right approach for the following reasons:tracing-core
, which I really don't think is necessary to implement this. IMO, if we can do it in a crate on top of-core
, we should.Subscriber
trait, we would need a method for determining whose ID is the authoritative one. This could lead to very surprising behaviour when implementations expect their IDs to be used.Finally, we could do nothing. Many implementations are already writing ad-hoc versions of the layered/stacked subscriber I described above (@LucioFranco's experiments w/ this was part of the inspiration behind the design I proposed). However there are several pitfalls/gotchas that ad-hoc implementations need to avoid, while if we provide a principled implementation in a library, it is only necessary to solve these problems once.
The text was updated successfully, but these errors were encountered: