Skip to content

Commit

Permalink
subscriber: Add context type to Layer
Browse files Browse the repository at this point in the history
Signed-off-by: Eliza Weisman <[email protected]>
  • Loading branch information
hawkw committed Jul 9, 2019
1 parent 5278c80 commit 7bd71e5
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 55 deletions.
106 changes: 71 additions & 35 deletions tracing-subscriber/src/filter.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,57 @@

use crate::layer::Layer;
use tracing_core::{subscriber::Interest, Metadata};
use crate::layer::{Ctx, Layer};
use tracing_core::{subscriber::{Subscriber, Interest}, Metadata};
use std::marker::PhantomData;

pub trait Filter: 'static {
pub trait Filter<S>
where
Self: 'static,
S: Subscriber,
{
fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest {
if self.enabled(metadata) {
if self.enabled(metadata, &Ctx::none()) {
Interest::always()
} else {
Interest::never()
}
}

fn enabled(&self, metadata: &Metadata) -> bool;
fn enabled(&self, metadata: &Metadata, ctx: &Ctx<S>) -> bool;
}

pub trait FilterExt: Filter {
pub trait FilterExt<S>
where
Self: Filter<S>,
S: Subscriber,
{
fn or<B>(self, b: B) -> Or<Self, B>
where
Self: Sized,
B: Filter<S>,
{
Or { a: self, b }
}

fn and<B>(self, b: B) -> And<Self, B>
where
Self: Sized,
B: Filter<S>,
{
And { a: self, b }
}
}

#[derive(Clone, Debug)]
pub struct EnabledFn<F>(F);
pub struct EnabledFn<F, S> {
f: F,
_s: PhantomData<fn(S)>,
}

#[derive(Clone, Debug)]
pub struct InterestFn<F>(F);
pub struct InterestFn<F, S> {
f: F,
_s: PhantomData<fn(S)>,
}

#[derive(Clone, Debug)]
pub struct Or<A, B> {
Expand All @@ -48,14 +65,14 @@ pub struct And<A, B> {
b: B,
}

pub fn enabled_fn<F>(f: F) -> EnabledFn<F>
pub fn enabled_fn<F, S>(f: F) -> EnabledFn<F, S>
where
F: Fn(&Metadata) -> bool + 'static,
{
EnabledFn::from(f)
}

pub fn callsite_fn<F>(f: F) -> InterestFn<F>
pub fn callsite_fn<F, S>(f: F) -> InterestFn<F, S>
where
F: Fn(&Metadata) -> Interest + 'static,
{
Expand All @@ -64,7 +81,11 @@ where

// === impl Layer ===

impl<F: Filter, S> Layer<S> for F {
impl<F, S> Layer<S> for F
where
F: Filter<S>,
S: Subscriber,
{
fn register_callsite(&self, metadata: &'static Metadata<'static>, prev: Interest) -> Interest {
let my_interest = self.callsite_enabled(metadata);
if my_interest.is_always() {
Expand All @@ -74,68 +95,82 @@ impl<F: Filter, S> Layer<S> for F {
}
}

fn enabled(&self, metadata: &Metadata, prev: bool) -> bool {
Filter::enabled(self, metadata) && prev
fn enabled(&self, metadata: &Metadata, prev: bool, ctx: Ctx<S>) -> bool {
Filter::enabled(self, metadata, &ctx) && prev
}
}

// === impl EnabledFn ===

impl<F> Filter for EnabledFn<F>
impl<F, S> Filter<S> for EnabledFn<F, S>
where
F: Fn(&Metadata) -> bool + 'static,
S: Subscriber,
{
fn enabled(&self, metadata: &Metadata) -> bool {
(self.0)(metadata)
fn enabled(&self, metadata: &Metadata, _: &Ctx<S>) -> bool {
(self.f)(metadata)
}
}

impl<F> From<F> for EnabledFn<F>
impl<F, S> From<F> for EnabledFn<F, S>
where
F: Fn(&Metadata) -> bool + 'static,
{
fn from(f: F) -> Self {
Self(f)
Self {
f,
_s: PhantomData,
}
}
}

// === impl InterestFn ===

impl<F> Filter for InterestFn<F>
impl<F, S> Filter<S> for InterestFn<F, S>
where
F: Fn(&Metadata) -> Interest + 'static,
S: Subscriber,
{
fn enabled(&self, metadata: &Metadata) -> bool {
let my_interest = (self.0)(metadata);
fn enabled(&self, metadata: &Metadata, _: &Ctx<S>) -> bool {
let my_interest = (self.f)(metadata);
my_interest.is_always() || my_interest.is_sometimes()
}

fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest {
(self.0)(metadata)
(self.f)(metadata)
}
}

impl<F> From<F> for InterestFn<F>
impl<F, S> From<F> for InterestFn<F, S>
where
F: Fn(&'static Metadata<'static>) -> Interest + 'static,
{
fn from(f: F) -> Self {
Self(f)
Self {
f,
_s: PhantomData,
}
}
}

// === impl FilterExt ===
impl<F: Filter> FilterExt for F {}

impl<F, S> FilterExt<S> for F
where
F: Filter<S>,
S: Subscriber,
{}

// === impl And ===

impl<A, B> Filter for And<A, B>
impl<A, B, S> Filter<S> for And<A, B>
where
A: Filter,
B: Filter,
A: Filter<S>,
B: Filter<S>,
S: Subscriber,
{
fn enabled(&self, metadata: &Metadata) -> bool {
self.a.enabled(metadata) && self.b.enabled(metadata)
fn enabled(&self, metadata: &Metadata, ctx: &Ctx<S>) -> bool {
self.a.enabled(metadata, ctx) && self.b.enabled(metadata, ctx)
}

fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest {
Expand All @@ -152,13 +187,14 @@ where

// === impl Or ===

impl<A, B> Filter for Or<A, B>
impl<A, B, S> Filter<S> for Or<A, B>
where
A: Filter,
B: Filter,
A: Filter<S>,
B: Filter<S>,
S: Subscriber,
{
fn enabled(&self, metadata: &Metadata) -> bool {
self.a.enabled(metadata) || self.b.enabled(metadata)
fn enabled(&self, metadata: &Metadata, ctx: &Ctx<S>) -> bool {
self.a.enabled(metadata, ctx) || self.b.enabled(metadata, ctx)
}

fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest {
Expand Down
81 changes: 61 additions & 20 deletions tracing-subscriber/src/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use tracing_core::{
Event,
};

use crate::filter;
use std::any::TypeId;

pub trait Layer<S>: 'static {
Expand All @@ -17,17 +16,28 @@ pub trait Layer<S>: 'static {
fn register_callsite(&self, _metadata: &'static Metadata<'static>, prev: Interest) -> Interest {
prev
}
fn enabled(&self, _metadata: &Metadata, prev: bool) -> bool {

fn enabled(&self, _metadata: &Metadata, prev: bool, _ctx: Ctx<S>) -> bool {
prev
}
fn new_span(&self, _attrs: &span::Attributes, _id: &span::Id) {}
fn record(&self, _span: &span::Id, _values: &span::Record) {}
fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
fn event(&self, _event: &Event) {}
fn enter(&self, _id: &span::Id) {}
fn exit(&self, _id: &span::Id) {}
fn clone_span(&self, _id: &span::Id, _new: Option<&span::Id>) {}
fn drop_span(&self, _id: &span::Id) {}

fn new_span(&self, _attrs: &span::Attributes, _id: &span::Id, _ctx: Ctx<S>) {}

// Note: it's unclear to me why we'd need the current span in `record` (the
// only thing the `Ctx` type currently provides), but passing it in anyway
// seems like a good future-proofing measure as it may grow other methods later...
fn record(&self, _span: &span::Id, _values: &span::Record, _ctx: Ctx<S>) {}
// Note: it's unclear to me why we'd need the current span in `record` (the
// only thing the `Ctx` type currently provides), but passing it in anyway
// seems like a good future-proofing measure as it may grow other methods later...
fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id, _ctx: Ctx<S>) {}

fn event(&self, _event: &Event, _ctx: Ctx<S>) {}
fn enter(&self, _id: &span::Id, _ctx: Ctx<S>) {}
fn exit(&self, _id: &span::Id, _ctx: Ctx<S>) {}

fn clone_span(&self, _id: &span::Id, _new: Option<&span::Id>, _ctx: Ctx<S>) {}
fn drop_span(&self, _id: &span::Id, _ctx: Ctx<S>) {}

/// Composes the given [`Subscriber`] with this `Layer`, returning a `Layered` subscriber.
///
Expand Down Expand Up @@ -107,6 +117,13 @@ pub trait SubscriberExt: Subscriber + crate::sealed::Sealed {
// }
}

/// Represents information about the current context provided to `Layer`s by the
/// wrapped `Subscriber`.
#[derive(Debug)]
pub struct Ctx<'a, S> {
subscriber: Option<&'a S>,
}

#[derive(Clone, Debug)]
pub struct Layered<L, S> {
layer: L,
Expand Down Expand Up @@ -177,6 +194,12 @@ impl<A, B> Layered<A, B> {
inner,
}
}

fn ctx(&self) -> Ctx<B> {
Ctx {
subscriber: Some(&self.inner),
}
}
}

impl<L, S> Subscriber for Layered<L, S>
Expand All @@ -191,52 +214,52 @@ where

fn enabled(&self, metadata: &Metadata) -> bool {
let enabled = self.inner.enabled(metadata);
self.layer.enabled(metadata, enabled)
self.layer.enabled(metadata, enabled, self.ctx())
}

fn new_span(&self, span: &span::Attributes) -> span::Id {
let id = self.inner.new_span(span);
self.layer.new_span(span, &id);
self.layer.new_span(span, &id, self.ctx());
id
}

fn record(&self, span: &span::Id, values: &span::Record) {
self.inner.record(span, values);
self.layer.record(span, values);
self.layer.record(span, values, self.ctx());
}

fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
self.inner.record_follows_from(span, follows);
self.layer.record_follows_from(span, follows);
self.layer.record_follows_from(span, follows, self.ctx());
}

fn event(&self, event: &Event) {
self.inner.event(event);
self.layer.event(event);
self.layer.event(event, self.ctx());
}

fn enter(&self, span: &span::Id) {
self.inner.enter(span);
self.layer.enter(span);
self.layer.enter(span, self.ctx());
}

fn exit(&self, span: &span::Id) {
self.inner.exit(span);
self.layer.exit(span);
self.layer.exit(span, self.ctx());
}

fn clone_span(&self, old: &span::Id) -> span::Id {
let new = self.inner.clone_span(old);
if &new != old {
self.layer.clone_span(old, Some(&new));
self.layer.clone_span(old, Some(&new), self.ctx());
} else {
self.layer.clone_span(old, None);
self.layer.clone_span(old, None, self.ctx());
};
new
}

fn drop_span(&self, id: span::Id) {
self.layer.drop_span(&id);
self.layer.drop_span(&id, self.ctx());
self.inner.drop_span(id);
}

Expand All @@ -253,3 +276,21 @@ where

impl<S: Subscriber> crate::sealed::Sealed for S {}
impl<S: Subscriber> SubscriberExt for S {}

// === impl Ctx ===

impl<'a, S: Subscriber> Ctx<'a, S> {
/// Returns the wrapped subscriber's view of the current span.
#[inline]
pub fn current_span(&self) -> span::Current {
self.subscriber
.map(Subscriber::current_span)
// TODO: this would be more correct as "unknown", so perhaps
// `tracing-core` should make `Current::unknown()` public?
.unwrap_or_else(span::Current::none)
}

pub(crate) fn none() -> Self {
Self { subscriber: None }
}
}

0 comments on commit 7bd71e5

Please sign in to comment.