trace: Add arguments struct to subscriber::Record (#955)

This branch changes the `Subscriber::record` method to take a new
arguments struct, `span::Record`. The `field::Record` trait was renamed
to `field::Visit` to prevent name conflicts.

In addition, the `ValueSet::is_empty`, `ValueSet::contains`, and
`ValueSet::record` methods were made crate-private, as they are exposed
on the `Attributes` and `Record` types. 

Signed-off-by: Eliza Weisman <[email protected]>
This commit is contained in:
Eliza Weisman
2019-03-07 12:41:10 -08:00
committed by GitHub
parent 6fbef0a528
commit d88aba8d1c
12 changed files with 186 additions and 143 deletions
+13 -13
View File
@@ -24,7 +24,7 @@ impl tokio_trace::Subscriber for EnabledSubscriber {
let _ = event;
}
fn record(&self, span: &Id, values: &field::ValueSet) {
fn record(&self, span: &Id, values: &span::Record) {
let _ = (span, values);
}
@@ -47,32 +47,32 @@ impl tokio_trace::Subscriber for EnabledSubscriber {
}
/// Simulates a subscriber that records span data.
struct RecordingSubscriber(Mutex<String>);
struct VisitingSubscriber(Mutex<String>);
struct Recorder<'a>(MutexGuard<'a, String>);
struct Visitor<'a>(MutexGuard<'a, String>);
impl<'a> field::Record for Recorder<'a> {
impl<'a> field::Visit for Visitor<'a> {
fn record_debug(&mut self, _field: &field::Field, value: &fmt::Debug) {
use std::fmt::Write;
let _ = write!(&mut *self.0, "{:?}", value);
}
}
impl tokio_trace::Subscriber for RecordingSubscriber {
impl tokio_trace::Subscriber for VisitingSubscriber {
fn new_span(&self, span: &span::Attributes) -> Id {
let mut recorder = Recorder(self.0.lock().unwrap());
span.values().record(&mut recorder);
let mut visitor = Visitor(self.0.lock().unwrap());
span.record(&mut visitor);
Id::from_u64(0)
}
fn record(&self, _span: &Id, values: &field::ValueSet) {
let mut recorder = Recorder(self.0.lock().unwrap());
values.record(&mut recorder);
fn record(&self, _span: &Id, values: &span::Record) {
let mut visitor = Visitor(self.0.lock().unwrap());
values.record(&mut visitor);
}
fn event(&self, event: &Event) {
let mut recorder = Recorder(self.0.lock().unwrap());
event.record(&mut recorder);
let mut visitor = Visitor(self.0.lock().unwrap());
event.record(&mut visitor);
}
fn record_follows_from(&self, span: &Id, follows: &Id) {
@@ -130,7 +130,7 @@ fn span_with_fields(b: &mut Bencher) {
#[bench]
fn span_with_fields_record(b: &mut Bencher) {
let subscriber = RecordingSubscriber(Mutex::new(String::from("")));
let subscriber = VisitingSubscriber(Mutex::new(String::from("")));
tokio_trace::subscriber::with_default(subscriber, || {
b.iter(|| {
span!(
+7 -7
View File
@@ -2,7 +2,7 @@
extern crate tokio_trace;
use tokio_trace::{
field::{self, Field, Record},
field::{self, Field, Visit},
span,
subscriber::{self, Subscriber},
Event, Id, Metadata,
@@ -29,7 +29,7 @@ struct Count<'a> {
counters: RwLockReadGuard<'a, HashMap<String, AtomicUsize>>,
}
impl<'a> Record for Count<'a> {
impl<'a> Visit for Count<'a> {
fn record_i64(&mut self, field: &Field, value: i64) {
if let Some(counter) = self.counters.get(field.name()) {
if value > 0 {
@@ -52,7 +52,7 @@ impl<'a> Record for Count<'a> {
}
impl CounterSubscriber {
fn recorder(&self) -> Count {
fn visitor(&self) -> Count {
Count {
counters: self.counters.0.read().unwrap(),
}
@@ -78,7 +78,7 @@ impl Subscriber for CounterSubscriber {
}
fn new_span(&self, new_span: &span::Attributes) -> Id {
new_span.values().record(&mut self.recorder());
new_span.record(&mut self.visitor());
let id = self.ids.fetch_add(1, Ordering::SeqCst);
Id::from_u64(id as u64)
}
@@ -87,12 +87,12 @@ impl Subscriber for CounterSubscriber {
// unimplemented
}
fn record(&self, _: &Id, values: &field::ValueSet) {
values.record(&mut self.recorder())
fn record(&self, _: &Id, values: &span::Record) {
values.record(&mut self.visitor())
}
fn event(&self, event: &Event) {
event.record(&mut self.recorder())
event.record(&mut self.visitor())
}
fn enabled(&self, metadata: &Metadata) -> bool {
@@ -15,7 +15,7 @@ extern crate humantime;
use self::ansi_term::{Color, Style};
use super::tokio_trace::{
self,
field::{Field, Record},
field::{Field, Visit},
Id, Level, Subscriber,
};
@@ -103,27 +103,23 @@ impl<'a> fmt::Display for ColorLevel<'a> {
}
impl Span {
fn new(
parent: Option<Id>,
_meta: &tokio_trace::Metadata,
values: &tokio_trace::field::ValueSet,
) -> Self {
fn new(parent: Option<Id>, attrs: &tokio_trace::span::Attributes) -> Self {
let mut span = Self {
parent,
kvs: Vec::new(),
};
values.record(&mut span);
attrs.record(&mut span);
span
}
}
impl Record for Span {
impl Visit for Span {
fn record_debug(&mut self, field: &Field, value: &fmt::Debug) {
self.kvs.push((field.name(), format!("{:?}", value)))
}
}
impl<'a> Record for Event<'a> {
impl<'a> Visit for Event<'a> {
fn record_debug(&mut self, field: &Field, value: &fmt::Debug) {
write!(
&mut self.stderr,
@@ -207,16 +203,14 @@ impl Subscriber for SloggishSubscriber {
}
fn new_span(&self, span: &tokio_trace::span::Attributes) -> tokio_trace::Id {
let meta = span.metadata();
let values = span.values();
let next = self.ids.fetch_add(1, Ordering::SeqCst) as u64;
let id = tokio_trace::Id::from_u64(next);
let span = Span::new(self.current.id(), meta, values);
let span = Span::new(self.current.id(), span);
self.spans.lock().unwrap().insert(id.clone(), span);
id
}
fn record(&self, span: &tokio_trace::Id, values: &tokio_trace::field::ValueSet) {
fn record(&self, span: &tokio_trace::Id, values: &tokio_trace::span::Record) {
let mut spans = self.spans.lock().expect("mutex poisoned!");
if let Some(span) = spans.get_mut(span) {
values.record(span);
@@ -271,12 +265,12 @@ impl Subscriber for SloggishSubscriber {
target = &event.metadata().target(),
)
.unwrap();
let mut recorder = Event {
let mut visitor = Event {
stderr,
comma: false,
};
event.record(&mut recorder);
write!(&mut recorder.stderr, "\n").unwrap();
event.record(&mut visitor);
write!(&mut visitor.stderr, "\n").unwrap();
}
#[inline]
+2 -2
View File
@@ -247,10 +247,10 @@
//! #[macro_use]
//! extern crate tokio_trace;
//! # pub struct FooSubscriber;
//! # use tokio_trace::{span::{Id, Attributes}, Metadata, field::ValueSet};
//! # use tokio_trace::{span::{Id, Attributes, Record}, Metadata};
//! # impl tokio_trace::Subscriber for FooSubscriber {
//! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
//! # fn record(&self, _: &Id, _: &ValueSet) {}
//! # fn record(&self, _: &Id, _: &Record) {}
//! # fn event(&self, _: &tokio_trace::Event) {}
//! # fn record_follows_from(&self, _: &Id, _: &Id) {}
//! # fn enabled(&self, _: &Metadata) -> bool { false }
+4 -4
View File
@@ -135,7 +135,7 @@
//! the data for future use, record it in some manner, or discard it completely.
//!
//! [`Subscriber`]: ::Subscriber
pub use tokio_trace_core::span::{Attributes, Id};
pub use tokio_trace_core::span::{Attributes, Id, Record};
use std::{
borrow::Borrow,
@@ -324,7 +324,7 @@ impl<'a> Span<'a> {
.is_some()
}
/// Records that the field described by `field` has the value `value`.
/// Visits that the field described by `field` has the value `value`.
pub fn record<Q: ?Sized, V>(&mut self, field: &Q, value: &V) -> &mut Self
where
Q: field::AsField,
@@ -343,7 +343,7 @@ impl<'a> Span<'a> {
self
}
/// Record all the fields in the span
/// Visit all the fields in the span
pub fn record_all(&mut self, values: &field::ValueSet) -> &mut Self {
if let Some(ref mut inner) = self.inner {
inner.record(&values);
@@ -479,7 +479,7 @@ impl<'a> Inner<'a> {
fn record(&mut self, values: &field::ValueSet) {
if values.callsite() == self.meta.callsite() {
self.subscriber.record(&self.id, &values)
self.subscriber.record(&self.id, &Record::new(values))
}
}
+7 -7
View File
@@ -1,6 +1,6 @@
use tokio_trace::{
callsite::Callsite,
field::{self, Field, Record, Value},
field::{self, Field, Value, Visit},
};
use std::{collections::HashMap, fmt};
@@ -106,8 +106,8 @@ impl Expect {
}
}
pub fn checker<'a>(&'a mut self, ctx: String) -> CheckRecorder<'a> {
CheckRecorder { expect: self, ctx }
pub fn checker<'a>(&'a mut self, ctx: String) -> CheckVisitor<'a> {
CheckVisitor { expect: self, ctx }
}
pub fn is_empty(&self) -> bool {
@@ -128,12 +128,12 @@ impl fmt::Display for MockValue {
}
}
pub struct CheckRecorder<'a> {
pub struct CheckVisitor<'a> {
expect: &'a mut Expect,
ctx: String,
}
impl<'a> Record for CheckRecorder<'a> {
impl<'a> Visit for CheckVisitor<'a> {
fn record_i64(&mut self, field: &Field, value: i64) {
self.expect
.compare_or_panic(field.name(), &value, &self.ctx[..])
@@ -160,7 +160,7 @@ impl<'a> Record for CheckRecorder<'a> {
}
}
impl<'a> CheckRecorder<'a> {
impl<'a> CheckVisitor<'a> {
pub fn finish(self) {
assert!(
self.expect.fields.is_empty(),
@@ -177,7 +177,7 @@ impl<'a> From<&'a Value> for MockValue {
value: Option<MockValue>,
}
impl Record for MockValueBuilder {
impl Visit for MockValueBuilder {
fn record_i64(&mut self, _: &Field, value: i64) {
self.value = Some(MockValue::I64(value));
}
+8 -10
View File
@@ -13,8 +13,7 @@ use std::{
},
};
use tokio_trace::{
field,
span::{Attributes, Id},
span::{self, Attributes, Id},
Event, Metadata, Subscriber,
};
@@ -25,7 +24,7 @@ enum Expect {
Exit(MockSpan),
CloneSpan(MockSpan),
DropSpan(MockSpan),
Record(MockSpan, mock_field::Expect),
Visit(MockSpan, mock_field::Expect),
NewSpan(NewSpan),
Nothing,
}
@@ -95,7 +94,7 @@ where
where
I: Into<mock_field::Expect>,
{
self.expected.push_back(Expect::Record(span, fields.into()));
self.expected.push_back(Expect::Visit(span, fields.into()));
self
}
@@ -144,21 +143,20 @@ where
(self.filter)(meta)
}
fn record(&self, id: &Id, values: &field::ValueSet) {
fn record(&self, id: &Id, values: &span::Record) {
let spans = self.spans.lock().unwrap();
let mut expected = self.expected.lock().unwrap();
let span = spans
.get(id)
.unwrap_or_else(|| panic!("no span for ID {:?}", id));
println!("record: {}; id={:?}; values={:?};", span.name, id, values);
let was_expected = if let Some(Expect::Record(_, _)) = expected.front() {
let was_expected = if let Some(Expect::Visit(_, _)) = expected.front() {
true
} else {
false
};
if was_expected {
if let Expect::Record(expected_span, mut expected_values) =
expected.pop_front().unwrap()
if let Expect::Visit(expected_span, mut expected_values) = expected.pop_front().unwrap()
{
if let Some(name) = expected_span.name() {
assert_eq!(name, span.name);
@@ -210,7 +208,7 @@ where
.metadata
.check(meta, format_args!("span `{}`", name));
let mut checker = expected.fields.checker(format!("{}", name));
values.record(&mut checker);
span.record(&mut checker);
checker.finish();
match expected.parent {
Some(Parent::ExplicitRoot) => {
@@ -390,7 +388,7 @@ impl Expect {
Expect::Exit(e) => panic!("expected to exit {} but {} instead", e, what,),
Expect::CloneSpan(e) => panic!("expected to clone {} but {} instead", e, what,),
Expect::DropSpan(e) => panic!("expected to drop {} but {} instead", e, what,),
Expect::Record(e, fields) => {
Expect::Visit(e, fields) => {
panic!("expected {} to record {} but {} instead", e, fields, what,)
}
Expect::NewSpan(e) => panic!("expected {} but {} instead", e, what),
@@ -1,6 +1,6 @@
//! Dispatches trace events to `Subscriber`s.
use {
callsite, field, span,
callsite, span,
subscriber::{self, Subscriber},
Event, Metadata,
};
@@ -97,7 +97,7 @@ impl Dispatch {
self.subscriber.register_callsite(metadata)
}
/// Record the construction of a new span, returning a new [ID] for the
/// Visit the construction of a new span, returning a new [ID] for the
/// span being constructed.
///
/// This calls the [`new_span`](::Subscriber::new_span)
@@ -109,12 +109,12 @@ impl Dispatch {
self.subscriber.new_span(span)
}
/// Record a set of values on a span.
/// Visit a set of values on a span.
///
/// This calls the [`record`](::Subscriber::record)
/// function on the `Subscriber` that this `Dispatch` forwards to.
#[inline]
pub fn record(&self, span: &span::Id, values: &field::ValueSet) {
pub fn record(&self, span: &span::Id, values: &span::Record) {
self.subscriber.record(span, &values)
}
@@ -140,7 +140,7 @@ impl Dispatch {
self.subscriber.enabled(metadata)
}
/// Records that an [`Event`] has occurred.
/// Visits that an [`Event`] has occurred.
///
/// This calls the [`event`](::Subscriber::event) function on
/// the `Subscriber` that this `Dispatch` forwards to.
@@ -151,7 +151,7 @@ impl Dispatch {
self.subscriber.event(event)
}
/// Records that a span has been entered.
/// Visits that a span has been entered.
///
/// This calls the [`enter`](::Subscriber::enter) function on the
/// `Subscriber` that this `Dispatch` forwards to.
@@ -160,7 +160,7 @@ impl Dispatch {
self.subscriber.enter(span)
}
/// Records that a span has been exited.
/// Visits that a span has been exited.
///
/// This calls the [`exit`](::Subscriber::exit) function on the `Subscriber`
/// that this `Dispatch` forwards to.
@@ -227,7 +227,7 @@ impl Subscriber for NoSubscriber {
fn event(&self, _event: &Event) {}
fn record(&self, _span: &span::Id, _values: &field::ValueSet) {}
fn record(&self, _span: &span::Id, _values: &span::Record) {}
fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
+4 -4
View File
@@ -33,12 +33,12 @@ impl<'a> Event<'a> {
});
}
/// Records all the fields on this `Event` with the specified [recorder].
/// Visits all the fields on this `Event` with the specified [visitor].
///
/// [recorder]: ::field::Record
/// [visitor]: ::field::Visit
#[inline]
pub fn record(&self, recorder: &mut field::Record) {
self.fields.record(recorder);
pub fn record(&self, visitor: &mut field::Visit) {
self.fields.record(visitor);
}
/// Returns a reference to the set of values on this `Event`.
+57 -57
View File
@@ -21,7 +21,7 @@
//! allow `Subscriber` implementations to provide type-specific behaviour for
//! consuming values of each type.
//!
//! Instances of the `Record` trait are provided by `Subscriber`s to record the
//! Instances of the `Visit` trait are provided by `Subscriber`s to record the
//! values attached to `Span`s and `Event`. This trait represents the behavior
//! used to record values of various types. For example, we might record
//! integers by incrementing counters for their field names, rather than printing
@@ -89,65 +89,65 @@ pub struct Iter {
fields: FieldSet,
}
/// Records typed values.
/// Visits typed values.
///
/// An instance of `Record` ("a recorder") represents the logic necessary to
/// An instance of `Visit` ("a visitor") represents the logic necessary to
/// record field values of various types. When an implementor of [`Value`] is
/// [recorded], it calls the appropriate method on the provided recorder to
/// [recorded], it calls the appropriate method on the provided visitor to
/// indicate the type that value should be recorded as.
///
/// When a [`Subscriber`] implementation [records an `Event`] or a
/// [set of `Value`s added to a `Span`], it can pass an `&mut Record` to the
/// `record` method on the provided [`ValueSet`] or [`Event`]. This recorder
/// [set of `Value`s added to a `Span`], it can pass an `&mut Visit` to the
/// `record` method on the provided [`ValueSet`] or [`Event`]. This visitor
/// will then be used to record all the field-value pairs present on that
/// `Event` or `ValueSet`.
///
/// # Examples
///
/// A simple recorder that writes to a string might be implemented like so:
/// A simple visitor that writes to a string might be implemented like so:
/// ```
/// # extern crate tokio_trace_core as tokio_trace;
/// use std::fmt::{self, Write};
/// use tokio_trace::field::{Value, Record, Field};
/// use tokio_trace::field::{Value, Visit, Field};
/// # fn main() {
/// pub struct StringRecorder<'a> {
/// pub struct StringVisitor<'a> {
/// string: &'a mut String,
/// }
///
/// impl<'a> Record for StringRecorder<'a> {
/// impl<'a> Visit for StringVisitor<'a> {
/// fn record_debug(&mut self, field: &Field, value: &fmt::Debug) {
/// write!(self.string, "{} = {:?}; ", field.name(), value).unwrap();
/// }
/// }
/// # }
/// ```
/// This recorder will format each recorded value using `fmt::Debug`, and
/// This visitor will format each recorded value using `fmt::Debug`, and
/// append the field name and formatted value to the provided string,
/// regardless of the type of the recorded value. When all the values have
/// been recorded, the `StringRecorder` may be dropped, allowing the string
/// been recorded, the `StringVisitor` may be dropped, allowing the string
/// to be printed or stored in some other data structure.
///
/// The `Record` trait provides default implementations for `record_i64`,
/// The `Visit` trait provides default implementations for `record_i64`,
/// `record_u64`, `record_bool`, and `record_str` which simply forward the
/// recorded value to `record_debug`. Thus, `record_debug` is the only method
/// which a `Record` implementation *must* implement. However, recorders may
/// which a `Visit` implementation *must* implement. However, visitors may
/// override the default implementations of these functions in order to
/// implement type-specific behavior.
///
/// Additionally, when a recorder recieves a value of a type it does not care
/// Additionally, when a visitor recieves a value of a type it does not care
/// about, it is free to ignore those values completely. For example, a
/// recorder which only records numeric data might look like this:
/// visitor which only records numeric data might look like this:
///
/// ```
/// # extern crate tokio_trace_core as tokio_trace;
/// # use std::fmt::{self, Write};
/// # use tokio_trace::field::{Value, Record, Field};
/// # use tokio_trace::field::{Value, Visit, Field};
/// # fn main() {
/// pub struct SumRecorder {
/// pub struct SumVisitor {
/// sum: i64,
/// }
///
/// impl Record for SumRecorder {
/// impl Visit for SumVisitor {
/// fn record_i64(&mut self, _field: &Field, value: i64) {
/// self.sum += value;
/// }
@@ -163,7 +163,7 @@ pub struct Iter {
/// # }
/// ```
///
/// This recorder (which is probably not particularly useful) keeps a running
/// This visitor (which is probably not particularly useful) keeps a running
/// sum of all the numeric values it records, and ignores all other values. A
/// more practical example of recording typed values is presented in
/// `examples/counters.rs`, which demonstrates a very simple metrics system
@@ -176,41 +176,41 @@ pub struct Iter {
/// [set of `Value`s added to a `Span`]: ::subscriber::Subscriber::record
/// [`Event`]: ::event::Event
/// [`ValueSet`]: ::field::ValueSet
pub trait Record {
/// Record a signed 64-bit integer value.
pub trait Visit {
/// Visit a signed 64-bit integer value.
fn record_i64(&mut self, field: &Field, value: i64) {
self.record_debug(field, &value)
}
/// Record an umsigned 64-bit integer value.
/// Visit an umsigned 64-bit integer value.
fn record_u64(&mut self, field: &Field, value: u64) {
self.record_debug(field, &value)
}
/// Record a boolean value.
/// Visit a boolean value.
fn record_bool(&mut self, field: &Field, value: bool) {
self.record_debug(field, &value)
}
/// Record a string value.
/// Visit a string value.
fn record_str(&mut self, field: &Field, value: &str) {
self.record_debug(field, &value)
}
/// Record a value implementing `fmt::Debug`.
/// Visit a value implementing `fmt::Debug`.
fn record_debug(&mut self, field: &Field, value: &fmt::Debug);
}
/// A field value of an erased type.
///
/// Implementors of `Value` may call the appropriate typed recording methods on
/// the [recorder] passed to their `record` method in order to indicate how
/// the [visitor] passed to their `record` method in order to indicate how
/// their data should be recorded.
///
/// [recorder]: ::field::Record
/// [visitor]: ::field::Visit
pub trait Value: ::sealed::Sealed {
/// Records this value with the given `Recorder`.
fn record(&self, key: &Field, recorder: &mut Record);
/// Visits this value with the given `Visitor`.
fn record(&self, key: &Field, visitor: &mut Visit);
}
/// A `Value` which serializes as a string using `fmt::Display`.
@@ -248,21 +248,21 @@ where
DebugValue(t)
}
// ===== impl Record =====
// ===== impl Visit =====
impl<'a, 'b> Record for fmt::DebugStruct<'a, 'b> {
impl<'a, 'b> Visit for fmt::DebugStruct<'a, 'b> {
fn record_debug(&mut self, field: &Field, value: &fmt::Debug) {
self.field(field.name(), value);
}
}
impl<'a, 'b> Record for fmt::DebugMap<'a, 'b> {
impl<'a, 'b> Visit for fmt::DebugMap<'a, 'b> {
fn record_debug(&mut self, field: &Field, value: &fmt::Debug) {
self.entry(&format_args!("{}", field), value);
}
}
impl<F> Record for F
impl<F> Visit for F
where
F: FnMut(&Field, &fmt::Debug),
{
@@ -288,9 +288,9 @@ macro_rules! impl_value {
fn record(
&self,
key: &$crate::field::Field,
recorder: &mut $crate::field::Record,
visitor: &mut $crate::field::Visit,
) {
recorder.$record(key, *self)
visitor.$record(key, *self)
}
}
)+
@@ -302,9 +302,9 @@ macro_rules! impl_value {
fn record(
&self,
key: &$crate::field::Field,
recorder: &mut $crate::field::Record,
visitor: &mut $crate::field::Visit,
) {
recorder.$record(key, *self as $as_ty)
visitor.$record(key, *self as $as_ty)
}
}
)+
@@ -324,8 +324,8 @@ impl_values! {
impl ::sealed::Sealed for str {}
impl Value for str {
fn record(&self, key: &Field, recorder: &mut Record) {
recorder.record_str(key, &self)
fn record(&self, key: &Field, visitor: &mut Visit) {
visitor.record_str(key, &self)
}
}
@@ -335,16 +335,16 @@ impl<'a, T: ?Sized> Value for &'a T
where
T: Value + 'a,
{
fn record(&self, key: &Field, recorder: &mut Record) {
(*self).record(key, recorder)
fn record(&self, key: &Field, visitor: &mut Visit) {
(*self).record(key, visitor)
}
}
impl<'a> ::sealed::Sealed for fmt::Arguments<'a> {}
impl<'a> Value for fmt::Arguments<'a> {
fn record(&self, key: &Field, recorder: &mut Record) {
recorder.record_debug(key, self)
fn record(&self, key: &Field, visitor: &mut Visit) {
visitor.record_debug(key, self)
}
}
@@ -356,8 +356,8 @@ impl<T> Value for DisplayValue<T>
where
T: fmt::Display,
{
fn record(&self, key: &Field, recorder: &mut Record) {
recorder.record_debug(key, &format_args!("{}", self.0))
fn record(&self, key: &Field, visitor: &mut Visit) {
visitor.record_debug(key, &format_args!("{}", self.0))
}
}
@@ -369,8 +369,8 @@ impl<T: fmt::Debug> Value for DebugValue<T>
where
T: fmt::Debug,
{
fn record(&self, key: &Field, recorder: &mut Record) {
recorder.record_debug(key, &self.0)
fn record(&self, key: &Field, visitor: &mut Visit) {
visitor.record_debug(key, &self.0)
}
}
@@ -544,23 +544,23 @@ impl<'a> ValueSet<'a> {
self.fields.callsite()
}
/// Records all the fields in this `ValueSet` with the provided [recorder].
/// Visits all the fields in this `ValueSet` with the provided [visitor].
///
/// [recorder]: ::field::Record
pub fn record(&self, recorder: &mut Record) {
/// [visitor]: ::field::Visit
pub(crate) fn record(&self, visitor: &mut Visit) {
let my_callsite = self.callsite();
for (field, value) in self.values {
if field.callsite() != my_callsite {
continue;
}
if let Some(value) = value {
value.record(field, recorder);
value.record(field, visitor);
}
}
}
/// Returns `true` if this `ValueSet` contains a value for the given `Field`.
pub fn contains(&self, field: &Field) -> bool {
pub(crate) fn contains(&self, field: &Field) -> bool {
field.callsite() == self.callsite()
&& self
.values
@@ -569,7 +569,7 @@ impl<'a> ValueSet<'a> {
}
/// Returns true if this `ValueSet` contains _no_ values.
pub fn is_empty(&self) -> bool {
pub(crate) fn is_empty(&self) -> bool {
let my_callsite = self.callsite();
self.values
.iter()
@@ -711,14 +711,14 @@ mod test {
(&fields.field("baz").unwrap(), None),
];
struct MyRecorder;
impl Record for MyRecorder {
struct MyVisitor;
impl Visit for MyVisitor {
fn record_debug(&mut self, field: &Field, _: &::std::fmt::Debug) {
assert_eq!(field.callsite(), TEST_META_1.callsite())
}
}
let valueset = fields.value_set(values);
valueset.record(&mut MyRecorder);
valueset.record(&mut MyVisitor);
}
#[test]
+51
View File
@@ -20,6 +20,12 @@ pub struct Attributes<'a> {
parent: Parent,
}
/// A set of fields recorded by a span.
#[derive(Debug)]
pub struct Record<'a> {
values: &'a field::ValueSet<'a>,
}
#[derive(Debug)]
enum Parent {
/// The new span will be a root span.
@@ -124,4 +130,49 @@ impl<'a> Attributes<'a> {
_ => None,
}
}
/// Records all the fields in this set of `Attributes` with the provided
/// [Visitor].
///
/// [visitor]: ::field::Visit
pub fn record(&self, visitor: &mut field::Visit) {
self.values.record(visitor)
}
/// Returns `true` if this set of `Attributes` contains a value for the
/// given `Field`.
pub fn contains(&self, field: &field::Field) -> bool {
self.values.contains(field)
}
/// Returns true if this set of `Attributes` contains _no_ values.
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
}
// ===== impl Record =====
impl<'a> Record<'a> {
/// Constructs a new `Record` from a `ValueSet`.
pub fn new(values: &'a field::ValueSet<'a>) -> Self {
Self { values }
}
/// Records all the fields in this `Record` with the provided [Visitor].
///
/// [visitor]: ::field::Visit
pub fn record(&self, visitor: &mut field::Visit) {
self.values.record(visitor)
}
/// Returns `true` if this `Record` contains a value for the given `Field`.
pub fn contains(&self, field: &field::Field) -> bool {
self.values.contains(field)
}
/// Returns true if this `Record` contains _no_ values.
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
}
+15 -15
View File
@@ -1,5 +1,5 @@
//! Subscribers collect and record trace data.
use {field, span, Event, Metadata};
use {span, Event, Metadata};
/// Trait representing the functions required to collect trace data.
///
@@ -14,7 +14,7 @@ use {field, span, Event, Metadata};
/// - Registering new spans as they are created, and providing them with span
/// IDs. Implicitly, this means the subscriber may determine the strategy for
/// determining span equality.
/// - Recording the attachment of field values and follows-from annotations to
/// - Visiting the attachment of field values and follows-from annotations to
/// spans.
/// - Filtering spans and events, and determining when those filters must be
/// invalidated.
@@ -106,11 +106,11 @@ pub trait Subscriber: 'static {
/// [metadata]: ::Metadata
fn enabled(&self, metadata: &Metadata) -> bool;
/// Record the construction of a new span, returning a new [span ID] for the
/// Visit the construction of a new span, returning a new [span ID] for the
/// span being constructed.
///
/// The provided `ValueSet` contains any field values that were provided
/// when the span was created. The subscriber may pass a [recorder] to the
/// when the span was created. The subscriber may pass a [visitor] to the
/// `ValueSet`'s [`record` method] to record these values.
///
/// IDs are used to uniquely identify spans and events within the context of a
@@ -123,20 +123,20 @@ pub trait Subscriber: 'static {
/// the metadata.
///
/// [span ID]: ../span/struct.Id.html
/// [recorder]: ::field::Record
/// [visitor]: ::field::Visit
/// [`record` method]: ::field::ValueSet::record
fn new_span(&self, span: &span::Attributes) -> span::Id;
// === Notification methods ===============================================
/// Record a set of values on a span.
/// Visit a set of values on a span.
///
/// The subscriber is expected to provide a [recorder] to the `ValueSet`'s
/// The subscriber is expected to provide a [visitor] to the `Record`'s
/// [`record` method] in order to record the added values.
///
/// [recorder]: ::field::Record
/// [`record` method]: ::field::ValueSet::record
fn record(&self, span: &span::Id, values: &field::ValueSet);
/// [visitor]: ::field::Visit
/// [`record` method]: ::span::Record::record
fn record(&self, span: &span::Id, values: &span::Record);
/// Adds an indication that `span` follows from the span with the id
/// `follows`.
@@ -158,18 +158,18 @@ pub trait Subscriber: 'static {
/// follow from _b_), it may silently do nothing.
fn record_follows_from(&self, span: &span::Id, follows: &span::Id);
/// Records that an [`Event`] has occurred.
/// Visits that an [`Event`] has occurred.
///
/// The provided `Event` struct contains any field values attached to the
/// event. The subscriber may pass a [recorder] to the `Event`'s
/// event. The subscriber may pass a [visitor] to the `Event`'s
/// [`record` method] to record these values.
///
/// [`Event`]: ::event::Event
/// [recorder]: ::field::Record
/// [visitor]: ::field::Visit
/// [`record` method]: ::event::Event::record
fn event(&self, event: &Event);
/// Records that a spanhas been entered.
/// Visits that a spanhas been entered.
///
/// When entering a span, this method is called to notify the subscriber
/// that the span has been entered. The subscriber is provided with the
@@ -179,7 +179,7 @@ pub trait Subscriber: 'static {
/// [span ID]: ../span/struct.Id.html
fn enter(&self, span: &span::Id);
/// Records that a span has been exited.
/// Visits that a span has been exited.
///
/// When entering a span, this method is called to notify the subscriber
/// that the span has been exited. The subscriber is provided with the