mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-21 00:00:10 +02:00
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:
@@ -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!(
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user