From af46eac5837af4871144923b1e75f38c41e8896d Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 28 Jun 2019 13:13:46 -0700 Subject: [PATCH] chore: remove `tokio-trace`, add "Related Projects" to README (#1221) ## Motivation The `tokio-trace` and `tokio-trace-core` crates have been renamed to `tracing` and `tracing-core`, and moved to their own repository (`tokio-rs/tracing`). ## Solution This branch removes `tokio-trace` and `tokio-trace-core` from the `tokio` repository. In addition, I've added a "Related Projects" section to the root README, which lists `tracing` (as well as `mio`, and `bytes`) as other libraries maintained by the Tokio project. I thought that this would help folks looking for `tokio-trace` here find it in its new home. In addition, it changes `tokio` to depend on `tracing-core` rather than `tokio-trace-core`. Closes #1159 Signed-off-by: Eliza Weisman --- Cargo.toml | 2 - README.md | 17 + azure-pipelines.yml | 4 - ci/patch.toml | 2 - tokio-trace/CHANGELOG.md | 3 - tokio-trace/Cargo.toml | 62 - tokio-trace/LICENSE | 25 - tokio-trace/README.md | 192 -- tokio-trace/benches/no_subscriber.rs | 42 - tokio-trace/benches/subscriber.rs | 158 -- tokio-trace/examples/counters.rs | 144 - tokio-trace/examples/sloggish/main.rs | 53 - .../examples/sloggish/sloggish_subscriber.rs | 285 -- tokio-trace/src/field.rs | 56 - tokio-trace/src/level_filters.rs | 137 - tokio-trace/src/lib.rs | 378 --- tokio-trace/src/macros.rs | 2467 ----------------- tokio-trace/src/span.rs | 858 ------ tokio-trace/src/subscriber.rs | 40 - tokio-trace/test-log-support/Cargo.toml | 10 - .../test-log-support/tests/log_no_trace.rs | 74 - .../test_static_max_level_features/Cargo.toml | 10 - .../tests/test.rs | 71 - tokio-trace/tests/event.rs | 251 -- .../filter_caching_is_lexically_scoped.rs | 64 - ...s_are_not_reevaluated_for_the_same_span.rs | 69 - ...re_reevaluated_for_different_call_sites.rs | 80 - tokio-trace/tests/macros.rs | 713 ----- tokio-trace/tests/span.rs | 723 ----- tokio-trace/tests/subscriber.rs | 48 - tokio-trace/tests/support/event.rs | 93 - tokio-trace/tests/support/field.rs | 225 -- tokio-trace/tests/support/metadata.rs | 64 - tokio-trace/tests/support/mod.rs | 8 - tokio-trace/tests/support/span.rs | 178 -- tokio-trace/tests/support/subscriber.rs | 409 --- tokio-trace/tokio-trace-core/CHANGELOG.md | 22 - tokio-trace/tokio-trace-core/Cargo.toml | 24 - tokio-trace/tokio-trace-core/LICENSE | 25 - tokio-trace/tokio-trace-core/README.md | 56 - tokio-trace/tokio-trace-core/src/callsite.rs | 142 - .../tokio-trace-core/src/dispatcher.rs | 612 ---- tokio-trace/tokio-trace-core/src/event.rs | 119 - tokio-trace/tokio-trace-core/src/field.rs | 801 ------ tokio-trace/tokio-trace-core/src/lib.rs | 213 -- tokio-trace/tokio-trace-core/src/metadata.rs | 370 --- tokio-trace/tokio-trace-core/src/parent.rs | 11 - tokio-trace/tokio-trace-core/src/span.rs | 185 -- .../tokio-trace-core/src/subscriber.rs | 477 ---- tokio-trace/tokio-trace-core/tests/macros.rs | 49 - tokio/Cargo.toml | 4 +- tokio/src/runtime/threadpool/builder.rs | 2 +- 52 files changed, 20 insertions(+), 11107 deletions(-) delete mode 100644 tokio-trace/CHANGELOG.md delete mode 100644 tokio-trace/Cargo.toml delete mode 100644 tokio-trace/LICENSE delete mode 100644 tokio-trace/README.md delete mode 100644 tokio-trace/benches/no_subscriber.rs delete mode 100644 tokio-trace/benches/subscriber.rs delete mode 100644 tokio-trace/examples/counters.rs delete mode 100644 tokio-trace/examples/sloggish/main.rs delete mode 100644 tokio-trace/examples/sloggish/sloggish_subscriber.rs delete mode 100644 tokio-trace/src/field.rs delete mode 100644 tokio-trace/src/level_filters.rs delete mode 100644 tokio-trace/src/lib.rs delete mode 100644 tokio-trace/src/macros.rs delete mode 100644 tokio-trace/src/span.rs delete mode 100644 tokio-trace/src/subscriber.rs delete mode 100644 tokio-trace/test-log-support/Cargo.toml delete mode 100644 tokio-trace/test-log-support/tests/log_no_trace.rs delete mode 100644 tokio-trace/test_static_max_level_features/Cargo.toml delete mode 100644 tokio-trace/test_static_max_level_features/tests/test.rs delete mode 100644 tokio-trace/tests/event.rs delete mode 100644 tokio-trace/tests/filter_caching_is_lexically_scoped.rs delete mode 100644 tokio-trace/tests/filters_are_not_reevaluated_for_the_same_span.rs delete mode 100644 tokio-trace/tests/filters_are_reevaluated_for_different_call_sites.rs delete mode 100644 tokio-trace/tests/macros.rs delete mode 100644 tokio-trace/tests/span.rs delete mode 100644 tokio-trace/tests/subscriber.rs delete mode 100644 tokio-trace/tests/support/event.rs delete mode 100644 tokio-trace/tests/support/field.rs delete mode 100644 tokio-trace/tests/support/metadata.rs delete mode 100644 tokio-trace/tests/support/mod.rs delete mode 100644 tokio-trace/tests/support/span.rs delete mode 100644 tokio-trace/tests/support/subscriber.rs delete mode 100644 tokio-trace/tokio-trace-core/CHANGELOG.md delete mode 100644 tokio-trace/tokio-trace-core/Cargo.toml delete mode 100644 tokio-trace/tokio-trace-core/LICENSE delete mode 100644 tokio-trace/tokio-trace-core/README.md delete mode 100644 tokio-trace/tokio-trace-core/src/callsite.rs delete mode 100644 tokio-trace/tokio-trace-core/src/dispatcher.rs delete mode 100644 tokio-trace/tokio-trace-core/src/event.rs delete mode 100644 tokio-trace/tokio-trace-core/src/field.rs delete mode 100644 tokio-trace/tokio-trace-core/src/lib.rs delete mode 100644 tokio-trace/tokio-trace-core/src/metadata.rs delete mode 100644 tokio-trace/tokio-trace-core/src/parent.rs delete mode 100644 tokio-trace/tokio-trace-core/src/span.rs delete mode 100644 tokio-trace/tokio-trace-core/src/subscriber.rs delete mode 100644 tokio-trace/tokio-trace-core/tests/macros.rs diff --git a/Cargo.toml b/Cargo.toml index 4b14d0772..de01ba670 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,8 +18,6 @@ members = [ "tokio-timer", "tokio-tcp", # "tokio-tls", - # "tokio-trace", - # "tokio-trace/tokio-trace-core", "tokio-udp", # "tokio-uds", ] diff --git a/README.md b/README.md index 0a019e5f0..6447d525e 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,23 @@ The crates included as part of Tokio are: [`tokio-udp`]: tokio-udp [`tokio-uds`]: tokio-uds +## Related Projects + +In addition to the crates in this repository, the Tokio project also maintains +several other libraries, including: + +* [`tracing`] (formerly `tokio-trace`): A framework for application-level + tracing and async-aware diagnostics. + +* [`mio`]: A low-level, cross-platform abstraction over OS I/O APIs that powers + `tokio`. + +* [`bytes`]: Utilities for working with bytes, including efficient byte buffers. + +[`tracing`]: https://github.com/tokio-rs/tracing +[`mio`]: https://github.com/tokio-rs/mio +[`bytes`]: https://github.com/tokio-rs/bytes + ## Supported Rust Versions Tokio is built against the latest stable, nightly, and beta Rust releases. The diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f6ae63f09..4d6a09d08 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -54,10 +54,6 @@ jobs: # - tokio-threadpool - tokio-timer - tokio-test - # - tokio-trace - # - tokio-trace/tokio-trace-core - # - tokio-trace/test-log-support - # - tokio-trace/test_static_max_level_features # - template: ci/azure-cargo-check.yml # parameters: diff --git a/ci/patch.toml b/ci/patch.toml index ab5313caf..e34484a2f 100644 --- a/ci/patch.toml +++ b/ci/patch.toml @@ -16,7 +16,5 @@ tokio-threadpool = { path = "tokio-threadpool" } tokio-timer = { path = "tokio-timer" } tokio-tcp = { path = "tokio-tcp" } tokio-tls = { path = "tokio-tls" } -tokio-trace = { path = "tokio-trace" } -tokio-trace-core = { path = "tokio-trace/tokio-trace-core" } tokio-udp = { path = "tokio-udp" } tokio-uds = { path = "tokio-uds" } diff --git a/tokio-trace/CHANGELOG.md b/tokio-trace/CHANGELOG.md deleted file mode 100644 index eaf3ae894..000000000 --- a/tokio-trace/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -# 0.1.0 (April 22, 2019) - -- Initial release diff --git a/tokio-trace/Cargo.toml b/tokio-trace/Cargo.toml deleted file mode 100644 index de7175477..000000000 --- a/tokio-trace/Cargo.toml +++ /dev/null @@ -1,62 +0,0 @@ -[package] -name = "tokio-trace" -# When releasing to crates.io: -# - Remove path dependencies -# - Update html_root_url. -# - Update doc url -# - Cargo.toml -# - README.md -# - Update CHANGELOG.md. -# - Create "v0.1.x" git tag -version = "0.1.0" -authors = ["Tokio Contributors "] -license = "MIT" -readme = "README.md" -repository = "https://github.com/tokio-rs/tokio" -homepage = "https://tokio.rs" -documentation = "https://docs.rs/tokio-trace/0.1.0/tokio_trace" -description = """ -A scoped, structured logging and diagnostics system. -""" -categories = ["development-tools::debugging", "asynchronous"] -keywords = ["logging", "tracing"] - -[dependencies] -tokio-trace-core = { path = "./tokio-trace-core" } -log = { version = "0.4", optional = true } -cfg-if = "0.1.7" - -[dev-dependencies] -ansi_term = "0.11" -humantime = "1.1.1" -futures = "0.1" -log = "0.4" -criterion = { version = "0.2", default_features = false } -# These are used for the "basic" example from the tokio-trace-prototype repo, -# which is currently not included as it used the `tokio-trace-log` crate, and -# that crate is currently unstable. -# env_logger = "0.5" -# tokio-trace-log = { path = "../tokio-trace-log" } - -[features] -max_level_off = [] -max_level_error = [] -max_level_warn = [] -max_level_info = [] -max_level_debug = [] -max_level_trace = [] - -release_max_level_off = [] -release_max_level_error = [] -release_max_level_warn = [] -release_max_level_info = [] -release_max_level_debug = [] -release_max_level_trace = [] - -[[bench]] -name = "subscriber" -harness = false - -[[bench]] -name = "no_subscriber" -harness = false \ No newline at end of file diff --git a/tokio-trace/LICENSE b/tokio-trace/LICENSE deleted file mode 100644 index cdb28b4b5..000000000 --- a/tokio-trace/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2019 Tokio Contributors - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/tokio-trace/README.md b/tokio-trace/README.md deleted file mode 100644 index 943acdfff..000000000 --- a/tokio-trace/README.md +++ /dev/null @@ -1,192 +0,0 @@ -# tokio-trace - -A scoped, structured logging and diagnostics system. - -[Documentation](https://docs.rs/tokio-trace/0.1.0/tokio_trace/index.html) - -## Overview - -`tokio-trace` is a framework for instrumenting Rust programs to collect -structured, event-based diagnostic information. - -In asynchronous systems like Tokio, interpreting traditional log messages can -often be quite challenging. Since individual tasks are multiplexed on the same -thread, associated events and log lines are intermixed making it difficult to -trace the logic flow. `tokio-trace` expands upon logging-style diagnostics by -allowing libraries and applications to record structured events with additional -information about *temporality* and *causality* — unlike a log message, a span -in `tokio-trace` has a beginning and end time, may be entered and exited by the -flow of execution, and may exist within a nested tree of similar spans. In -addition, `tokio-trace` spans are *structured*, with the ability to record typed -data as well as textual messages. - -The `tokio-trace` crate provides the APIs necessary for instrumenting libraries -and applications to emit trace data. - -## Usage - -First, add this to your `Cargo.toml`: - -```toml -[dependencies] -tokio-trace = "0.1" -``` - -Next, add this to your crate: - -```rust -#[macro_use] -extern crate tokio_trace; -``` - -This crate provides macros for creating `Span`s and `Event`s, which represent -periods of time and momentary events within the execution of a program, -respectively. - -As a rule of thumb, _spans_ should be used to represent discrete units of work -(e.g., a given request's lifetime in a server) or periods of time spent in a -given context (e.g., time spent interacting with an instance of an external -system, such as a database). In contrast, _events_ should be used to represent -points in time within a span — a request returned with a given status code, -_n_ new items were taken from a queue, and so on. - -`Span`s are constructed using the `span!` macro, and then _entered_ -to indicate that some code takes place within the context of that `Span`: - -```rust -// Construct a new span named "my span". -let mut span = span!("my span"); -span.in_scope(|| { - // Any trace events in this closure or code called by it will occur within - // the span. -}); -// Dropping the span will close it, indicating that it has ended. -``` - -The `Event` type represent an event that occurs instantaneously, and is -essentially a `Span` that cannot be entered. They are created using the `event!` -macro: - -```rust -use tokio_trace::Level; -event!(Level::INFO, "something has happened!"); -``` - -Users of the [`log`] crate should note that `tokio-trace` exposes a set of macros for -creating `Event`s (`trace!`, `debug!`, `info!`, `warn!`, and `error!`) which may -be invoked with the same syntax as the similarly-named macros from the `log` -crate. Often, the process of converting a project to use `tokio-trace` can begin -with a simple drop-in replacement. - -Let's consider the `log` crate's yak-shaving example: - -```rust -#[macro_use] -extern crate tokio_trace; -use tokio_trace::field; - -pub fn shave_the_yak(yak: &mut Yak) { - // Create a new span for this invocation of `shave_the_yak`, annotated - // with the yak being shaved as a *field* on the span. - span!("shave_the_yak", yak = field::debug(&yak)).in_scope(|| { - // Since the span is annotated with the yak, it is part of the context - // for everything happening inside the span. Therefore, we don't need - // to add it to the message for this event, as the `log` crate does. - info!(target: "yak_events", "Commencing yak shaving"); - - loop { - match find_a_razor() { - Ok(razor) => { - // We can add the razor as a field rather than formatting it - // as part of the message, allowing subscribers to consume it - // in a more structured manner: - info!({ razor = field::display(razor) }, "Razor located"); - yak.shave(razor); - break; - } - Err(err) => { - // However, we can also create events with formatted messages, - // just as we would for log records. - warn!("Unable to locate a razor: {}, retrying", err); - } - } - } - }) -} -``` - -You can find examples showing how to use this crate in the examples directory. - -### In libraries - -Libraries should link only to the `tokio-trace` crate, and use the provided -macros to record whatever information will be useful to downstream consumers. - -### In executables - -In order to record trace events, executables have to use a `Subscriber` -implementation compatible with `tokio-trace`. A `Subscriber` implements a way of -collecting trace data, such as by logging it to standard output. - -There currently aren't too many subscribers to choose from. The best one to use right now -is probably [`tokio-trace-fmt`], which logs to the terminal. - -The simplest way to use a subscriber is to call the `set_global_default` function: - -```rust -#[macro_use] -extern crate tokio_trace; - -let my_subscriber = FooSubscriber::new(); - -tokio_trace::subscriber::set_global_default(my_subscriber).expect("setting tokio_trace default failed"); -``` - -This subscriber will be used as the default in all threads for the remainder of the duration -of the program, similar to how loggers work in the `log` crate. - -Note: Libraries should *NOT* call `set_global_default()`! That will cause conflicts when -executables try to set the default later. - -In addition, you can locally override the default subscriber, using the `tokio` pattern -of executing code in a context. For example: - -```rust -#[macro_use] -extern crate tokio_trace; - -let my_subscriber = FooSubscriber::new(); - -tokio_trace::subscriber::with_default(subscriber, || { - // Any trace events generated in this closure or by functions it calls - // will be collected by `my_subscriber`. -}) -``` - -This approach allows trace data to be collected by multiple subscribers within -different contexts in the program. Note that the override only applies to the -currently executing thread; other threads will not see the change from with_default. - -Any trace events generated outside the context of a -subscriber will not be collected. - -The executable itself may use the `tokio-trace` crate to instrument itself as -well. - -The [`tokio-trace-nursery`] repository contains less stable crates designed to -be used with the `tokio-trace` ecosystem. It includes a collection of -`Subscriber` implementations, as well as utility and adapter crates. - -[`log`]: https://docs.rs/log/0.4.6/log/ -[`tokio-trace-nursery`]: https://github.com/tokio-rs/tokio-trace-nursery -[`tokio-trace-fmt`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-fmt - -## License - -This project is licensed under the [MIT license](LICENSE). - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in Tokio by you, shall be licensed as MIT, without any additional -terms or conditions. diff --git a/tokio-trace/benches/no_subscriber.rs b/tokio-trace/benches/no_subscriber.rs deleted file mode 100644 index d5c8090e1..000000000 --- a/tokio-trace/benches/no_subscriber.rs +++ /dev/null @@ -1,42 +0,0 @@ -#[macro_use] -extern crate tokio_trace; -#[macro_use] -extern crate log; -#[macro_use] -extern crate criterion; - -use criterion::Criterion; -use tokio_trace::Level; - -fn criterion_benchmark(c: &mut Criterion) { - c.bench_function("span_no_subscriber", |b| { - b.iter(|| { - span!(Level::TRACE, "span"); - }) - }); - c.bench_function("bench_log_no_logger", |b| { - b.iter(|| { - log!(log::Level::Info, "log"); - }); - }); - c.bench_function("bench_costly_field_no_subscriber", |b| { - b.iter(|| { - span!( - Level::TRACE, - "span", - foo = tokio_trace::field::display(format!("bar {:?}", 2)) - ); - }); - }); - // This is just included as a baseline. - c.bench_function("bench_no_span_no_subscriber", |b| { - b.iter(|| {}); - }); - c.bench_function("bench_1_atomic_load", |b| { - use std::sync::atomic::{AtomicUsize, Ordering}; - let foo = AtomicUsize::new(1); - b.iter(|| foo.load(Ordering::Relaxed)); - }); -} -criterion_group!(benches, criterion_benchmark); -criterion_main!(benches); diff --git a/tokio-trace/benches/subscriber.rs b/tokio-trace/benches/subscriber.rs deleted file mode 100644 index 117c32207..000000000 --- a/tokio-trace/benches/subscriber.rs +++ /dev/null @@ -1,158 +0,0 @@ -#[macro_use] -extern crate tokio_trace; -#[macro_use] -extern crate criterion; - -use criterion::{black_box, Criterion}; -use tokio_trace::Level; - -use std::{ - fmt, - sync::{Mutex, MutexGuard}, -}; -use tokio_trace::{field, span, Event, Id, Metadata}; - -/// A subscriber that is enabled but otherwise does nothing. -struct EnabledSubscriber; - -impl tokio_trace::Subscriber for EnabledSubscriber { - fn new_span(&self, span: &span::Attributes) -> Id { - let _ = span; - Id::from_u64(0xDEADFACE) - } - - fn event(&self, event: &Event) { - let _ = event; - } - - fn record(&self, span: &Id, values: &span::Record) { - let _ = (span, values); - } - - fn record_follows_from(&self, span: &Id, follows: &Id) { - let _ = (span, follows); - } - - fn enabled(&self, metadata: &Metadata) -> bool { - let _ = metadata; - true - } - - fn enter(&self, span: &Id) { - let _ = span; - } - - fn exit(&self, span: &Id) { - let _ = span; - } -} - -/// Simulates a subscriber that records span data. -struct VisitingSubscriber(Mutex); - -struct Visitor<'a>(MutexGuard<'a, String>); - -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 VisitingSubscriber { - fn new_span(&self, span: &span::Attributes) -> Id { - let mut visitor = Visitor(self.0.lock().unwrap()); - span.record(&mut visitor); - Id::from_u64(0xDEADFACE) - } - - 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 visitor = Visitor(self.0.lock().unwrap()); - event.record(&mut visitor); - } - - fn record_follows_from(&self, span: &Id, follows: &Id) { - let _ = (span, follows); - } - - fn enabled(&self, metadata: &Metadata) -> bool { - let _ = metadata; - true - } - - fn enter(&self, span: &Id) { - let _ = span; - } - - fn exit(&self, span: &Id) { - let _ = span; - } -} - -const N_SPANS: usize = 100; - -fn criterion_benchmark(c: &mut Criterion) { - c.bench_function("span_no_fields", |b| { - tokio_trace::subscriber::with_default(EnabledSubscriber, || { - b.iter(|| span!(Level::TRACE, "span")) - }); - }); - - c.bench_function("enter_span", |b| { - tokio_trace::subscriber::with_default(EnabledSubscriber, || { - let span = span!(Level::TRACE, "span"); - b.iter(|| black_box(span.in_scope(|| {}))) - }); - }); - - c.bench_function("span_repeatedly", |b| { - #[inline] - fn mk_span(i: u64) -> tokio_trace::Span { - span!(Level::TRACE, "span", i = i) - } - - let n = black_box(N_SPANS); - tokio_trace::subscriber::with_default(EnabledSubscriber, || { - b.iter(|| (0..n).fold(mk_span(0), |_, i| mk_span(i as u64))) - }); - }); - - c.bench_function("span_with_fields", |b| { - tokio_trace::subscriber::with_default(EnabledSubscriber, || { - b.iter(|| { - span!( - Level::TRACE, - "span", - foo = "foo", - bar = "bar", - baz = 3, - quuux = tokio_trace::field::debug(0.99) - ) - }) - }); - }); - - c.bench_function("span_with_fields_record", |b| { - let subscriber = VisitingSubscriber(Mutex::new(String::from(""))); - tokio_trace::subscriber::with_default(subscriber, || { - b.iter(|| { - span!( - Level::TRACE, - "span", - foo = "foo", - bar = "bar", - baz = 3, - quuux = tokio_trace::field::debug(0.99) - ) - }) - }); - }); -} - -criterion_group!(benches, criterion_benchmark); -criterion_main!(benches); diff --git a/tokio-trace/examples/counters.rs b/tokio-trace/examples/counters.rs deleted file mode 100644 index dad02bb82..000000000 --- a/tokio-trace/examples/counters.rs +++ /dev/null @@ -1,144 +0,0 @@ -#[macro_use] -extern crate tokio_trace; - -use tokio_trace::{ - field::{Field, Visit}, - span, - subscriber::{self, Subscriber}, - Event, Id, Level, Metadata, -}; - -use std::{ - collections::HashMap, - fmt, - sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, RwLock, RwLockReadGuard, - }, -}; - -#[derive(Clone)] -struct Counters(Arc>>); - -struct CounterSubscriber { - ids: AtomicUsize, - counters: Counters, -} - -struct Count<'a> { - counters: RwLockReadGuard<'a, HashMap>, -} - -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 { - counter.fetch_add(value as usize, Ordering::Release); - } else { - counter.fetch_sub((value * -1) as usize, Ordering::Release); - } - }; - } - - fn record_u64(&mut self, field: &Field, value: u64) { - if let Some(counter) = self.counters.get(field.name()) { - counter.fetch_add(value as usize, Ordering::Release); - }; - } - - fn record_bool(&mut self, _: &Field, _: bool) {} - fn record_str(&mut self, _: &Field, _: &str) {} - fn record_debug(&mut self, _: &Field, _: &fmt::Debug) {} -} - -impl CounterSubscriber { - fn visitor(&self) -> Count { - Count { - counters: self.counters.0.read().unwrap(), - } - } -} - -impl Subscriber for CounterSubscriber { - fn register_callsite(&self, meta: &Metadata) -> subscriber::Interest { - let mut interest = subscriber::Interest::never(); - for key in meta.fields() { - let name = key.name(); - if name.contains("count") { - self.counters - .0 - .write() - .unwrap() - .entry(name.to_owned()) - .or_insert_with(|| AtomicUsize::new(0)); - interest = subscriber::Interest::always(); - } - } - interest - } - - fn new_span(&self, new_span: &span::Attributes) -> Id { - new_span.record(&mut self.visitor()); - let id = self.ids.fetch_add(1, Ordering::SeqCst); - Id::from_u64(id as u64) - } - - fn record_follows_from(&self, _span: &Id, _follows: &Id) { - // unimplemented - } - - fn record(&self, _: &Id, values: &span::Record) { - values.record(&mut self.visitor()) - } - - fn event(&self, event: &Event) { - event.record(&mut self.visitor()) - } - - fn enabled(&self, metadata: &Metadata) -> bool { - metadata.fields().iter().any(|f| f.name().contains("count")) - } - - fn enter(&self, _span: &Id) {} - fn exit(&self, _span: &Id) {} -} - -impl Counters { - fn print_counters(&self) { - for (k, v) in self.0.read().unwrap().iter() { - println!("{}: {}", k, v.load(Ordering::Acquire)); - } - } - - fn new() -> (Self, CounterSubscriber) { - let counters = Counters(Arc::new(RwLock::new(HashMap::new()))); - let subscriber = CounterSubscriber { - ids: AtomicUsize::new(1), - counters: counters.clone(), - }; - (counters, subscriber) - } -} - -fn main() { - let (counters, subscriber) = Counters::new(); - - tokio_trace::subscriber::with_default(subscriber, || { - let mut foo: u64 = 2; - span!(Level::TRACE, "my_great_span", foo_count = &foo).in_scope(|| { - foo += 1; - info!({ yak_shaved = true, yak_count = 1 }, "hi from inside my span"); - span!( - Level::TRACE, - "my other span", - foo_count = &foo, - baz_count = 5 - ) - .in_scope(|| { - warn!({ yak_shaved = false, yak_count = -1 }, "failed to shave yak"); - }); - }); - }); - - counters.print_counters(); -} diff --git a/tokio-trace/examples/sloggish/main.rs b/tokio-trace/examples/sloggish/main.rs deleted file mode 100644 index 00c465d6c..000000000 --- a/tokio-trace/examples/sloggish/main.rs +++ /dev/null @@ -1,53 +0,0 @@ -//! A simple example demonstrating how one might implement a custom -//! subscriber. -//! -//! This subscriber implements a tree-structured logger similar to -//! the "compact" formatter in [`slog-term`]. The demo mimicks the -//! example output in the screenshot in the [`slog` README]. -//! -//! Note that this logger isn't ready for actual production use. -//! Several corners were cut to make the example simple. -//! -//! [`slog-term`]: https://docs.rs/slog-term/2.4.0/slog_term/ -//! [`slog` README]: https://github.com/slog-rs/slog#terminal-output-example -#[macro_use] -extern crate tokio_trace; - -use tokio_trace::{field, Level}; - -mod sloggish_subscriber; -use self::sloggish_subscriber::SloggishSubscriber; - -fn main() { - let subscriber = SloggishSubscriber::new(2); - - tokio_trace::subscriber::with_default(subscriber, || { - span!(Level::TRACE, "", version = &field::display(5.0)).in_scope(|| { - span!(Level::TRACE, "server", host = "localhost", port = 8080).in_scope(|| { - info!("starting"); - info!("listening"); - let peer1 = span!(Level::TRACE, "conn", peer_addr = "82.9.9.9", port = 42381); - peer1.in_scope(|| { - debug!("connected"); - debug!({ length = 2 }, "message received"); - }); - let peer2 = span!(Level::TRACE, "conn", peer_addr = "8.8.8.8", port = 18230); - peer2.in_scope(|| { - debug!("connected"); - }); - peer1.in_scope(|| { - warn!({ algo = "xor" }, "weak encryption requested"); - debug!({ length = 8 }, "response sent"); - debug!("disconnected"); - }); - peer2.in_scope(|| { - debug!({ length = 5 }, "message received"); - debug!({ length = 8 }, "response sent"); - debug!("disconnected"); - }); - warn!("internal error"); - info!("exit"); - }) - }); - }); -} diff --git a/tokio-trace/examples/sloggish/sloggish_subscriber.rs b/tokio-trace/examples/sloggish/sloggish_subscriber.rs deleted file mode 100644 index aed43c830..000000000 --- a/tokio-trace/examples/sloggish/sloggish_subscriber.rs +++ /dev/null @@ -1,285 +0,0 @@ -//! A simple example demonstrating how one might implement a custom -//! subscriber. -//! -//! This subscriber implements a tree-structured logger similar to -//! the "compact" formatter in [`slog-term`]. The demo mimicks the -//! example output in the screenshot in the [`slog` README]. -//! -//! Note that this logger isn't ready for actual production use. -//! Several corners were cut to make the example simple. -//! -//! [`slog-term`]: https://docs.rs/slog-term/2.4.0/slog_term/ -//! [`slog` README]: https://github.com/slog-rs/slog#terminal-output-example -extern crate ansi_term; -extern crate humantime; -use self::ansi_term::{Color, Style}; -use super::tokio_trace::{ - self, - field::{Field, Visit}, - Id, Level, Subscriber, -}; - -use std::{ - cell::RefCell, - collections::HashMap, - fmt, - io::{self, Write}, - sync::{ - atomic::{AtomicUsize, Ordering}, - Mutex, - }, - thread, - time::SystemTime, -}; - -/// Tracks the currently executing span on a per-thread basis. -#[derive(Clone)] -pub struct CurrentSpanPerThread { - current: &'static thread::LocalKey>>, -} - -impl CurrentSpanPerThread { - pub fn new() -> Self { - thread_local! { - static CURRENT: RefCell> = RefCell::new(vec![]); - }; - Self { current: &CURRENT } - } - - /// Returns the [`Id`](::Id) of the span in which the current thread is - /// executing, or `None` if it is not inside of a span. - pub fn id(&self) -> Option { - self.current - .with(|current| current.borrow().last().cloned()) - } - - pub fn enter(&self, span: Id) { - self.current.with(|current| { - current.borrow_mut().push(span); - }) - } - - pub fn exit(&self) { - self.current.with(|current| { - let _ = current.borrow_mut().pop(); - }) - } -} - -pub struct SloggishSubscriber { - // TODO: this can probably be unified with the "stack" that's used for - // printing? - current: CurrentSpanPerThread, - indent_amount: usize, - stderr: io::Stderr, - stack: Mutex>, - spans: Mutex>, - ids: AtomicUsize, -} - -struct Span { - parent: Option, - kvs: Vec<(&'static str, String)>, -} - -struct Event<'a> { - stderr: io::StderrLock<'a>, - comma: bool, -} - -struct ColorLevel<'a>(&'a Level); - -impl<'a> fmt::Display for ColorLevel<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.0 { - &Level::TRACE => Color::Purple.paint("TRACE"), - &Level::DEBUG => Color::Blue.paint("DEBUG"), - &Level::INFO => Color::Green.paint("INFO "), - &Level::WARN => Color::Yellow.paint("WARN "), - &Level::ERROR => Color::Red.paint("ERROR"), - } - .fmt(f) - } -} - -impl Span { - fn new(parent: Option, attrs: &tokio_trace::span::Attributes) -> Self { - let mut span = Self { - parent, - kvs: Vec::new(), - }; - attrs.record(&mut span); - span - } -} - -impl Visit for Span { - fn record_debug(&mut self, field: &Field, value: &fmt::Debug) { - self.kvs.push((field.name(), format!("{:?}", value))) - } -} - -impl<'a> Visit for Event<'a> { - fn record_debug(&mut self, field: &Field, value: &fmt::Debug) { - write!( - &mut self.stderr, - "{comma} ", - comma = if self.comma { "," } else { "" }, - ) - .unwrap(); - let name = field.name(); - if name == "message" { - write!( - &mut self.stderr, - "{}", - // Have to alloc here due to `ansi_term`'s API... - Style::new().bold().paint(format!("{:?}", value)) - ) - .unwrap(); - self.comma = true; - } else { - write!( - &mut self.stderr, - "{}: {:?}", - Style::new().bold().paint(name), - value - ) - .unwrap(); - self.comma = true; - } - } -} - -impl SloggishSubscriber { - pub fn new(indent_amount: usize) -> Self { - Self { - current: CurrentSpanPerThread::new(), - indent_amount, - stderr: io::stderr(), - stack: Mutex::new(vec![]), - spans: Mutex::new(HashMap::new()), - ids: AtomicUsize::new(1), - } - } - - fn print_kvs<'a, I, K, V>( - &self, - writer: &mut impl Write, - kvs: I, - leading: &str, - ) -> io::Result<()> - where - I: IntoIterator, - K: AsRef + 'a, - V: fmt::Display + 'a, - { - let mut kvs = kvs.into_iter(); - if let Some((k, v)) = kvs.next() { - write!( - writer, - "{}{}: {}", - leading, - Style::new().bold().paint(k.as_ref()), - v - )?; - } - for (k, v) in kvs { - write!(writer, ", {}: {}", Style::new().bold().paint(k.as_ref()), v)?; - } - Ok(()) - } - - fn print_indent(&self, writer: &mut impl Write, indent: usize) -> io::Result<()> { - for _ in 0..(indent * self.indent_amount) { - write!(writer, " ")?; - } - Ok(()) - } -} - -impl Subscriber for SloggishSubscriber { - fn enabled(&self, _metadata: &tokio_trace::Metadata) -> bool { - true - } - - fn new_span(&self, span: &tokio_trace::span::Attributes) -> tokio_trace::Id { - 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(), span); - self.spans.lock().unwrap().insert(id.clone(), span); - id - } - - 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); - } - } - - fn record_follows_from(&self, _span: &tokio_trace::Id, _follows: &tokio_trace::Id) { - // unimplemented - } - - fn enter(&self, span_id: &tokio_trace::Id) { - self.current.enter(span_id.clone()); - let mut stderr = self.stderr.lock(); - let mut stack = self.stack.lock().unwrap(); - let spans = self.spans.lock().unwrap(); - let data = spans.get(span_id); - let parent = data.and_then(|span| span.parent.as_ref()); - if stack.iter().any(|id| id == span_id) { - // We are already in this span, do nothing. - return; - } else { - let indent = if let Some(idx) = stack - .iter() - .position(|id| parent.map(|p| id == p).unwrap_or(false)) - { - let idx = idx + 1; - stack.truncate(idx); - idx - } else { - stack.clear(); - 0 - }; - self.print_indent(&mut stderr, indent).unwrap(); - stack.push(span_id.clone()); - if let Some(data) = data { - self.print_kvs(&mut stderr, data.kvs.iter().map(|(k, v)| (k, v)), "") - .unwrap(); - } - write!(&mut stderr, "\n").unwrap(); - } - } - - fn event(&self, event: &tokio_trace::Event) { - let mut stderr = self.stderr.lock(); - let indent = self.stack.lock().unwrap().len(); - self.print_indent(&mut stderr, indent).unwrap(); - write!( - &mut stderr, - "{timestamp} {level} {target}", - timestamp = humantime::format_rfc3339_seconds(SystemTime::now()), - level = ColorLevel(event.metadata().level()), - target = &event.metadata().target(), - ) - .unwrap(); - let mut visitor = Event { - stderr, - comma: false, - }; - event.record(&mut visitor); - write!(&mut visitor.stderr, "\n").unwrap(); - } - - #[inline] - fn exit(&self, _span: &tokio_trace::Id) { - // TODO: unify stack with current span - self.current.exit(); - } - - fn drop_span(&self, _id: tokio_trace::Id) { - // TODO: GC unneeded spans. - } -} diff --git a/tokio-trace/src/field.rs b/tokio-trace/src/field.rs deleted file mode 100644 index 5b0e37496..000000000 --- a/tokio-trace/src/field.rs +++ /dev/null @@ -1,56 +0,0 @@ -//! Structured data associated with `Span`s and `Event`s. -pub use tokio_trace_core::field::*; - -use Metadata; - -/// Trait implemented to allow a type to be used as a field key. -/// -/// **Note**: Although this is implemented for both the [`Field`] type *and* any -/// type that can be borrowed as an `&str`, only `Field` allows _O_(1) access. -/// Indexing a field with a string results in an iterative search that performs -/// string comparisons. Thus, if possible, once the key for a field is known, it -/// should be used whenever possible. -/// -/// [`Field`]: ../struct.Field.html -pub trait AsField: ::sealed::Sealed { - /// Attempts to convert `&self` into a `Field` with the specified `metadata`. - /// - /// If `metadata` defines this field, then the field is returned. Otherwise, - /// this returns `None`. - fn as_field(&self, metadata: &Metadata) -> Option; -} - -// ===== impl AsField ===== - -impl AsField for Field { - #[inline] - fn as_field(&self, metadata: &Metadata) -> Option { - if self.callsite() == metadata.callsite() { - Some(self.clone()) - } else { - None - } - } -} - -impl<'a> AsField for &'a Field { - #[inline] - fn as_field(&self, metadata: &Metadata) -> Option { - if self.callsite() == metadata.callsite() { - Some((*self).clone()) - } else { - None - } - } -} - -impl AsField for str { - #[inline] - fn as_field(&self, metadata: &Metadata) -> Option { - metadata.fields().field(&self) - } -} - -impl ::sealed::Sealed for Field {} -impl<'a> ::sealed::Sealed for &'a Field {} -impl ::sealed::Sealed for str {} diff --git a/tokio-trace/src/level_filters.rs b/tokio-trace/src/level_filters.rs deleted file mode 100644 index dff70b4ea..000000000 --- a/tokio-trace/src/level_filters.rs +++ /dev/null @@ -1,137 +0,0 @@ -//! Trace verbosity level filtering. -//! -//! # Compile time filters -//! -//! Trace verbosity levels can be statically disabled at compile time via Cargo -//! features, similar to the [`log` crate]. Trace instrumentation at disabled -//! levels will be skipped and will not even be present in the resulting binary -//! unless the verbosity level is specified dynamically. This level is -//! configured separately for release and debug builds. The features are: -//! -//! * `max_level_off` -//! * `max_level_error` -//! * `max_level_warn` -//! * `max_level_info` -//! * `max_level_debug` -//! * `max_level_trace` -//! * `release_max_level_off` -//! * `release_max_level_error` -//! * `release_max_level_warn` -//! * `release_max_level_info` -//! * `release_max_level_debug` -//! * `release_max_level_trace` -//! -//! These features control the value of the `STATIC_MAX_LEVEL` constant. The -//! instrumentation macros macros check this value before recording an event or -//! constructing a span. By default, no levels are disabled. -//! -//! For example, a crate can disable trace level instrumentation in debug builds -//! and trace, debug, and info level instrumentation in release builds with the -//! following configuration: -//! -//! ```toml -//! [dependencies] -//! tokio-trace = { version = "0.1", features = ["max_level_debug", "release_max_level_warn"] } -//! ``` -//! -//! [`log` crate]: https://docs.rs/log/0.4.6/log/#compile-time-filters -use std::cmp::Ordering; -use tokio_trace_core::Level; - -/// A filter comparable to trace verbosity `Level`. -/// -/// If a `Level` is considered less than a `LevelFilter`, it should be -/// considered disabled; if greater than or equal to the `LevelFilter`, that -/// level is enabled. -/// -/// Note that this is essentially identical to the `Level` type, but with the -/// addition of an `OFF` level that completely disables all trace -/// instrumentation. -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] -pub struct LevelFilter(Option); - -impl LevelFilter { - /// The "off" level. - /// - /// Designates that trace instrumentation should be completely disabled. - pub const OFF: LevelFilter = LevelFilter(None); - /// The "error" level. - /// - /// Designates very serious errors. - pub const ERROR: LevelFilter = LevelFilter(Some(Level::ERROR)); - /// The "warn" level. - /// - /// Designates hazardous situations. - pub const WARN: LevelFilter = LevelFilter(Some(Level::WARN)); - /// The "info" level. - /// - /// Designates useful information. - pub const INFO: LevelFilter = LevelFilter(Some(Level::INFO)); - /// The "debug" level. - /// - /// Designates lower priority information. - pub const DEBUG: LevelFilter = LevelFilter(Some(Level::DEBUG)); - /// The "trace" level. - /// - /// Designates very low priority, often extremely verbose, information. - pub const TRACE: LevelFilter = LevelFilter(Some(Level::TRACE)); -} - -impl PartialEq for Level { - fn eq(&self, other: &LevelFilter) -> bool { - match other.0 { - None => false, - Some(ref level) => self.eq(level), - } - } -} - -impl PartialOrd for Level { - fn partial_cmp(&self, other: &LevelFilter) -> Option { - match other.0 { - None => Some(Ordering::Less), - Some(ref level) => self.partial_cmp(level), - } - } -} - -/// The statically configured maximum trace level. -/// -/// See the [module-level documentation] for information on how to configure -/// this. -/// -/// This value is checked by the `event!` and `span!` macros. Code that -/// manually constructs events or spans via the `Event::record` function or -/// `Span` constructors should compare the level against this value to -/// determine if those spans or events are enabled. -/// -/// [module-level documentation]: ../index.html#compile-time-filters -pub const STATIC_MAX_LEVEL: LevelFilter = MAX_LEVEL; - -cfg_if! { - if #[cfg(all(not(debug_assertions), feature = "release_max_level_off"))] { - const MAX_LEVEL: LevelFilter = LevelFilter::OFF; - } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_error"))] { - const MAX_LEVEL: LevelFilter = LevelFilter::ERROR; - } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_warn"))] { - const MAX_LEVEL: LevelFilter = LevelFilter::WARN; - } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_info"))] { - const MAX_LEVEL: LevelFilter = LevelFilter::INFO; - } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_debug"))] { - const MAX_LEVEL: LevelFilter = LevelFilter::DEBUG; - } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_trace"))] { - const MAX_LEVEL: LevelFilter = LevelFilter::TRACE; - } else if #[cfg(feature = "max_level_off")] { - const MAX_LEVEL: LevelFilter = LevelFilter::OFF; - } else if #[cfg(feature = "max_level_error")] { - const MAX_LEVEL: LevelFilter = LevelFilter::ERROR; - } else if #[cfg(feature = "max_level_warn")] { - const MAX_LEVEL: LevelFilter = LevelFilter::WARN; - } else if #[cfg(feature = "max_level_info")] { - const MAX_LEVEL: LevelFilter = LevelFilter::INFO; - } else if #[cfg(feature = "max_level_debug")] { - const MAX_LEVEL: LevelFilter = LevelFilter::DEBUG; - } else { - const MAX_LEVEL: LevelFilter = LevelFilter::TRACE; - } -} diff --git a/tokio-trace/src/lib.rs b/tokio-trace/src/lib.rs deleted file mode 100644 index 29c281d89..000000000 --- a/tokio-trace/src/lib.rs +++ /dev/null @@ -1,378 +0,0 @@ -#![doc(html_root_url = "https://docs.rs/tokio-trace/0.1.0")] -#![deny(missing_debug_implementations, missing_docs, unreachable_pub)] -#![cfg_attr(test, deny(warnings))] -//! A scoped, structured logging and diagnostics system. -//! -//! # Overview -//! -//! `tokio-trace` is a framework for instrumenting Rust programs to collect -//! structured, event-based diagnostic information. -//! -//! In asynchronous systems like Tokio, interpreting traditional log messages can -//! often be quite challenging. Since individual tasks are multiplexed on the same -//! thread, associated events and log lines are intermixed making it difficult to -//! trace the logic flow. `tokio-trace` expands upon logging-style diagnostics by -//! allowing libraries and applications to record structured events with additional -//! information about *temporality* and *causality* — unlike a log message, a span -//! in `tokio-trace` has a beginning and end time, may be entered and exited by the -//! flow of execution, and may exist within a nested tree of similar spans. In -//! addition, `tokio-trace` spans are *structured*, with the ability to record typed -//! data as well as textual messages. -//! -//! The `tokio-trace` crate provides the APIs necessary for instrumenting libraries -//! and applications to emit trace data. -//! -//! # Core Concepts -//! -//! The core of `tokio-trace`'s API is composed of _spans_, _events_ and -//! _subscribers_. We'll cover these in turn. -//! -//! ## Spans -//! -//! A [`span`] represents a _period of time_ during which a program was executing -//! in some context. A thread of execution is said to _enter_ a span when it -//! begins executing in that context, and to _exit_ the span when switching to -//! another context. The span in which a thread is currently executing is -//! referred to as the _current_ span. -//! -//! For example: -//! ``` -//! #[macro_use] -//! extern crate tokio_trace; -//! -//! use tokio_trace::Level; -//! -//! # fn main() { -//! let span = span!(Level::TRACE, "my_span"); -//! let _enter = span.enter(); -//! // perform some work in the context of `my_span`... -//! # } -//!``` -//! -//! The [`span` module]'s documentation provides further details on how to use spans. -//! -//! ## Events -//! -//! An [`Event`] represents a _point_ in time. It signifies something that -//! happened while the trace was executing. `Event`s are comparable to the log -//! records emitted by unstructured logging code, but unlike a typical log line, -//! an `Event` may occur within the context of a `Span`. Like a `Span`, it -//! may have fields, and implicitly inherits any of the fields present on its -//! parent span. -//! -//! For example: -//! ``` -//! # #[macro_use] extern crate tokio_trace; -//! # use tokio_trace::Level; -//! # fn main() { -//! // records an event outside of any span context: -//! event!(Level::INFO, "something happened"); -//! -//! span!(Level::INFO, "my_span").in_scope(|| { -//! // records an event within "my_span". -//! event!(Level::DEBUG, "something happened inside my_span"); -//! }); -//! # } -//!``` -//! -//! Essentially, `Event`s exist to bridge the gap between traditional -//! unstructured logging and span-based tracing. Similar to log records, they -//! may be recorded at a number of levels, and can have unstructured, -//! human-readable messages; however, they also carry key-value data and exist -//! within the context of the tree of spans that comprise a trace. Thus, -//! individual log record-like events can be pinpointed not only in time, but -//! in the logical execution flow of the system. -//! -//! Events are represented as a special case of spans — they are created, they -//! may have fields added, and then they close immediately, without being -//! entered. -//! -//! In general, events should be used to represent points in time _within_ a -//! span — a request returned with a given status code, _n_ new items were -//! taken from a queue, and so on. -//! -//! ## `Subscriber`s -//! -//! As `Span`s and `Event`s occur, they are recorded or aggregated by -//! implementations of the [`Subscriber`] trait. `Subscriber`s are notified -//! when an `Event` takes place and when a `Span` is entered or exited. These -//! notifications are represented by the following `Subscriber` trait methods: -//! + [`observe_event`], called when an `Event` takes place, -//! + [`enter`], called when execution enters a `Span`, -//! + [`exit`], called when execution exits a `Span` -//! -//! In addition, subscribers may implement the [`enabled`] function to _filter_ -//! the notifications they receive based on [metadata] describing each `Span` -//! or `Event`. If a call to `Subscriber::enabled` returns `false` for a given -//! set of metadata, that `Subscriber` will *not* be notified about the -//! corresponding `Span` or `Event`. For performance reasons, if no currently -//! active subscribers express interest in a given set of metadata by returning -//! `true`, then the corresponding `Span` or `Event` will never be constructed. -//! -//! # Usage -//! -//! First, add this to your `Cargo.toml`: -//! -//! ```toml -//! [dependencies] -//! tokio-trace = "0.1" -//! ``` -//! -//! Next, add this to your crate: -//! -//! ```rust -//! #[macro_use] -//! extern crate tokio_trace; -//! # fn main() {} -//! ``` -//! -//! `Span`s are constructed using the `span!` macro, and then _entered_ -//! to indicate that some code takes place within the context of that `Span`: -//! -//! ```rust -//! # #[macro_use] -//! # extern crate tokio_trace; -//! # use tokio_trace::Level; -//! # fn main() { -//! // Construct a new span named "my span" with trace log level. -//! let span = span!(Level::TRACE, "my span"); -//! -//! // Enter the span, returning a guard object. -//! let _enter = span.enter(); -//! -//! // Any trace events that occur before the guard is dropped will occur -//! // within the span. -//! -//! // Dropping the guard will exit the span. -//! # } -//! ``` -//! -//! `Event`s are created using the `event!` macro, and are recorded when the -//! event is dropped: -//! -//! ```rust -//! # #[macro_use] -//! # extern crate tokio_trace; -//! # fn main() { -//! use tokio_trace::Level; -//! event!(Level::INFO, "something has happened!"); -//! # } -//! ``` -//! -//! Users of the [`log`] crate should note that `tokio-trace` exposes a set of -//! macros for creating `Event`s (`trace!`, `debug!`, `info!`, `warn!`, and -//! `error!`) which may be invoked with the same syntax as the similarly-named -//! macros from the `log` crate. Often, the process of converting a project to -//! use `tokio-trace` can begin with a simple drop-in replacement. -//! -//! Let's consider the `log` crate's yak-shaving example: -//! -//! ```rust -//! #[macro_use] -//! extern crate tokio_trace; -//! use tokio_trace::Level; -//! -//! # #[derive(Debug)] pub struct Yak(String); -//! # impl Yak { fn shave(&mut self, _: u32) {} } -//! # fn find_a_razor() -> Result { Ok(1) } -//! # fn main() { -//! pub fn shave_the_yak(yak: &mut Yak) { -//! let span = span!(Level::TRACE, "shave_the_yak", ?yak); -//! let _enter = span.enter(); -//! -//! // Since the span is annotated with the yak, it is part of the context -//! // for everything happening inside the span. Therefore, we don't need -//! // to add it to the message for this event, as the `log` crate does. -//! info!(target: "yak_events", "Commencing yak shaving"); -//! loop { -//! match find_a_razor() { -//! Ok(razor) => { -//! // We can add the razor as a field rather than formatting it -//! // as part of the message, allowing subscribers to consume it -//! // in a more structured manner: -//! info!({ %razor }, "Razor located"); -//! yak.shave(razor); -//! break; -//! } -//! Err(err) => { -//! // However, we can also create events with formatted messages, -//! // just as we would for log records. -//! warn!("Unable to locate a razor: {}, retrying", err); -//! } -//! } -//! } -//! } -//! # } -//! ``` -//! -//! You can find examples showing how to use this crate in the examples -//! directory. -//! -//! ## In libraries -//! -//! Libraries should link only to the `tokio-trace` crate, and use the provided -//! macros to record whatever information will be useful to downstream -//! consumers. -//! -//! ## In executables -//! -//! In order to record trace events, executables have to use a `Subscriber` -//! implementation compatible with `tokio-trace`. A `Subscriber` implements a -//! way of collecting trace data, such as by logging it to standard output. -//! -//! There currently aren't too many subscribers to choose from. The best one to use right now -//! is probably [`tokio-trace-fmt`], which logs to the terminal. -//! The simplest way to use a subscriber is to call the `set_global_default` function: -//! -//! ```no_build -//! #[macro_use] -//! extern crate tokio_trace; -//! let my_subscriber = FooSubscriber::new(); -//! tokio_trace::subscriber::set_global_default(my_subscriber).expect("setting tokio_trace default failed"); -//! ``` -//! -//! Note: Libraries should *NOT* call `set_global_default()`! That will cause conflicts when -//! executables try to set the default later. -//! -//! This subscriber will be used as the default in all threads for the remainder of the duration -//! of the program, similar to how loggers work in the `log` crate. -//! -//! In addition, you can locally override the default subscriber, using the `tokio` pattern -//! of executing code in a context. For example: -//! -//! Unlike the `log` crate, `tokio-trace` does *not* use a global `Subscriber` -//! which is initialized once. Instead, it follows the `tokio` pattern of -//! executing code in a context. For example: -//! -//! ```rust -//! #[macro_use] -//! extern crate tokio_trace; -//! # pub struct FooSubscriber; -//! # 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, _: &Record) {} -//! # fn event(&self, _: &tokio_trace::Event) {} -//! # fn record_follows_from(&self, _: &Id, _: &Id) {} -//! # fn enabled(&self, _: &Metadata) -> bool { false } -//! # fn enter(&self, _: &Id) {} -//! # fn exit(&self, _: &Id) {} -//! # } -//! # impl FooSubscriber { -//! # fn new() -> Self { FooSubscriber } -//! # } -//! # fn main() { -//! -//! let my_subscriber = FooSubscriber::new(); -//! -//! tokio_trace::subscriber::with_default(my_subscriber, || { -//! // Any trace events generated in this closure or by functions it calls -//! // will be collected by `my_subscriber`. -//! }) -//! # } -//! ``` -//! -//! This approach allows trace data to be collected by multiple subscribers -//! within different contexts in the program. Note that the override only applies to the -//! currently executing thread; other threads will not see the change from with_default. -//! with that subscriber as the default. -//! -//! Any trace events generated outside the -//! context of a subscriber will not be collected. -//! -//! The executable itself may use the `tokio-trace` crate to instrument itself -//! as well. -//! -//! The [`tokio-trace-nursery`] repository contains less stable crates designed -//! to be used with the `tokio-trace` ecosystem. It includes a collection of -//! `Subscriber` implementations, as well as utility and adapter crates. -//! -//! In particular, the following `tokio-trace-nursery` crates are likely to be -//! of interest: -//! -//! - [`tokio-trace-futures`] provides a compatibility layer with the `futures` -//! crate, allowing spans to be attached to `Future`s, `Stream`s, and `Executor`s. -//! - [`tokio-trace-fmt`] provides a `Subscriber` implementation for -//! logging formatted trace data to stdout, with similar filtering and -//! formatting to the `env-logger` crate. -//! - [`tokio-trace-log`] provides a compatibility layer with the `log` crate, -//! allowing log `Record`s to be recorded as `tokio-trace` `Event`s within the -//! trace tree. This is useful when a project using `tokio-trace` have -//! dependencies which use `log`. -//! -//! -//! ## Crate Feature Flags -//! -//! The following crate feature flags are available: -//! -//! * A set of features controlling the [static verbosity level]. -//! * `log` causes trace instrumentation points to emit [`log`] records as well -//! as trace events. This is inteded for use in libraries whose users may be -//! using either `tokio-trace` or `log`. -//! -//! ```toml -//! [dependencies] -//! tokio-trace = { version = "0.1", features = ["log"] } -//! ``` -//! -//! [`log`]: https://docs.rs/log/0.4.6/log/ -//! [`span`]: span/index.html -//! [`span` module]: span/index.html -//! [`in_scope`]: span/struct.Span.html#method.in_scope -//! [`Event`]: struct.Event.html -//! [`Subscriber`]: subscriber/trait.Subscriber.html -//! [`observe_event`]: subscriber/trait.Subscriber.html#tymethod.observe_event -//! [`enter`]: subscriber/trait.Subscriber.html#tymethod.enter -//! [`exit`]: subscriber/trait.Subscriber.html#tymethod.exit -//! [`enabled`]: subscriber/trait.Subscriber.html#tymethod.enabled -//! [metadata]: struct.Metadata.html -//! [`field::display`]: field/fn.display.html -//! [`field::debug`]: field/fn.debug.html -//! [`tokio-trace-nursery`]: https://github.com/tokio-rs/tokio-trace-nursery -//! [`tokio-trace-futures`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-futures -//! [`tokio-trace-fmt`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-fmt -//! [`tokio-trace-log`]: https://github.com/tokio-rs/tokio-trace-nursery/tree/master/tokio-trace-log -//! [static verbosity level]: level_filters/index.html#compile-time-filters -#[macro_use] -extern crate cfg_if; -extern crate tokio_trace_core; - -#[cfg(feature = "log")] -#[doc(hidden)] -pub extern crate log; - -// Somehow this `use` statement is necessary for us to re-export the `core` -// macros on Rust 1.26.0. I'm not sure how this makes it work, but it does. -#[allow(unused_imports)] -#[doc(hidden)] -use tokio_trace_core::*; - -pub use self::{ - dispatcher::Dispatch, - event::Event, - field::Value, - span::Span, - subscriber::Subscriber, - tokio_trace_core::{dispatcher, event, Level, Metadata}, -}; - -#[doc(hidden)] -pub use self::{ - span::Id, - tokio_trace_core::{ - callsite::{self, Callsite}, - metadata, - }, -}; - -#[macro_use] -mod macros; - -pub mod field; -pub mod level_filters; -pub mod span; -pub mod subscriber; - -mod sealed { - pub trait Sealed {} -} diff --git a/tokio-trace/src/macros.rs b/tokio-trace/src/macros.rs deleted file mode 100644 index 81af1dafc..000000000 --- a/tokio-trace/src/macros.rs +++ /dev/null @@ -1,2467 +0,0 @@ -/// Constructs a new span. -/// -/// # Examples -/// -/// Creating a new span: -/// ``` -/// #[macro_use] -/// extern crate tokio_trace; -/// use tokio_trace::Level; -/// # fn main() { -/// let span = span!(Level::TRACE, "my span"); -/// let _enter = span.enter(); -/// // do work inside the span... -/// # } -/// ``` -/// -/// ## Recording Fields -/// -/// Span fields are written using the syntax `key = value`. -/// ``` -/// # #[macro_use] extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// // construct a new span with two fields: -/// // - "foo", with a value of 42, -/// // - "bar", with the value "false" -/// let my_span = span!(Level::INFO, "my_span", foo = 42, bar = false); -/// # } -/// ``` -/// Note that a trailing comma on the final field is valid: -/// ``` -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// span!( -/// Level::INFO, -/// "my_span", -/// foo = 42, -/// bar = false, -/// ); -/// # } -/// ``` -/// -/// As shorthand, local variables may be used as field values without an -/// assignment, similar to [struct initializers]. For example: -/// ``` -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// let user = "ferris"; -/// -/// span!(Level::TRACE, "login", user); -/// // is equivalent to: -/// span!(Level::TRACE, "login", user = user); -/// # } -///``` -/// -/// Field names can include dots, but should not be terminated by them: -/// ``` -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// let user = "ferris"; -/// let email = "ferris@rust-lang.org"; -/// span!(Level::TRACE, "login", user, user.email = email); -/// # } -///``` -/// -/// Since field names can include dots, fields on local structs can be used -/// using the local variable shorthand: -/// ``` -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// # struct User { -/// # name: &'static str, -/// # email: &'static str, -/// # } -/// let user = User { -/// name: "ferris", -/// email: "ferris@rust-lang.org", -/// }; -/// // the span will have the fields `user.name = "ferris"` and -/// // `user.email = "ferris@rust-lang.org"`. -/// span!(Level::TRACE, "login", user.name, user.email); -/// # } -///``` -/// -// TODO(#1138): determine a new syntax for uninitialized span fields, and -// re-enable this. -// /// Field values may be recorded after the span is created. The `_` character is -// /// used to represent a field whose value has yet to be recorded: -// /// ``` -// /// # #[macro_use] -// /// # extern crate tokio_trace; -// /// # use tokio_trace::Level; -// /// # fn main() { -// /// let my_span = span!(Level::TRACE, "my span", foo = 2, bar = _); -// /// my_span.record("bar", &7); -// /// # } -// /// ``` -// /// -/// The `?` sigil is shorthand for [`field::debug`]: -/// ``` -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// #[derive(Debug)] -/// struct MyStruct { -/// field: &'static str, -/// } -/// -/// let my_struct = MyStruct { -/// field: "Hello world!" -/// }; -/// -/// // `my_struct` will be recorded using its `fmt::Debug` implementation. -/// span!(Level::TRACE, "my span", foo = ?my_struct); -/// // is equivalent to: -/// span!(Level::TRACE, "my span", foo = tokio_trace::field::debug(&my_struct)); -/// # } -/// ``` -/// -/// The `%` character is shorthand for [`field::display`]: -/// ``` -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// # #[derive(Debug)] -/// # struct MyStruct { -/// # field: &'static str, -/// # } -/// # -/// # let my_struct = MyStruct { -/// # field: "Hello world!" -/// # }; -/// // `my_struct.field` will be recorded using its `fmt::Display` implementation. -/// span!(Level::TRACE, "my span", foo = %my_struct.field); -/// // is equivalent to: -/// span!(Level::TRACE, "my span", foo = tokio_trace::field::display(&my_struct.field)); -/// # } -/// ``` -/// -/// The `%` and `?` sigils may also be used with local variable shorthand: -/// ``` -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// # #[derive(Debug)] -/// # struct MyStruct { -/// # field: &'static str, -/// # } -/// # -/// # let my_struct = MyStruct { -/// # field: "Hello world!" -/// # }; -/// // `my_struct.field` will be recorded using its `fmt::Display` implementation. -/// let my_span = span!(Level::TRACE, "my span", %my_struct.field); -/// # } -/// ``` -/// -/// Note that a span may have up to 32 fields. The following will not compile: -/// ```rust,compile_fail -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// span!( -/// Level::TRACE, -/// "too many fields!", -/// a = 1, b = 2, c = 3, d = 4, e = 5, f = 6, g = 7, h = 8, i = 9, -/// j = 10, k = 11, l = 12, m = 13, n = 14, o = 15, p = 16, q = 17, -/// r = 18, s = 19, t = 20, u = 21, v = 22, w = 23, x = 24, y = 25, -/// z = 26, aa = 27, bb = 28, cc = 29, dd = 30, ee = 31, ff = 32, gg = 33 -/// ); -/// # } -/// ``` -/// -/// ## Setting Span Attributes -/// -/// In addition to the level and name of the span, which are required, the -/// [target] and [parent span] may be overridden. For example: -/// -/// Creating a span with custom target: -/// ``` -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// span!(Level::TRACE, target: "app_span", "my span"); -/// # } -/// ``` -/// -/// Creating a span with an explicit parent: -/// ```rust -/// # #[macro_use] extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// // Create, but do not enter, a span called "foo". -/// let foo = span!(Level::INFO, "foo"); -/// -/// // Create and enter a span called "bar". -/// let bar = span!(Level::INFO, "bar"); -/// let _enter = bar.enter(); -/// -/// // Although we have currently entered "bar", "baz"'s parent span -/// // will be "foo". -/// let baz = span!(Level::INFO, parent: &foo, "baz"); -/// # } -/// ``` -/// -/// Creating a span _without_ a parent: -/// -///```rust -/// # #[macro_use] extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// let foo = span!(Level::INFO, "foo"); -/// let _enter = foo.enter(); -/// -/// // Although we have currently entered "foo", "bar" will be created -/// // as the root of its own trace tree: -/// let bar = span!(Level::INFO, parent: None, "bar"); -/// # } -/// ``` -/// -/// Both the parent and target may be overridden simultaenously: -/// -///```rust -/// # #[macro_use] extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// let foo = span!(Level::INFO, "foo"); -// -/// let bar = span!(Level::INFO, target: "bar_events", parent: &foo, "bar"); -/// # } -/// ``` -/// -/// By default, the module path to the current Rust module will be used -/// as the target, and the parent will be [determined contextually]. -/// -/// [struct initializers]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#using-the-field-init-shorthand-when-variables-and-fields-have-the-same-name -/// [target]: struct.Metadata.html#method.target -/// [parent span]: span/struct.Attributes.html#method.parent -/// [determined contextually]: span/struct.Attributes.html#method.is_contextual -/// [`field::debug`]: field/fn.display.html -/// [`field::display`]: field/fn.display.html -#[macro_export(local_inner_macros)] -macro_rules! span { - ($lvl:expr, target: $target:expr, parent: $parent:expr, $name:expr) => { - span!($lvl, target: $target, parent: $parent, $name,) - }; - ($lvl:expr, target: $target:expr, parent: $parent:expr, $name:expr, $($fields:tt)*) => { - { - use $crate::callsite; - use $crate::callsite::Callsite; - let callsite = callsite! { - name: $name, - kind: $crate::metadata::Kind::SPAN, - target: $target, - level: $lvl, - fields: $($fields)* - }; - let meta = callsite.metadata(); - - if $lvl <= $crate::level_filters::STATIC_MAX_LEVEL && is_enabled!(callsite) { - $crate::Span::child_of( - $parent, - meta, - &valueset!(meta.fields(), $($fields)*), - ) - } else { - __tokio_trace_disabled_span!( - meta, - &valueset!(meta.fields(), $($fields)*) - ) - } - } - }; - ($lvl:expr, target: $target:expr, $name:expr, $($fields:tt)*) => { - { - use $crate::callsite; - use $crate::callsite::Callsite; - let callsite = callsite! { - name: $name, - kind: $crate::metadata::Kind::SPAN, - target: $target, - level: $lvl, - fields: $($fields)* - }; - let meta = callsite.metadata(); - - if $lvl <= $crate::level_filters::STATIC_MAX_LEVEL && is_enabled!(callsite) { - $crate::Span::new( - meta, - &valueset!(meta.fields(), $($fields)*) - ) - } else { - __tokio_trace_disabled_span!( - meta, - &valueset!(meta.fields(), $($fields)*) - ) - } - } - - }; - ($lvl:expr, target: $target:expr, parent: $parent:expr, $name:expr) => { - span!($lvl, target: $target, parent: $parent, $name,) - }; - ($lvl:expr, parent: $parent:expr, $name:expr, $($fields:tt)*) => { - span!( - $lvl, - target: __tokio_trace_module_path!(), - parent: $parent, - $name, - $($fields)* - ) - }; - ($lvl:expr, parent: $parent:expr, $name:expr) => { - span!( - $lvl, - target: __tokio_trace_module_path!(), - parent: $parent, - $name, - ) - }; - ($lvl:expr, target: $target:expr, $name:expr, $($fields:tt)*) => { - span!( - $lvl, - target: $target, - $name, - $($fields)* - ) - }; - ($lvl:expr, target: $target:expr, $name:expr) => { - span!($lvl, target: $target, $name,) - }; - ($lvl:expr, $name:expr, $($fields:tt)*) => { - span!( - $lvl, - target: __tokio_trace_module_path!(), - $name, - $($fields)* - ) - }; - ($lvl:expr, $name:expr) => { - span!( - $lvl, - target: __tokio_trace_module_path!(), - $name, - ) - }; -} - -/// Constructs a span at the trace level. -/// -/// [Fields] and [attributes] are set using the same syntax as the [`span!`] -/// macro. -/// -/// [attributes]: macro.span.html#setting-span-attributes -/// [Fields]: macro.span.html#recording-fields -/// [`span!`]: macro.span.html -/// -/// # Examples -/// -/// ```rust -/// # #[macro_use] extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// trace_span!("my_span"); -/// // is equivalent to: -/// span!(Level::TRACE, "my_span"); -/// # } -/// ``` -/// -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # fn main() { -/// let span = trace_span!("my span"); -/// span.in_scope(|| { -/// // do work inside the span... -/// }); -/// # } -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! trace_span { - (target: $target:expr, parent: $parent:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::TRACE, - target: $target, - parent: $parent, - $name, - $($field)* - ) - }; - (target: $target:expr, parent: $parent:expr, $name:expr) => { - trace_span!(target: $target, parent: $parent, $name,) - }; - (parent: $parent:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::TRACE, - target: __tokio_trace_module_path!(), - parent: $parent, - $name, - $($field)* - ) - }; - (parent: $parent:expr, $name:expr) => { - trace_span!(parent: $parent, $name,) - }; - (target: $target:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::TRACE, - target: $target, - $name, - $($field)* - ) - }; - (target: $target:expr, $name:expr) => { - trace_span!(target: $target, $name,) - }; - ($name:expr, $($field:tt)*) => { - span!( - $crate::Level::TRACE, - target: __tokio_trace_module_path!(), - $name, - $($field)* - ) - }; - ($name:expr) => {trace_span!($name,)}; -} - -/// Constructs a span at the debug level. -/// -/// [Fields] and [attributes] are set using the same syntax as the [`span!`] -/// macro. -/// -/// [attributes]: macro.span.html#setting-span-attributes -/// [Fields]: macro.span.html#recording-fields -/// [`span!`]: macro.span.html -/// -/// # Examples -/// -/// ```rust -/// # #[macro_use] extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// debug_span!("my_span"); -/// // is equivalent to: -/// span!(Level::DEBUG, "my_span"); -/// # } -/// ``` -/// -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # fn main() { -/// let span = debug_span!("my span"); -/// span.in_scope(|| { -/// // do work inside the span... -/// }); -/// # } -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! debug_span { - (target: $target:expr, parent: $parent:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::DEBUG, - target: $target, - parent: $parent, - $name, - $($field)* - ) - }; - (target: $target:expr, parent: $parent:expr, $name:expr) => { - debug_span!(target: $target, parent: $parent, $name,) - }; - (parent: $parent:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::DEBUG, - target: __tokio_trace_module_path!(), - parent: $parent, - $name, - $($field)* - ) - }; - (parent: $parent:expr, $name:expr) => { - debug_span!(parent: $parent, $name,) - }; - (target: $target:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::DEBUG, - target: $target, - $name, - $($field)* - ) - }; - (target: $target:expr, $name:expr) => { - debug_span!(target: $target, $name,) - }; - ($name:expr, $($field:tt)*) => { - span!( - $crate::Level::DEBUG, - target: __tokio_trace_module_path!(), - $name, - $($field)* - ) - }; - ($name:expr) => {debug_span!($name,)}; -} - -/// Constructs a span at the info level. -/// -/// [Fields] and [attributes] are set using the same syntax as the [`span!`] -/// macro. -/// -/// [attributes]: macro.span.html#setting-span-attributes -/// [Fields]: macro.span.html#recording-fields -/// [`span!`]: macro.span.html -/// -/// # Examples -/// -/// ```rust -/// # #[macro_use] extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// info_span!("my_span"); -/// // is equivalent to: -/// span!(Level::INFO, "my_span"); -/// # } -/// ``` -/// -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # fn main() { -/// let span = info_span!("my span"); -/// span.in_scope(|| { -/// // do work inside the span... -/// }); -/// # } -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! info_span { - (target: $target:expr, parent: $parent:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::INFO, - target: $target, - parent: $parent, - $name, - $($field)* - ) - }; - (target: $target:expr, parent: $parent:expr, $name:expr) => { - info_span!(target: $target, parent: $parent, $name,) - }; - (parent: $parent:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::INFO, - target: __tokio_trace_module_path!(), - parent: $parent, - $name, - $($field)* - ) - }; - (parent: $parent:expr, $name:expr) => { - info_span!(parent: $parent, $name,) - }; - (target: $target:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::INFO, - target: $target, - $name, - $($field)* - ) - }; - (target: $target:expr, $name:expr) => { - info_span!(target: $target, $name,) - }; - ($name:expr, $($field:tt)*) => { - span!( - $crate::Level::INFO, - target: __tokio_trace_module_path!(), - $name, - $($field)* - ) - }; - ($name:expr) => {info_span!($name,)}; -} - -/// Constructs a span at the warn level. -/// -/// [Fields] and [attributes] are set using the same syntax as the [`span!`] -/// macro. -/// -/// [attributes]: macro.span.html#setting-span-attributes -/// [Fields]: macro.span.html#recording-fields -/// [`span!`]: macro.span.html -/// -/// # Examples -/// -/// ```rust -/// # #[macro_use] extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// info_span!("my_span"); -/// // is equivalent to: -/// span!(Level::INFO, "my_span"); -/// # } -/// ``` -/// -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # fn main() { -/// let span = warn_span!("my span"); -/// span.in_scope(|| { -/// // do work inside the span... -/// }); -/// # } -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! warn_span { - (target: $target:expr, parent: $parent:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::WARN, - target: $target, - parent: $parent, - $name, - $($field)* - ) - }; - (target: $target:expr, parent: $parent:expr, $name:expr) => { - warn_span!(target: $target, parent: $parent, $name,) - }; - (parent: $parent:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::WARN, - target: __tokio_trace_module_path!(), - parent: $parent, - $name, - $($field)* - ) - }; - (parent: $parent:expr, $name:expr) => { - warn_span!(parent: $parent, $name,) - }; - (target: $target:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::WARN, - target: $target, - $name, - $($field)* - ) - }; - (target: $target:expr, $name:expr) => { - warn_span!(target: $target, $name,) - }; - ($name:expr, $($field:tt)*) => { - span!( - $crate::Level::WARN, - target: __tokio_trace_module_path!(), - $name, - $($field)* - ) - }; - ($name:expr) => {warn_span!($name,)}; -} -/// Constructs a span at the error level. -/// -/// [Fields] and [attributes] are set using the same syntax as the [`span!`] -/// macro. -/// -/// [attributes]: macro.span.html#setting-span-attributes -/// [Fields]: macro.span.html#recording-fields -/// [`span!`]: macro.span.html -/// -/// # Examples -/// -/// ```rust -/// # #[macro_use] extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// error_span!("my_span"); -/// // is equivalent to: -/// span!(Level::ERROR, "my_span"); -/// # } -/// ``` -/// -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # fn main() { -/// let span = error_span!("my span"); -/// span.in_scope(|| { -/// // do work inside the span... -/// }); -/// # } -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! error_span { - (target: $target:expr, parent: $parent:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::ERROR, - target: $target, - parent: $parent, - $name, - $($field)* - ) - }; - (target: $target:expr, parent: $parent:expr, $name:expr) => { - error_span!(target: $target, parent: $parent, $name,) - }; - (parent: $parent:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::ERROR, - target: __tokio_trace_module_path!(), - parent: $parent, - $name, - $($field)* - ) - }; - (parent: $parent:expr, $name:expr) => { - error_span!(parent: $parent, $name,) - }; - (target: $target:expr, $name:expr, $($field:tt)*) => { - span!( - $crate::Level::ERROR, - target: $target, - $name, - $($field)* - ) - }; - (target: $target:expr, $name:expr) => { - error_span!(target: $target, $name,) - }; - ($name:expr, $($field:tt)*) => { - span!( - $crate::Level::ERROR, - target: __tokio_trace_module_path!(), - $name, - $($field)* - ) - }; - ($name:expr) => {error_span!($name,)}; -} - -/// Constructs a new `Event`. -/// -/// # Examples -/// -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace; -/// use tokio_trace::{Level, field}; -/// -/// # fn main() { -/// let data = (42, "fourty-two"); -/// let private_data = "private"; -/// let error = "a bad error"; -/// -/// event!(Level::ERROR, { error = field::display(error) }, "Received error"); -/// event!(target: "app_events", Level::WARN, { -/// private_data = private_data, -/// data = field::debug(data), -/// }, -/// "App warning: {}", error -/// ); -/// event!(Level::INFO, the_answer = data.0); -/// # } -/// ``` -/// -/// Note that *unlike `span!`*, `event!` requires a value for all fields. As -/// events are recorded immediately when the macro is invoked, there is no -/// opportunity for fields to be recorded later. A trailing comma on the final -/// field is valid. -/// -/// For example, the following does not compile: -/// ```rust,compile_fail -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// event!(Level::Info, foo = 5, bad_field, bar = "hello") -/// #} -/// ``` -/// Shorthand for `field::debug`: -/// ``` -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// #[derive(Debug)] -/// struct MyStruct { -/// field: &'static str, -/// } -/// -/// let my_struct = MyStruct { -/// field: "Hello world!" -/// }; -/// -/// // `my_struct` will be recorded using its `fmt::Debug` implementation. -/// event!(Level::TRACE, my_struct = ?my_struct); -/// # } -/// ``` -/// Shorthand for `field::display`: -/// ``` -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// # #[derive(Debug)] -/// # struct MyStruct { -/// # field: &'static str, -/// # } -/// # -/// # let my_struct = MyStruct { -/// # field: "Hello world!" -/// # }; -/// // `my_struct.field` will be recorded using its `fmt::Display` implementation. -/// event!(Level::TRACE, my_struct.field = %my_struct.field); -/// # } -/// ``` -/// Events may have up to 32 fields. The following will not compile: -/// ```rust,compile_fail -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use tokio_trace::Level; -/// # fn main() { -/// event!(Level::INFO, -/// a = 1, b = 2, c = 3, d = 4, e = 5, f = 6, g = 7, h = 8, i = 9, -/// j = 10, k = 11, l = 12, m = 13, n = 14, o = 15, p = 16, q = 17, -/// r = 18, s = 19, t = 20, u = 21, v = 22, w = 23, x = 24, y = 25, -/// z = 26, aa = 27, bb = 28, cc = 29, dd = 30, ee = 31, ff = 32, gg = 33 -/// ); -/// # } -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! event { - (target: $target:expr, $lvl:expr, parent: $parent:expr, { $($fields:tt)* } )=> ({ - { - __tokio_trace_log!( - target: $target, - $lvl, - $($fields)* - ); - - if $lvl <= $crate::level_filters::STATIC_MAX_LEVEL { - #[allow(unused_imports)] - use $crate::{callsite, dispatcher, Event, field::{Value, ValueSet}}; - use $crate::callsite::Callsite; - let callsite = callsite! { - name: __tokio_trace_concat!( - "event ", - __tokio_trace_file!(), - ":", - __tokio_trace_line!() - ), - kind: $crate::metadata::Kind::EVENT, - target: $target, - level: $lvl, - fields: $($fields)* - }; - if is_enabled!(callsite) { - let meta = callsite.metadata(); - Event::dispatch(meta, &valueset!(meta.fields(), $($fields)*) ); - } - } - } - }); - (target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ - { - __tokio_trace_log!( - target: $target, - $lvl, - $($fields)* - ); - - if $lvl <= $crate::level_filters::STATIC_MAX_LEVEL { - #[allow(unused_imports)] - use $crate::{callsite, dispatcher, Event, field::{Value, ValueSet}}; - use $crate::callsite::Callsite; - let callsite = callsite! { - name: __tokio_trace_concat!( - "event ", - __tokio_trace_file!(), - ":", - __tokio_trace_line!() - ), - kind: $crate::metadata::Kind::EVENT, - target: $target, - level: $lvl, - fields: $($fields)* - }; - if is_enabled!(callsite) { - let meta = callsite.metadata(); - Event::dispatch(meta, &valueset!(meta.fields(), $($fields)*) ); - } - } - } - }); - (target: $target:expr, $lvl:expr, parent: $parent:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ({ - event!( - target: $target, - $lvl, - parent: $parent, - { message = __tokio_trace_format_args!($($arg)+), $($fields)* } - ) - }); - (target: $target:expr, $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ({ - event!( - target: $target, - $lvl, - { message = __tokio_trace_format_args!($($arg)+), $($fields)* } - ) - }); - (target: $target:expr, $lvl:expr, parent: $parent:expr, $($k:ident).+ = $($fields:tt)* ) => ( - event!(target: $target, $lvl, parent: $parent, { $($k).+ = $($fields)* }) - ); - (target: $target:expr, $lvl:expr, $($k:ident).+ = $($fields:tt)* ) => ( - event!(target: $target, $lvl, { $($k).+ = $($fields)* }) - ); - (target: $target:expr, $lvl:expr, parent: $parent:expr, $($arg:tt)+ ) => ( - event!(target: $target, $lvl, parent: $parent, { }, $($arg)+) - ); - (target: $target:expr, $lvl:expr, $($arg:tt)+ ) => ( - event!(target: $target, $lvl, { }, $($arg)+) - ); - ( $lvl:expr, parent: $parent:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - parent: $parent, - { message = __tokio_trace_format_args!($($arg)+), $($fields)* } - ) - ); - ( $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - { message = __tokio_trace_format_args!($($arg)+), $($fields)* } - ) - ); - ( $lvl:expr, parent: $parent:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - parent: $parent, - { message = __tokio_trace_format_args!($($arg)+), $($fields)* } - ) - ); - ( $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - { message = __tokio_trace_format_args!($($arg)+), $($fields)* } - ) - ); - ( $lvl:expr, parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - parent: $parent, - { $($k).+ = $($field)*} - ) - ); - ($lvl:expr, $($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - { $($k).+ = $($field)*} - ) - ); - ($lvl:expr, parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - parent: $parent, - { ?$($k).+ = $($field)*} - ) - ); - ($lvl:expr, ?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - { ?$($k).+ = $($field)*} - ) - ); - ($lvl:expr, parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - parent: $parent, - { %$($k).+ = $($field)*} - ) - ); - ($lvl:expr, %$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - { %$($k).+ = $($field)*} - ) - ); - ($lvl:expr, parent: $parent:expr, $($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - parent: $parent, - { $($k).+, $($field)*} - ) - ); - ($lvl:expr, $($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - { $($k).+, $($field)*} - ) - ); - ($lvl:expr, parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - parent: $parent, - { ?$($k).+, $($field)*} - ) - ); - ($lvl:expr, ?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - { ?$($k).+, $($field)*} - ) - ); - ($lvl:expr, parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - parent: $parent, - { %$($k).+, $($field)*} - ) - ); - ($lvl:expr, %$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $lvl, - { %$($k).+, $($field)*} - ) - ); - ( $lvl:expr, parent: $parent:expr, $($arg:tt)+ ) => ( - event!(target: __tokio_trace_module_path!(), $lvl, parent: $parent, { }, $($arg)+) - ); - ( $lvl:expr, $($arg:tt)+ ) => ( - event!(target: __tokio_trace_module_path!(), $lvl, { }, $($arg)+) - ); -} - -/// Constructs an event at the trace level. -/// -/// When both a message and fields are included, curly braces (`{` and `}`) are -/// used to delimit the list of fields from the format string for the message. -/// A trailing comma on the final field is valid. -/// -/// # Examples -/// -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use std::time::SystemTime; -/// # #[derive(Debug, Copy, Clone)] struct Position { x: f32, y: f32 } -/// # impl Position { -/// # const ORIGIN: Self = Self { x: 0.0, y: 0.0 }; -/// # fn dist(&self, other: Position) -> f32 { -/// # let x = (other.x - self.x).exp2(); let y = (self.y - other.y).exp2(); -/// # (x + y).sqrt() -/// # } -/// # } -/// # fn main() { -/// use tokio_trace::field; -/// -/// let pos = Position { x: 3.234, y: -1.223 }; -/// let origin_dist = pos.dist(Position::ORIGIN); -/// -/// trace!(position = field::debug(pos), origin_dist = field::debug(origin_dist)); -/// trace!(target: "app_events", -/// { position = field::debug(pos) }, -/// "x is {} and y is {}", -/// if pos.x >= 0.0 { "positive" } else { "negative" }, -/// if pos.y >= 0.0 { "positive" } else { "negative" }); -/// # } -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! trace { - (target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( - event!(target: $target, $crate::Level::TRACE, parent: $parent, { $($field)* }, $($arg)*) - ); - (target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::TRACE, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::TRACE, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::TRACE, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( - event!(target: $target, $crate::Level::TRACE, parent: $parent, {}, $($arg)+) - ); - (parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - parent: $parent, - { $($field)+ }, - $($arg)+ - ) - ); - (parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - parent: $parent, - { $($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - parent: $parent, - { ?$($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - parent: $parent, - { %$($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, $($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - parent: $parent, - { $($k).+, $($field)*} - ) - ); - (parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - parent: $parent, - { ?$($k).+, $($field)*} - ) - ); - (parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - parent: $parent, - { %$($k).+, $($field)*} - ) - ); - (parent: $parent:expr, $($arg:tt)+) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - parent: $parent, - {}, - $($arg)+ - ) - ); - (target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( - event!(target: $target, $crate::Level::TRACE, { $($field)* }, $($arg)*) - ); - (target: $target:expr, $($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::TRACE, { $($k).+ $($field)+ }) - ); - (target: $target:expr, ?$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::TRACE, { $($k).+ $($field)+ }) - ); - (target: $target:expr, %$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::TRACE, { $($k).+ $($field)+ }) - ); - (target: $target:expr, $($arg:tt)+ ) => ( - event!(target: $target, $crate::Level::TRACE, {}, $($arg)+) - ); - ({ $($field:tt)+ }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - { $($field)+ }, - $($arg)+ - ) - ); - ($($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - { $($k).+ = $($field)*} - ) - ); - (?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - { ?$($k).+ = $($field)*} - ) - ); - (%$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - { %$($k).+ = $($field)*} - ) - ); - ($($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - { $($k).+, $($field)*} - ) - ); - (?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - { ?$($k).+, $($field)*} - ) - ); - (%$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - { %$($k).+, $($field)*} - ) - ); - ($($arg:tt)+) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::TRACE, - {}, - $($arg)+ - ) - ); -} - -/// Constructs an event at the debug level. -/// -/// When both a message and fields are included, curly braces (`{` and `}`) are -/// used to delimit the list of fields from the format string for the message. -/// A trailing comma on the final field is valid. -/// -/// # Examples -/// -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # fn main() { -/// # #[derive(Debug)] struct Position { x: f32, y: f32 } -/// use tokio_trace::field; -/// -/// let pos = Position { x: 3.234, y: -1.223 }; -/// -/// debug!(?pos.x, ?pos.y); -/// debug!(target: "app_events", { position = ?pos }, "New position"); -/// # } -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! debug { - (target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( - event!(target: $target, $crate::Level::INFO, parent: $parent, { $($field)* }, $($arg)*) - ); - (target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, parent: $parent, {}, $($arg)+) - ); - (parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { $($field)+ }, - $($arg)+ - ) - ); - (parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { $($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { ?$($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { %$($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, $($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { $($k).+, $($field)*} - ) - ); - (parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { ?$($k).+, $($field)*} - ) - ); - (parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { %$($k).+, $($field)*} - ) - ); - (parent: $parent:expr, $($arg:tt)+) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - {}, - $($arg)+ - ) - ); - (target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( - event!(target: $target, $crate::Level::DEBUG, { $($field)* }, $($arg)*) - ); - (target: $target:expr, $($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::DEBUG, { $($k).+ $($field)+ }) - ); - (target: $target:expr, ?$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::DEBUG, { $($k).+ $($field)+ }) - ); - (target: $target:expr, %$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::DEBUG, { $($k).+ $($field)+ }) - ); - (target: $target:expr, $($arg:tt)+ ) => ( - event!(target: $target, $crate::Level::DEBUG, {}, $($arg)+) - ); - ({ $($field:tt)+ }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::DEBUG, - { $($field)+ }, - $($arg)+ - ) - ); - ($($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::DEBUG, - { $($k).+ = $($field)*} - ) - ); - (?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::DEBUG, - { ?$($k).+ = $($field)*} - ) - ); - (%$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::DEBUG, - { %$($k).+ = $($field)*} - ) - ); - ($($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::DEBUG, - { $($k).+, $($field)*} - ) - ); - (?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::DEBUG, - { ?$($k).+, $($field)*} - ) - ); - (%$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::DEBUG, - { %$($k).+, $($field)*} - ) - ); - ($($arg:tt)+) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::DEBUG, - {}, - $($arg)+ - ) - ); -} - -/// Constructs an event at the info level. -/// -/// When both a message and fields are included, curly braces (`{` and `}`) are -/// used to delimit the list of fields from the format string for the message. -/// A trailing comma on the final field is valid. -/// -/// # Examples -/// -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # use std::net::Ipv4Addr; -/// # fn main() { -/// # struct Connection { port: u32, speed: f32 } -/// use tokio_trace::field; -/// -/// let addr = Ipv4Addr::new(127, 0, 0, 1); -/// let conn = Connection { port: 40, speed: 3.20 }; -/// -/// info!({ port = conn.port }, "connected to {}", addr); -/// info!( -/// target: "connection_events", -/// ip = %addr, -/// conn.port, -/// ?conn.speed, -/// ); -/// # } -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! info { - (target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( - event!(target: $target, $crate::Level::INFO, parent: $parent, { $($field)* }, $($arg)*) - ); - (target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, parent: $parent, {}, $($arg)+) - ); - (parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { $($field)+ }, - $($arg)+ - ) - ); - (parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { $($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { ?$($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { %$($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, $($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { $($k).+, $($field)*} - ) - ); - (parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { ?$($k).+, $($field)*} - ) - ); - (parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - { %$($k).+, $($field)*} - ) - ); - (parent: $parent:expr, $($arg:tt)+) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - parent: $parent, - {}, - $($arg)+ - ) - ); - (target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( - event!(target: $target, $crate::Level::INFO, { $($field)* }, $($arg)*) - ); - (target: $target:expr, $($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, { $($k).+ $($field)+ }) - ); - (target: $target:expr, ?$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, { $($k).+ $($field)+ }) - ); - (target: $target:expr, %$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, { $($k).+ $($field)+ }) - ); - (target: $target:expr, $($arg:tt)+ ) => ( - event!(target: $target, $crate::Level::INFO, {}, $($arg)+) - ); - ({ $($field:tt)+ }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - { $($field)+ }, - $($arg)+ - ) - ); - ($($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - { $($k).+ = $($field)*} - ) - ); - (?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - { ?$($k).+ = $($field)*} - ) - ); - (%$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - { %$($k).+ = $($field)*} - ) - ); - ($($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - { $($k).+, $($field)*} - ) - ); - (?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - { ?$($k).+, $($field)*} - ) - ); - (%$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - { %$($k).+, $($field)*} - ) - ); - ($($arg:tt)+) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::INFO, - {}, - $($arg)+ - ) - ); -} - -/// Constructs an event at the warn level. -/// -/// When both a message and fields are included, curly braces (`{` and `}`) are -/// used to delimit the list of fields from the format string for the message. -/// A trailing comma on the final field is valid. -/// -/// # Examples -/// -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # fn main() { -/// use tokio_trace::field; -/// -/// let warn_description = "Invalid Input"; -/// let input = &[0x27, 0x45]; -/// -/// warn!(input = field::debug(input), warning = warn_description); -/// warn!( -/// target: "input_events", -/// { warning = warn_description }, -/// "Received warning for input: {:?}", input, -/// ); -/// # } -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! warn { - (target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( - event!(target: $target, $crate::Level::WARN, parent: $parent, { $($field)* }, $($arg)*) - ); - (target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::WARN, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::WARN, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::WARN, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( - event!(target: $target, $crate::Level::WARN, parent: $parent, {}, $($arg)+) - ); - (parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - parent: $parent, - { $($field)+ }, - $($arg)+ - ) - ); - (parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - parent: $parent, - { $($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - parent: $parent, - { ?$($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - parent: $parent, - { %$($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, $($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - parent: $parent, - { $($k).+, $($field)*} - ) - ); - (parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - parent: $parent, - { ?$($k).+, $($field)*} - ) - ); - (parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - parent: $parent, - { %$($k).+, $($field)*} - ) - ); - (parent: $parent:expr, $($arg:tt)+) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - parent: $parent, - {}, - $($arg)+ - ) - ); - (target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( - event!(target: $target, $crate::Level::WARN, { $($field)* }, $($arg)*) - ); - (target: $target:expr, $($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::WARN, { $($k).+ $($field)+ }) - ); - (target: $target:expr, ?$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::WARN, { $($k).+ $($field)+ }) - ); - (target: $target:expr, %$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::WARN, { $($k).+ $($field)+ }) - ); - (target: $target:expr, $($arg:tt)+ ) => ( - event!(target: $target, $crate::Level::WARN, {}, $($arg)+) - ); - ({ $($field:tt)+ }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - { $($field)+ }, - $($arg)+ - ) - ); - ($($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - { $($k).+ = $($field)*} - ) - ); - (?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - { ?$($k).+ = $($field)*} - ) - ); - (%$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - { %$($k).+ = $($field)*} - ) - ); - ($($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - { $($k).+, $($field)*} - ) - ); - (?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - { ?$($k).+, $($field)*} - ) - ); - (%$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - { %$($k).+, $($field)*} - ) - ); - ($($arg:tt)+) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::WARN, - {}, - $($arg)+ - ) - ); -} - -/// Constructs an event at the error level. -/// -/// When both a message and fields are included, curly braces (`{` and `}`) are -/// used to delimit the list of fields from the format string for the message. -/// A trailing comma on the final field is valid. -/// -/// # Examples -/// -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace; -/// # fn main() { -/// use tokio_trace::field; -/// let (err_info, port) = ("No connection", 22); -/// -/// error!(port = port, error = field::display(err_info)); -/// error!(target: "app_events", "App Error: {}", err_info); -/// error!({ info = err_info }, "error on port: {}", port); -/// # } -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! error { - (target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( - event!(target: $target, $crate::Level::ERROR, parent: $parent, { $($field)* }, $($arg)*) - ); - (target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::ERROR, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::ERROR, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::ERROR, parent: $parent, { $($k).+ $($field)+ }) - ); - (target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( - event!(target: $target, $crate::Level::ERROR, parent: $parent, {}, $($arg)+) - ); - (parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - parent: $parent, - { $($field)+ }, - $($arg)+ - ) - ); - (parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - parent: $parent, - { $($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - parent: $parent, - { ?$($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - parent: $parent, - { %$($k).+ = $($field)*} - ) - ); - (parent: $parent:expr, $($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - parent: $parent, - { $($k).+, $($field)*} - ) - ); - (parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - parent: $parent, - { ?$($k).+, $($field)*} - ) - ); - (parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - parent: $parent, - { %$($k).+, $($field)*} - ) - ); - (parent: $parent:expr, $($arg:tt)+) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - parent: $parent, - {}, - $($arg)+ - ) - ); - (target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( - event!(target: $target, $crate::Level::ERROR, { $($field)* }, $($arg)*) - ); - (target: $target:expr, $($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::ERROR, { $($k).+ $($field)+ }) - ); - (target: $target:expr, ?$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::ERROR, { $($k).+ $($field)+ }) - ); - (target: $target:expr, %$($k:ident).+ $($field:tt)+ ) => ( - event!(target: $target, $crate::Level::ERROR, { $($k).+ $($field)+ }) - ); - (target: $target:expr, $($arg:tt)+ ) => ( - event!(target: $target, $crate::Level::ERROR, {}, $($arg)+) - ); - ({ $($field:tt)+ }, $($arg:tt)+ ) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - { $($field)+ }, - $($arg)+ - ) - ); - ($($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - { $($k).+ = $($field)*} - ) - ); - (?$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - { ?$($k).+ = $($field)*} - ) - ); - (%$($k:ident).+ = $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - { %$($k).+ = $($field)*} - ) - ); - ($($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - { $($k).+, $($field)*} - ) - ); - (?$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - { ?$($k).+, $($field)*} - ) - ); - (%$($k:ident).+, $($field:tt)*) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - { %$($k).+, $($field)*} - ) - ); - ($($arg:tt)+) => ( - event!( - target: __tokio_trace_module_path!(), - $crate::Level::ERROR, - {}, - $($arg)+ - ) - ); -} - -/// Constructs a new static callsite for a span or event. -#[doc(hidden)] -#[macro_export(local_inner_macros)] -macro_rules! callsite { - (name: $name:expr, kind: $kind:expr, fields: $($fields:tt)*) => {{ - callsite! { - name: $name, - kind: $kind, - target: __tokio_trace_module_path!(), - level: $crate::Level::TRACE, - fields: $($fields)* - } - }}; - ( - name: $name:expr, - kind: $kind:expr, - level: $lvl:expr, - fields: $($fields:tt)* - ) => {{ - callsite! { - name: $name, - kind: $kind, - target: __tokio_trace_module_path!(), - level: $lvl, - fields: $($fields)* - } - }}; - ( - name: $name:expr, - kind: $kind:expr, - target: $target:expr, - level: $lvl:expr, - fields: $($fields:tt)* - ) => {{ - use std::sync::{ - atomic::{self, AtomicUsize, Ordering}, - Once, - }; - use $crate::{callsite, subscriber::Interest, Metadata}; - struct MyCallsite; - static META: Metadata<'static> = { - metadata! { - name: $name, - target: $target, - level: $lvl, - fields: fieldset!( $($fields)* ), - callsite: &MyCallsite, - kind: $kind, - } - }; - // FIXME: Rust 1.34 deprecated ATOMIC_USIZE_INIT. When Tokio's minimum - // supported version is 1.34, replace this with the const fn `::new`. - #[allow(deprecated)] - static INTEREST: AtomicUsize = atomic::ATOMIC_USIZE_INIT; - static REGISTRATION: Once = Once::new(); - impl MyCallsite { - #[inline] - fn interest(&self) -> Interest { - match INTEREST.load(Ordering::Relaxed) { - 0 => Interest::never(), - 2 => Interest::always(), - _ => Interest::sometimes(), - } - } - } - impl callsite::Callsite for MyCallsite { - fn set_interest(&self, interest: Interest) { - let interest = match () { - _ if interest.is_never() => 0, - _ if interest.is_always() => 2, - _ => 1, - }; - INTEREST.store(interest, Ordering::SeqCst); - } - - fn metadata(&self) -> &Metadata { - &META - } - } - REGISTRATION.call_once(|| { - callsite::register(&MyCallsite); - }); - &MyCallsite - }}; -} - -#[macro_export] -// TODO: determine if this ought to be public API? -#[doc(hidden)] -macro_rules! is_enabled { - ($callsite:expr) => {{ - let interest = $callsite.interest(); - if interest.is_never() { - false - } else if interest.is_always() { - true - } else { - let meta = $callsite.metadata(); - $crate::dispatcher::get_default(|current| current.enabled(meta)) - } - }}; -} - -#[doc(hidden)] -#[macro_export(local_inner_macros)] -macro_rules! valueset { - - // === base case === - (@ { $($val:expr),* }, $next:expr, $(,)*) => { - &[ $($val),* ] - }; - - // === recursive case (more tts), non-empty out set === - - // TODO(#1138): determine a new syntax for uninitialized span fields, and - // re-enable this. - // (@{ $($out:expr),+ }, $next:expr, $($k:ident).+ = _, $($rest:tt)*) => { - // valueset!(@ { $($out),+, (&$next, None) }, $next, $($rest)*) - // }; - (@ { $($out:expr),+ }, $next:expr, $($k:ident).+ = ?$val:expr, $($rest:tt)*) => { - valueset!( - @ { $($out),+, (&$next, Some(&debug(&$val) as &Value)) }, - $next, - $($rest)* - ) - }; - (@ { $($out:expr),+ }, $next:expr, $($k:ident).+ = %$val:expr, $($rest:tt)*) => { - valueset!( - @ { $($out),+, (&$next, Some(&display(&$val) as &Value)) }, - $next, - $($rest)* - ) - }; - (@ { $($out:expr),+ }, $next:expr, $($k:ident).+ = $val:expr, $($rest:tt)*) => { - valueset!( - @ { $($out),+, (&$next, Some(&$val as &Value)) }, - $next, - $($rest)* - ) - }; - (@ { $($out:expr),+ }, $next:expr, $($k:ident).+, $($rest:tt)*) => { - valueset!( - @ { $($out),+, (&$next, Some(&$($k).+ as &Value)) }, - $next, - $($rest)* - ) - }; - (@ { $($out:expr),+ }, $next:expr, ?$($k:ident).+, $($rest:tt)*) => { - valueset!( - @ { $($out),+, (&$next, Some(&debug(&$($k).+) as &Value)) }, - $next, - $($rest)* - ) - }; - (@ { $($out:expr),+ }, $next:expr, %$($k:ident).+, $($rest:tt)*) => { - valueset!( - @ { $($out),+, (&$next, Some(&display(&$($k).+) as &Value)) }, - $next, - $($rest)* - ) - }; - - // == recursive case (more tts), empty out set === - - // TODO(#1138): determine a new syntax for uninitialized span fields, and - // re-enable this. - // (@ { }, $next:expr, $($k:ident).+ = _, $($rest:tt)* ) => { - // valueset!(@ { (&$next, None) }, $next, $($rest)* ) - // }; - (@ { }, $next:expr, $($k:ident).+ = ?$val:expr, $($rest:tt)* ) => { - valueset!(@ { (&$next, Some(&debug(&$val) as &Value)) }, $next, $($rest)* ) - }; - (@ { }, $next:expr, $($k:ident).+ = %$val:expr, $($rest:tt)*) => { - valueset!(@ { (&$next, Some(&display(&$val) as &Value)) }, $next, $($rest)*) - }; - (@ { }, $next:expr, $($k:ident).+ = $val:expr, $($rest:tt)*) => { - valueset!(@ { (&$next, Some(&$val as &Value)) }, $next, $($rest)*) - }; - (@ { }, $next:expr, $($k:ident).+, $($rest:tt)*) => { - valueset!(@ { (&$next, Some(&$($k).+ as &Value)) }, $next, $($rest)* ) - }; - (@ { }, $next:expr, ?$($k:ident).+, $($rest:tt)*) => { - valueset!(@ { (&$next, Some(&debug(&$($k).+) as &Value)) }, $next, $($rest)* ) - }; - (@ { }, $next:expr, %$($k:ident).+, $($rest:tt)*) => { - valueset!(@ { (&$next, Some(&display(&$($k).+) as &Value)) }, $next, $($rest)* ) - }; - - // === entry === - ($fields:expr, $($kvs:tt)+) => { - { - #[allow(unused_imports)] - use $crate::field::{debug, display, Value}; - let mut iter = $fields.iter(); - $fields.value_set(valueset!( - @ { }, - iter.next().expect("FieldSet corrupted (this is a bug)"), - $($kvs)+, - )) - } - }; - ($fields:expr,) => { - { - $fields.value_set(&[]) - } - }; -} - -#[doc(hidden)] -#[macro_export(local_inner_macros)] -macro_rules! fieldset { - // == base case == - (@ { $($out:expr),* $(,)* } $(,)*) => { - &[ $($out),* ] - }; - - // == empty out set, remaining tts == - (@ { } $($k:ident).+ = ?$val:expr, $($rest:tt)*) => { - fieldset!(@ { __tokio_trace_stringify!($($k).+) } $($rest)*) - }; - (@ { } $($k:ident).+ = %$val:expr, $($rest:tt)*) => { - fieldset!(@ { __tokio_trace_stringify!($($k).+) } $($rest)*) - }; - (@ { } $($k:ident).+ = $val:expr, $($rest:tt)*) => { - fieldset!(@ { __tokio_trace_stringify!($($k).+) } $($rest)*) - }; - // TODO(#1138): determine a new syntax for uninitialized span fields, and - // re-enable this. - // (@ { } $($k:ident).+ = _, $($rest:tt)*) => { - // fieldset!(@ { __tokio_trace_stringify!($($k).+) } $($rest)*) - // }; - (@ { } ?$($k:ident).+, $($rest:tt)*) => { - fieldset!(@ { __tokio_trace_stringify!($($k).+) } $($rest)*) - }; - (@ { } %$($k:ident).+, $($rest:tt)*) => { - fieldset!(@ { __tokio_trace_stringify!($($k).+) } $($rest)*) - }; - (@ { } $($k:ident).+, $($rest:tt)*) => { - fieldset!(@ { __tokio_trace_stringify!($($k).+) } $($rest)*) - }; - - - // == non-empty out set, remaining tts == - (@ { $($out:expr),+ } $($k:ident).+ = ?$val:expr, $($rest:tt)*) => { - fieldset!(@ { $($out),+,__tokio_trace_stringify!($($k).+) } $($rest)*) - }; - (@ { $($out:expr),+ } $($k:ident).+ = %$val:expr, $($rest:tt)*) => { - fieldset!(@ { $($out),+, __tokio_trace_stringify!($($k).+) } $($rest)*) - }; - (@ { $($out:expr),+ } $($k:ident).+ = $val:expr, $($rest:tt)*) => { - fieldset!(@ { $($out),+, __tokio_trace_stringify!($($k).+) } $($rest)*) - }; - // TODO(#1138): determine a new syntax for uninitialized span fields, and - // re-enable this. - // (@ { $($out:expr),+ } $($k:ident).+ = _, $($rest:tt)*) => { - // fieldset!(@ { $($out),+, __tokio_trace_stringify!($($k).+) } $($rest)*) - // }; - (@ { $($out:expr),+ } ?$($k:ident).+, $($rest:tt)*) => { - fieldset!(@ { $($out),+, __tokio_trace_stringify!($($k).+) } $($rest)*) - }; - (@ { $($out:expr),+ } %$($k:ident).+, $($rest:tt)*) => { - fieldset!(@ { $($out),+, __tokio_trace_stringify!($($k).+) } $($rest)*) - }; - (@ { $($out:expr),+ } $($k:ident).+, $($rest:tt)*) => { - fieldset!(@ { $($out),+, __tokio_trace_stringify!($($k).+) } $($rest)*) - }; - - // == entry == - ($($args:tt)*) => { - fieldset!(@ { } $($args)*, ) - }; - -} - -// The macros above cannot invoke format_args directly because they use -// local_inner_macros. A format_args invocation there would resolve to -// $crate::format_args, which does not exist. Instead invoke format_args here -// outside of local_inner_macros so that it resolves (probably) to -// core::format_args or std::format_args. Same for the several macros that -// follow. -// -// This is a workaround until we drop support for pre-1.30 compilers. At that -// point we can remove use of local_inner_macros, use $crate:: when invoking -// local macros, and invoke format_args directly. -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_format_args { - ($($args:tt)*) => { - format_args!($($args)*) - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_module_path { - () => { - module_path!() - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_file { - () => { - file!() - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_line { - () => { - line!() - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_concat { - ($($e:expr),*) => { - concat!($($e),*) - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_stringify { - ($s:expr) => { - stringify!($s) - }; -} - -#[cfg(feature = "log")] -#[doc(hidden)] -#[macro_export] -macro_rules! level_to_log { - ($level:expr) => { - match $level { - $crate::Level::ERROR => $crate::log::Level::Error, - $crate::Level::WARN => $crate::log::Level::Warn, - $crate::Level::INFO => $crate::log::Level::Info, - $crate::Level::DEBUG => $crate::log::Level::Debug, - _ => $crate::log::Level::Trace, - } - }; -} - -#[cfg(feature = "log")] -#[doc(hidden)] -#[macro_export(local_inner_macros)] -macro_rules! __tokio_trace_log { - (target: $target:expr, $level:expr, $($field:tt)+ ) => { - use $crate::log; - let level = level_to_log!($level); - if level <= log::STATIC_MAX_LEVEL { - let log_meta = log::Metadata::builder() - .level(level) - .target($target) - .build(); - let logger = log::logger(); - if logger.enabled(&log_meta) { - logger.log(&log::Record::builder() - .file(Some(__tokio_trace_file!())) - .module_path(Some(__tokio_trace_module_path!())) - .line(Some(__tokio_trace_line!())) - .metadata(log_meta) - .args(__mk_format_args!($($field)+)) - .build()); - } - } - }; -} - -#[cfg(not(feature = "log"))] -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_log { - (target: $target:expr, $level:expr, $($field:tt)+ ) => {}; -} - -#[cfg(feature = "log")] -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_disabled_span { - ($meta:expr, $valueset:expr) => {{ - let span = $crate::Span::new_disabled($meta); - span.record_all(&$valueset); - span - }}; -} - -#[cfg(not(feature = "log"))] -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_disabled_span { - ($meta:expr, $valueset:expr) => { - $crate::Span::new_disabled($meta) - }; -} - -#[cfg(feature = "log")] -#[doc(hidden)] -#[macro_export(local_inner_macros)] -macro_rules! __mk_format_string { - // === base case === - (@ { $($out:expr),+ } $(,)*) => { - __tokio_trace_concat!( $($out),+) - }; - - // === recursive case (more tts), non-empty out set === - (@ { $($out:expr),+ }, message = $val:expr, $($rest:tt)*) => { - __mk_format_string!(@ { $($out),+, "{} " }, $($rest)*) - }; - (@ { $($out:expr),+ }, $($k:ident).+ = ?$val:expr, $($rest:tt)*) => { - __mk_format_string!(@ { $($out),+, __tokio_trace_stringify!($($k).+), "={:?} " }, $($rest)*) - }; - (@ { $($out:expr),+ }, $($k:ident).+ = %$val:expr, $($rest:tt)*) => { - __mk_format_string!(@ { $($out),+, __tokio_trace_stringify!($($k).+), "={} " }, $($rest)*) - }; - (@ { $($out:expr),+ }, $($k:ident).+ = $val:expr, $($rest:tt)*) => { - __mk_format_string!(@ { $($out),+, __tokio_trace_stringify!($($k).+), "={:?} " }, $($rest)*) - }; - - // === recursive case (more tts), empty out set === - (@ { }, message = $val:expr, $($rest:tt)*) => { - __mk_format_string!(@ { "{} " }, $($rest)*) - }; - (@ { }, $($k:ident).+ = ?$val:expr, $($rest:tt)*) => { - __mk_format_string!(@ { __tokio_trace_stringify!($($k).+), "={:?} " }, $($rest)*) - }; - (@ { }, $($k:ident).+ = %$val:expr, $($rest:tt)*) => { - __mk_format_string!(@ { __tokio_trace_stringify!($($k).+), "={} " }, $($rest)*) - }; - (@ { }, $($k:ident).+ = $val:expr, $($rest:tt)*) => { - __mk_format_string!(@ { __tokio_trace_stringify!($($k).+), "={:?} " }, $($rest)*) - }; - - // === entry === - ($($kvs:tt)+) => { - __mk_format_string!(@ { }, $($kvs)+,) - }; - () => { - "" - } -} - -#[cfg(feature = "log")] -#[doc(hidden)] -#[macro_export(local_inner_macros)] -macro_rules! __mk_format_args { - // == base case == - (@ { $($out:expr),* }, $fmt:expr, $(,)*) => { - __tokio_trace_format_args!($fmt, $($out),*) - }; - - // === recursive case (more tts), non-empty out set === - (@ { $($out:expr),+ }, $fmt:expr, $($k:ident).+ = ?$val:expr, $($rest:tt)*) => { - __mk_format_args!(@ { $($out),+, $val }, $fmt, $($rest)*) - }; - (@ { $($out:expr),+ }, $fmt:expr, $($k:ident).+ = %$val:expr, $($rest:tt)*) => { - __mk_format_args!(@ { $($out),+, $val }, $fmt, $($rest)*) - }; - (@ { $($out:expr),+ }, $fmt:expr, $($k:ident).+ = $val:expr, $($rest:tt)*) => { - __mk_format_args!(@ { $($out),+, $val }, $fmt, $($rest)*) - }; - - // == recursive case (more tts), empty out set === - (@ { }, $fmt:expr, message = $val:expr, $($rest:tt)*) => { - __mk_format_args!(@ { $val }, $fmt, $($rest)*) - }; - (@ { }, $fmt:expr, $($k:ident).+ = ?$val:expr, $($rest:tt)*) => { - __mk_format_args!(@ { $val }, $fmt, $($rest)*) - }; - (@ { }, $fmt:expr, $($k:ident).+ = %$val:expr, $($rest:tt)*) => { - __mk_format_args!(@ { $val }, $fmt, $($rest)*) - }; - (@ { }, $fmt:expr, $($k:ident).+ = $val:expr, $($rest:tt)*) => { - __mk_format_args!(@ { $val }, $fmt, $($rest)*) - }; - - // === entry === - ($($kv:tt)*) => { - __mk_format_args!(@ { }, __mk_format_string!($($kv)*), $($kv)*,) - }; -} diff --git a/tokio-trace/src/span.rs b/tokio-trace/src/span.rs deleted file mode 100644 index 242d30abf..000000000 --- a/tokio-trace/src/span.rs +++ /dev/null @@ -1,858 +0,0 @@ -//! Spans represent periods of time in which a program was executing in a -//! particular context. -//! -//! A span consists of [fields], user-defined key-value pairs of arbitrary data -//! that describe the context the span represents, and [metadata], a fixed set -//! of attributes that describe all `tokio-trace` spans and events. Each span is -//! assigned an [`Id` ] by the subscriber that uniquely identifies it in relation -//! to other spans. -//! -//! # Creating Spans -//! -//! Spans are created using the [`span!`] macro. This macro is invoked with a -//! [verbosity level], followed by a set of attributes whose default values -//! the user whishes to override, a string literal providing the span's name, -//! and finally, between zero and 32 fields. -//! -//! For example: -//! ```rust -//! #[macro_use] -//! extern crate tokio_trace; -//! use tokio_trace::Level; -//! -//! # fn main() { -//! /// Construct a new span at the `INFO` level named "my_span", with a single -//! /// field named answer , with the value `42`. -//! let my_span = span!(Level::INFO, "my_span", answer = 42); -//! # } -//! ``` -//! -//! The documentation for the [`span!`] macro provides additional examples of -//! the various options that exist when creating spans. -//! -//! The [`trace_span!`], [`debug_span!`], [`info_span!`], [`warn_span!`], and -//! [`error_span!`] exist as shorthand for constructing spans at various -//! verbosity levels. -//! -//! ## Recording Span Creation -//! -//! The [`Attributes`] type contains data associated with a span, and is -//! provided to the [`Subscriber`] when a new span is created. It contains -//! the span's metadata, the ID of the span's parent if one was explicitly set, -//! and any fields whose values were recorded when the span was constructed. -//! The subscriber may then choose to cache the data for future use, record -//! it in some manner, or discard it completely. -//! -//! # The Span Lifecycle -//! -//! ## Entering a Span -//! -//! A thread of execution is said to _enter_ a span when it begins executing, -//! and _exit_ the span when it switches to another context. Spans may be -//! entered through the [`enter`] and [`in_scope`] methods. -//! -//! The `enter` method enters a span, returning a [guard] that exits the span -//! when dropped -//! ``` -//! # #[macro_use] extern crate tokio_trace; -//! # use tokio_trace::Level; -//! # fn main() { -//! let my_var: u64 = 5; -//! let my_span = span!(Level::TRACE, "my_span", my_var); -//! -//! // `my_span` exists but has not been entered. -//! -//! // Enter `my_span`... -//! let _enter = my_span.enter(); -//! -//! // Perform some work inside of the context of `my_span`... -//! // Dropping the `_enter` guard will exit the span. -//! # } -//!``` -//! -//! `in_scope` takes a closure or function pointer and executes it inside the -//! span. -//! ``` -//! # #[macro_use] extern crate tokio_trace; -//! # use tokio_trace::Level; -//! # fn main() { -//! let my_var: u64 = 5; -//! let my_span = span!(Level::TRACE, "my_span", my_var = &my_var); -//! -//! my_span.in_scope(|| { -//! // perform some work in the context of `my_span`... -//! }); -//! -//! // Perform some work outside of the context of `my_span`... -//! -//! my_span.in_scope(|| { -//! // Perform some more work in the context of `my_span`. -//! }); -//! # } -//! ``` -//! -//! **Note:** Since entering a span takes `&self`, and `Span`s are `Clone`, -//! `Send`, and `Sync`, it is entirely valid for multiple threads to enter the -//! same span concurrently. -//! -//! ## Span Relationships -//! -//! Spans form a tree structure — unless it is a root span, all spans have a -//! _parent_, and may have one or more _children_. When a new span is created, -//! the current span becomes the new span's parent. The total execution time of -//! a span consists of the time spent in that span and in the entire subtree -//! represented by its children. Thus, a parent span always lasts for at least -//! as long as the longest-executing span in its subtree. -//! -//! ``` -//! # #[macro_use] extern crate tokio_trace; -//! # use tokio_trace::Level; -//! # fn main() { -//! // this span is considered the "root" of a new trace tree: -//! span!(Level::INFO, "root").in_scope(|| { -//! // since we are now inside "root", this span is considered a child -//! // of "root": -//! span!(Level::DEBUG, "outer_child").in_scope(|| { -//! // this span is a child of "outer_child", which is in turn a -//! // child of "root": -//! span!(Level::TRACE, "inner_child").in_scope(|| { -//! // and so on... -//! }); -//! }); -//! // another span created here would also be a child of "root". -//! }); -//! # } -//!``` -//! -//! In addition, the parent of a span may be explicitly specified in -//! the `span!` macro. For example: -//! -//! ```rust -//! # #[macro_use] extern crate tokio_trace; -//! # use tokio_trace::Level; -//! # fn main() { -//! // Create, but do not enter, a span called "foo". -//! let foo = span!(Level::INFO, "foo"); -//! -//! // Create and enter a span called "bar". -//! let bar = span!(Level::INFO, "bar"); -//! let _enter = bar.enter(); -//! -//! // Although we have currently entered "bar", "baz"'s parent span -//! // will be "foo". -//! let baz = span!(Level::INFO, parent: &foo, "baz"); -//! # } -//! ``` -//! -//! A child span should typically be considered _part_ of its parent. For -//! example, if a subscriber is recording the length of time spent in various -//! spans, it should generally include the time spent in a span's children as -//! part of that span's duration. -//! -//! In addition to having zero or one parent, a span may also _follow from_ any -//! number of other spans. This indicates a causal relationship between the span -//! and the spans that it follows from, but a follower is *not* typically -//! considered part of the duration of the span it follows. Unlike the parent, a -//! span may record that it follows from another span after it is created, using -//! the [`follows_from`] method. -//! -//! As an example, consider a listener task in a server. As the listener accepts -//! incoming connections, it spawns new tasks that handle those connections. We -//! might want to have a span representing the listener, and instrument each -//! spawned handler task with its own span. We would want our instrumentation to -//! record that the handler tasks were spawned as a result of the listener task. -//! However, we might not consider the handler tasks to be _part_ of the time -//! spent in the listener task, so we would not consider those spans children of -//! the listener span. Instead, we would record that the handler tasks follow -//! from the listener, recording the causal relationship but treating the spans -//! as separate durations. -//! -//! ## Closing Spans -//! -//! Execution may enter and exit a span multiple times before that span is -//! _closed_. Consider, for example, a future which has an associated -//! span and enters that span every time it is polled: -//! ```rust -//! # extern crate tokio_trace; -//! # extern crate futures; -//! # use futures::{Future, Poll, Async}; -//! struct MyFuture { -//! // data -//! span: tokio_trace::Span, -//! } -//! -//! impl Future for MyFuture { -//! type Item = (); -//! type Error = (); -//! -//! fn poll(&mut self) -> Poll { -//! let _enter = self.span.enter(); -//! // Do actual future work... -//! # Ok(Async::Ready(())) -//! } -//! } -//! ``` -//! -//! If this future was spawned on an executor, it might yield one or more times -//! before `poll` returns `Ok(Async::Ready)`. If the future were to yield, then -//! the executor would move on to poll the next future, which may _also_ enter -//! an associated span or series of spans. Therefore, it is valid for a span to -//! be entered repeatedly before it completes. Only the time when that span or -//! one of its children was the current span is considered to be time spent in -//! that span. A span which is not executing and has not yet been closed is said -//! to be _idle_. -//! -//! Because spans may be entered and exited multiple times before they close, -//! [`Subscriber`]s have separate trait methods which are called to notify them -//! of span exits and when span handles are dropped. When execution exits a -//! span, [`exit`] will always be called with that span's ID to notify the -//! subscriber that the span has been exited. When span handles are dropped, the -//! [`drop_span`] method is called with that span's ID. The subscriber may use -//! this to determine whether or not the span will be entered again. -//! -//! If there is only a single handle with the capacity to exit a span, dropping -//! that handle "closes" the span, since the capacity to enter it no longer -//! exists. For example: -//! ``` -//! # #[macro_use] extern crate tokio_trace; -//! # use tokio_trace::Level; -//! # fn main() { -//! { -//! span!(Level::TRACE, "my_span").in_scope(|| { -//! // perform some work in the context of `my_span`... -//! }); // --> Subscriber::exit(my_span) -//! -//! // The handle to `my_span` only lives inside of this block; when it is -//! // dropped, the subscriber will be informed via `drop_span`. -//! -//! } // --> Subscriber::drop_span(my_span) -//! # } -//! ``` -//! -//! However, if multiple handles exist, the span can still be re-entered even if -//! one or more is dropped. For determining when _all_ handles to a span have -//! been dropped, `Subscriber`s have a [`clone_span`] method, which is called -//! every time a span handle is cloned. Combined with `drop_span`, this may be -//! used to track the number of handles to a given span — if `drop_span` has -//! been called one more time than the number of calls to `clone_span` for a -//! given ID, then no more handles to the span with that ID exist. The -//! subscriber may then treat it as closed. -//! -//! # When to use spans -//! -//! As a rule of thumb, spans should be used to represent discrete units of work -//! (e.g., a given request's lifetime in a server) or periods of time spent in a -//! given context (e.g., time spent interacting with an instance of an external -//! system, such as a database). -//! -//! Which scopes in a program correspond to new spans depend somewhat on user -//! intent. For example, consider the case of a loop in a program. Should we -//! construct one span and perform the entire loop inside of that span, like: -//! -//! ```rust -//! # #[macro_use] extern crate tokio_trace; -//! # use tokio_trace::Level; -//! # fn main() { -//! # let n = 1; -//! let span = span!(Level::TRACE, "my_loop"); -//! let _enter = span.enter(); -//! for i in 0..n { -//! # let _ = i; -//! // ... -//! } -//! # } -//! ``` -//! Or, should we create a new span for each iteration of the loop, as in: -//! ```rust -//! # #[macro_use] extern crate tokio_trace; -//! # use tokio_trace::Level; -//! # fn main() { -//! # let n = 1u64; -//! for i in 0..n { -//! let span = span!(Level::TRACE, "my_loop", iteration = i); -//! let _enter = span.enter(); -//! // ... -//! } -//! # } -//! ``` -//! -//! Depending on the circumstances, we might want to do either, or both. For -//! example, if we want to know how long was spent in the loop overall, we would -//! create a single span around the entire loop; whereas if we wanted to know how -//! much time was spent in each individual iteration, we would enter a new span -//! on every iteration. -//! -//! [fields]: ../field/index.html -//! [metadata]: ../struct.Metadata.html -//! [`Id`]: struct.Id.html -//! [verbosity level]: ../struct.Level.html -//! [`span!`]: ../macro.span.html -//! [`trace_span!`]: ../macro.trace_span.html -//! [`debug_span!`]: ../macro.debug_span.html -//! [`info_span!`]: ../macro.info_span.html -//! [`warn_span!`]: ../macro.warn_span.html -//! [`error_span!`]: ../macro.error_span.html -//! [`clone_span`]: ../subscriber/trait.Subscriber.html#method.clone_span -//! [`drop_span`]: ../subscriber/trait.Subscriber.html#method.drop_span -//! [`exit`]: ../subscriber/trait.Subscriber.html#tymethod.exit -//! [`Subscriber`]: ../subscriber/trait.Subscriber.html -//! [`Attributes`]: struct.Attributes.html -//! [`enter`]: struct.Span.html#method.enter -//! [`in_scope`]: struct.Span.html#method.in_scope -//! [`follows_from`]: struct.Span.html#method.follows_from -//! [guard]: struct.Entered.html -pub use tokio_trace_core::span::{Attributes, Id, Record}; - -use std::{ - cmp, fmt, - hash::{Hash, Hasher}, -}; -use {dispatcher::Dispatch, field, Metadata}; - -/// Trait implemented by types which have a span `Id`. -pub trait AsId: ::sealed::Sealed { - /// Returns the `Id` of the span that `self` corresponds to, or `None` if - /// this corresponds to a disabled span. - fn as_id(&self) -> Option<&Id>; -} - -/// A handle representing a span, with the capability to enter the span if it -/// exists. -/// -/// If the span was rejected by the current `Subscriber`'s filter, entering the -/// span will silently do nothing. Thus, the handle can be used in the same -/// manner regardless of whether or not the trace is currently being collected. -#[derive(Clone)] -pub struct Span { - /// A handle used to enter the span when it is not executing. - /// - /// If this is `None`, then the span has either closed or was never enabled. - inner: Option, - meta: &'static Metadata<'static>, -} - -/// A handle representing the capacity to enter a span which is known to exist. -/// -/// Unlike `Span`, this type is only constructed for spans which _have_ been -/// enabled by the current filter. This type is primarily used for implementing -/// span handles; users should typically not need to interact with it directly. -#[derive(Debug)] -pub(crate) struct Inner { - /// The span's ID, as provided by `subscriber`. - id: Id, - - /// The subscriber that will receive events relating to this span. - /// - /// This should be the same subscriber that provided this span with its - /// `id`. - subscriber: Dispatch, -} - -/// A guard representing a span which has been entered and is currently -/// executing. -/// -/// When the guard is dropped, the span will be exited. -/// -/// This is returned by the [`Span::enter`] function. -/// -/// [`Span::enter`]: ../struct.Span.html#method.enter -#[derive(Debug)] -#[must_use = "once a span has been entered, it should be exited"] -pub struct Entered<'a> { - span: &'a Span, -} - -// ===== impl Span ===== - -impl Span { - /// Constructs a new `Span` with the given [metadata] and set of - /// [field values]. - /// - /// The new span will be constructed by the currently-active [`Subscriber`], - /// with the current span as its parent (if one exists). - /// - /// After the span is constructed, [field values] and/or [`follows_from`] - /// annotations may be added to it. - /// - /// [metadata]: ../metadata - /// [`Subscriber`]: ../subscriber/trait.Subscriber.html - /// [field values]: ../field/struct.ValueSet.html - /// [`follows_from`]: ../struct.Span.html#method.follows_from - #[inline] - pub fn new(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span { - let new_span = Attributes::new(meta, values); - Self::make(meta, new_span) - } - - /// Constructs a new `Span` as the root of its own trace tree, with the - /// given [metadata] and set of [field values]. - /// - /// After the span is constructed, [field values] and/or [`follows_from`] - /// annotations may be added to it. - /// - /// [metadata]: ../metadata - /// [field values]: ../field/struct.ValueSet.html - /// [`follows_from`]: ../struct.Span.html#method.follows_from - #[inline] - pub fn new_root(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span { - Self::make(meta, Attributes::new_root(meta, values)) - } - - /// Constructs a new `Span` as child of the given parent span, with the - /// given [metadata] and set of [field values]. - /// - /// After the span is constructed, [field values] and/or [`follows_from`] - /// annotations may be added to it. - /// - /// [metadata]: ../metadata - /// [field values]: ../field/struct.ValueSet.html - /// [`follows_from`]: ../struct.Span.html#method.follows_from - pub fn child_of( - parent: impl Into>, - meta: &'static Metadata<'static>, - values: &field::ValueSet, - ) -> Span { - let new_span = match parent.into() { - Some(parent) => Attributes::child_of(parent, meta, values), - None => Attributes::new_root(meta, values), - }; - Self::make(meta, new_span) - } - - /// Constructs a new disabled span. - #[inline(always)] - pub fn new_disabled(meta: &'static Metadata<'static>) -> Span { - Span { inner: None, meta } - } - - fn make(meta: &'static Metadata<'static>, new_span: Attributes) -> Span { - let attrs = &new_span; - let inner = ::dispatcher::get_default(move |dispatch| { - let id = dispatch.new_span(attrs); - Some(Inner::new(id, dispatch)) - }); - let span = Self { inner, meta }; - span.log(format_args!("{}; {}", meta.name(), FmtAttrs(&new_span))); - span - } - - /// Enters this span, returning a guard that will exit the span when dropped. - /// - /// If this span is enabled by the current subscriber, then this function will - /// call [`Subscriber::enter`] with the span's [`Id`], and dropping the guard - /// will call [`Subscriber::exit`]. If the span is disabled, this does nothing. - /// - /// # Examples - /// - /// ``` - /// #[macro_use] extern crate tokio_trace; - /// # use tokio_trace::Level; - /// # fn main() { - /// let span = span!(Level::INFO, "my_span"); - /// let guard = span.enter(); - /// - /// // code here is within the span - /// - /// drop(guard); - /// - /// // code here is no longer within the span - /// - /// # } - /// ``` - /// - /// Guards need not be explicitly dropped: - /// - /// ``` - /// #[macro_use] extern crate tokio_trace; - /// # fn main() { - /// fn my_function() -> String { - /// // enter a span for the duration of this function. - /// let span = trace_span!("my_function"); - /// let _enter = span.enter(); - /// - /// // anything happening in functions we call is still inside the span... - /// my_other_function(); - /// - /// // returning from the function drops the guard, exiting the span. - /// return "Hello world".to_owned(); - /// } - /// - /// fn my_other_function() { - /// // ... - /// } - /// # } - /// ``` - /// - /// Sub-scopes may be created to limit the duration for which the span is - /// entered: - /// - /// ``` - /// #[macro_use] extern crate tokio_trace; - /// # fn main() { - /// let span = info_span!("my_great_span"); - /// - /// { - /// let _enter = span.enter(); - /// - /// // this event occurs inside the span. - /// info!("i'm in the span!"); - /// - /// // exiting the scope drops the guard, exiting the span. - /// } - /// - /// // this event is not inside the span. - /// info!("i'm outside the span!") - /// # } - /// ``` - /// - /// [`Subscriber::enter`]: ../subscriber/trait.Subscriber.html#method.enter - /// [`Subscriber::exit`]: ../subscriber/trait.Subscriber.html#method.exit - /// [`Id`]: ../struct.Id.html - pub fn enter<'a>(&'a self) -> Entered<'a> { - if let Some(ref inner) = self.inner.as_ref() { - inner.subscriber.enter(&inner.id); - } - self.log(format_args!("-> {}", self.meta.name)); - Entered { span: self } - } - - /// Executes the given function in the context of this span. - /// - /// If this span is enabled, then this function enters the span, invokes `f` - /// and then exits the span. If the span is disabled, `f` will still be - /// invoked, but in the context of the currently-executing span (if there is - /// one). - /// - /// Returns the result of evaluating `f`. - /// - /// # Examples - /// - /// ``` - /// # #[macro_use] extern crate tokio_trace; - /// # use tokio_trace::Level; - /// # fn main() { - /// let my_span = span!(Level::TRACE, "my_span"); - /// - /// my_span.in_scope(|| { - /// // this event occurs within the span. - /// trace!("i'm in the span!"); - /// }); - /// - /// // this event occurs outside the span. - /// trace!("i'm not in the span!"); - /// # } - /// ``` - /// - /// Calling a function and returning the result: - /// ``` - /// # #[macro_use] extern crate tokio_trace; - /// # use tokio_trace::Level; - /// fn hello_world() -> String { - /// "Hello world!".to_owned() - /// } - /// - /// # fn main() { - /// let span = info_span!("hello_world"); - /// // the span will be entered for the duration of the call to - /// // `hello_world`. - /// let a_string = span.in_scope(hello_world); - /// # } - /// - pub fn in_scope T, T>(&self, f: F) -> T { - let _enter = self.enter(); - f() - } - - /// Returns a [`Field`](../field/struct.Field.html) for the field with the - /// given `name`, if one exists, - pub fn field(&self, field: &Q) -> Option - where - Q: field::AsField, - { - self.metadata().and_then(|meta| field.as_field(meta)) - } - - /// Returns true if this `Span` has a field for the given - /// [`Field`](../field/struct.Field.html) or field name. - #[inline] - pub fn has_field(&self, field: &Q) -> bool - where - Q: field::AsField, - { - self.field(field).is_some() - } - - /// Visits that the field described by `field` has the value `value`. - pub fn record(&self, field: &Q, value: &V) -> &Self - where - Q: field::AsField, - V: field::Value, - { - if let Some(field) = field.as_field(self.meta) { - self.record_all( - &self - .meta - .fields() - .value_set(&[(&field, Some(value as &field::Value))]), - ); - } - - self - } - - /// Visit all the fields in the span - pub fn record_all(&self, values: &field::ValueSet) -> &Self { - let record = Record::new(values); - if let Some(ref inner) = self.inner { - inner.record(&record); - } - self.log(format_args!("{}; {}", self.meta.name(), FmtValues(&record))); - self - } - - /// Returns `true` if this span was disabled by the subscriber and does not - /// exist. - #[inline] - pub fn is_disabled(&self) -> bool { - self.inner.is_none() - } - - /// Indicates that the span with the given ID has an indirect causal - /// relationship with this span. - /// - /// This relationship differs somewhat from the parent-child relationship: a - /// span may have any number of prior spans, rather than a single one; and - /// spans are not considered to be executing _inside_ of the spans they - /// follow from. This means that a span may close even if subsequent spans - /// that follow from it are still open, and time spent inside of a - /// subsequent span should not be included in the time its precedents were - /// executing. This is used to model causal relationships such as when a - /// single future spawns several related background tasks, et cetera. - /// - /// If this span is disabled, or the resulting follows-from relationship - /// would be invalid, this function will do nothing. - pub fn follows_from(&self, from: impl for<'a> Into>) -> &Self { - if let Some(ref inner) = self.inner { - if let Some(from) = from.into() { - inner.follows_from(from); - } - } - self - } - - /// Returns this span's `Id`, if it is enabled. - pub fn id(&self) -> Option { - self.inner.as_ref().map(Inner::id) - } - - /// Returns this span's `Metadata`, if it is enabled. - pub fn metadata(&self) -> Option<&'static Metadata<'static>> { - if self.inner.is_some() { - Some(self.meta) - } else { - None - } - } - - #[cfg(feature = "log")] - #[inline] - fn log(&self, message: fmt::Arguments) { - use log; - let logger = log::logger(); - let log_meta = log::Metadata::builder() - .level(level_to_log!(self.meta.level)) - .target(self.meta.target) - .build(); - if logger.enabled(&log_meta) { - logger.log( - &log::Record::builder() - .metadata(log_meta) - .module_path(self.meta.module_path) - .file(self.meta.file) - .line(self.meta.line) - .args(message) - .build(), - ); - } - } - - #[cfg(not(feature = "log"))] - #[inline] - fn log(&self, _: fmt::Arguments) {} -} - -impl cmp::PartialEq for Span { - fn eq(&self, other: &Self) -> bool { - self.meta.callsite() == other.meta.callsite() && self.inner == other.inner - } -} - -impl Hash for Span { - fn hash(&self, hasher: &mut H) { - self.inner.hash(hasher); - } -} - -impl fmt::Debug for Span { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut span = f.debug_struct("Span"); - span.field("name", &self.meta.name()) - .field("level", &self.meta.level()) - .field("target", &self.meta.target()); - - if let Some(ref inner) = self.inner { - span.field("id", &inner.id()); - } else { - span.field("disabled", &true); - } - - if let Some(ref path) = self.meta.module_path() { - span.field("module_path", &path); - } - - if let Some(ref line) = self.meta.line() { - span.field("line", &line); - } - - if let Some(ref file) = self.meta.file() { - span.field("file", &file); - } - - span.finish() - } -} - -impl<'a> Into> for &'a Span { - fn into(self) -> Option<&'a Id> { - self.inner.as_ref().map(|inner| &inner.id) - } -} - -impl<'a> Into> for &'a Span { - fn into(self) -> Option { - self.inner.as_ref().map(Inner::id) - } -} - -impl Into> for Span { - fn into(self) -> Option { - self.inner.as_ref().map(Inner::id) - } -} - -// ===== impl Inner ===== - -impl Inner { - /// Indicates that the span with the given ID has an indirect causal - /// relationship with this span. - /// - /// This relationship differs somewhat from the parent-child relationship: a - /// span may have any number of prior spans, rather than a single one; and - /// spans are not considered to be executing _inside_ of the spans they - /// follow from. This means that a span may close even if subsequent spans - /// that follow from it are still open, and time spent inside of a - /// subsequent span should not be included in the time its precedents were - /// executing. This is used to model causal relationships such as when a - /// single future spawns several related background tasks, et cetera. - /// - /// If this span is disabled, this function will do nothing. Otherwise, it - /// returns `Ok(())` if the other span was added as a precedent of this - /// span, or an error if this was not possible. - fn follows_from(&self, from: &Id) { - self.subscriber.record_follows_from(&self.id, &from) - } - - /// Returns the span's ID. - fn id(&self) -> Id { - self.id.clone() - } - - fn record(&self, values: &Record) { - self.subscriber.record(&self.id, values) - } - - fn new(id: Id, subscriber: &Dispatch) -> Self { - Inner { - id, - subscriber: subscriber.clone(), - } - } -} - -impl cmp::PartialEq for Inner { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } -} - -impl Hash for Inner { - fn hash(&self, state: &mut H) { - self.id.hash(state); - } -} - -impl Drop for Inner { - fn drop(&mut self) { - self.subscriber.drop_span(self.id.clone()); - } -} - -impl Clone for Inner { - fn clone(&self) -> Self { - Inner { - id: self.subscriber.clone_span(&self.id), - subscriber: self.subscriber.clone(), - } - } -} - -// ===== impl Entered ===== - -impl<'a> Drop for Entered<'a> { - #[inline] - fn drop(&mut self) { - // Dropping the guard exits the span. - // - // Running this behaviour on drop rather than with an explicit function - // call means that spans may still be exited when unwinding. - if let Some(inner) = self.span.inner.as_ref() { - inner.subscriber.exit(&inner.id); - } - self.span.log(format_args!("<- {}", self.span.meta.name)); - } -} - -struct FmtValues<'a>(&'a Record<'a>); - -impl<'a> fmt::Display for FmtValues<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut res = Ok(()); - self.0.record(&mut |k: &field::Field, v: &fmt::Debug| { - res = write!(f, "{}={:?} ", k, v); - }); - res - } -} - -struct FmtAttrs<'a>(&'a Attributes<'a>); - -impl<'a> fmt::Display for FmtAttrs<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut res = Ok(()); - self.0.record(&mut |k: &field::Field, v: &fmt::Debug| { - res = write!(f, "{}={:?} ", k, v); - }); - res - } -} - -#[cfg(test)] -mod test { - use super::*; - - trait AssertSend: Send {} - impl AssertSend for Span {} - - trait AssertSync: Sync {} - impl AssertSync for Span {} -} diff --git a/tokio-trace/src/subscriber.rs b/tokio-trace/src/subscriber.rs deleted file mode 100644 index c6b0f7a88..000000000 --- a/tokio-trace/src/subscriber.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Collects and records trace data. -pub use tokio_trace_core::subscriber::*; - -/// Sets this subscriber as the default for the duration of a closure. -/// -/// The default subscriber is used when creating a new [`Span`] or -/// [`Event`], _if no span is currently executing_. If a span is currently -/// executing, new spans or events are dispatched to the subscriber that -/// tagged that span, instead. -/// -/// [`Span`]: ../span/struct.Span.html -/// [`Subscriber`]: ../subscriber/trait.Subscriber.html -/// [`Event`]: :../event/struct.Event.html -pub fn with_default(subscriber: S, f: impl FnOnce() -> T) -> T -where - S: Subscriber + Send + Sync + 'static, -{ - ::dispatcher::with_default(&::Dispatch::new(subscriber), f) -} - -/// Sets this subscriber as the global default for the duration of the entire program. -/// Will be used as a fallback if no thread-local subscriber has been set in a thread (using `with_default`.) -/// -/// Can only be set once; subsequent attempts to set the global default will fail. -/// Returns whether the initialization was successful. -/// -/// Note: Libraries should *NOT* call `set_global_default()`! That will cause conflicts when -/// executables try to set them later. -/// -/// [span]: ../span/index.html -/// [`Subscriber`]: ../subscriber/trait.Subscriber.html -/// [`Event`]: ../event/struct.Event.html -pub fn set_global_default(subscriber: S) -> Result<(), SetGlobalDefaultError> -where - S: Subscriber + Send + Sync + 'static, -{ - ::dispatcher::set_global_default(::Dispatch::new(subscriber)) -} - -pub use tokio_trace_core::dispatcher::SetGlobalDefaultError; diff --git a/tokio-trace/test-log-support/Cargo.toml b/tokio-trace/test-log-support/Cargo.toml deleted file mode 100644 index f749e6356..000000000 --- a/tokio-trace/test-log-support/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[workspace] - -[package] -name = "test_log_support" -version = "0.1.0" -publish = false - -[dependencies] -tokio-trace = { path = "..", features = ["log"] } -log = { version = "0.4", features = ["std"] } diff --git a/tokio-trace/test-log-support/tests/log_no_trace.rs b/tokio-trace/test-log-support/tests/log_no_trace.rs deleted file mode 100644 index 61134dc21..000000000 --- a/tokio-trace/test-log-support/tests/log_no_trace.rs +++ /dev/null @@ -1,74 +0,0 @@ -extern crate log; -#[macro_use] -extern crate tokio_trace; - -use log::{LevelFilter, Log, Metadata, Record}; -use std::sync::{Arc, Mutex}; -use tokio_trace::Level; - -struct State { - last_log: Mutex>, -} - -struct Logger(Arc); - -impl Log for Logger { - fn enabled(&self, _: &Metadata) -> bool { - true - } - - fn log(&self, record: &Record) { - let line = format!("{}", record.args()); - println!("{:<5} {} {}", record.level(), record.target(), line); - *self.0.last_log.lock().unwrap() = Some(line); - } - - fn flush(&self) {} -} - -#[test] -fn test_always_log() { - let me = Arc::new(State { - last_log: Mutex::new(None), - }); - let a = me.clone(); - log::set_boxed_logger(Box::new(Logger(me))).unwrap(); - log::set_max_level(LevelFilter::Trace); - - error!(foo = 5); - last(&a, "foo=5"); - warn!("hello {};", "world"); - last(&a, "hello world;"); - info!(message = "hello world;", thingy = 42, other_thingy = 666); - last(&a, "hello world; thingy=42 other_thingy=666"); - - let foo = span!(Level::TRACE, "foo"); - last(&a, "foo;"); - foo.in_scope(|| { - last(&a, "-> foo"); - - trace!({foo = 3, bar = 4}, "hello {};", "san francisco"); - last(&a, "hello san francisco; foo=3 bar=4"); - }); - last(&a, "<- foo"); - - span!(Level::TRACE, "foo", bar = 3, baz = false); - last(&a, "foo; bar=3 baz=false"); - - // TODO(#1138): determine a new syntax for uninitialized span fields, and - // re-enable these. - // let span = span!(Level::TRACE, "foo", bar = _, baz = _); - // span.record("bar", &3); - // last(&a, "foo; bar=3"); - // span.record("baz", &"a string"); - // last(&a, "foo; baz=\"a string\""); -} - -fn last(state: &State, expected: &str) { - let mut lock = state.last_log.lock().unwrap(); - { - let last = lock.as_ref().map(|s| s.as_str().trim()); - assert_eq!(last, Some(expected)); - } - *lock = None; -} diff --git a/tokio-trace/test_static_max_level_features/Cargo.toml b/tokio-trace/test_static_max_level_features/Cargo.toml deleted file mode 100644 index a40596a3f..000000000 --- a/tokio-trace/test_static_max_level_features/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[workspace] - -[package] -name = "test_cargo_max_level_features" -version = "0.1.0" -publish = false - -[dependencies.tokio-trace] -path = ".." -features = ["max_level_debug", "release_max_level_info"] diff --git a/tokio-trace/test_static_max_level_features/tests/test.rs b/tokio-trace/test_static_max_level_features/tests/test.rs deleted file mode 100644 index ff13b2eef..000000000 --- a/tokio-trace/test_static_max_level_features/tests/test.rs +++ /dev/null @@ -1,71 +0,0 @@ -#[macro_use] -extern crate tokio_trace; - -use std::sync::{Arc, Mutex}; -use tokio_trace::span::{Attributes, Record}; -use tokio_trace::{span, Event, Id, Level, Metadata, Subscriber}; - -struct State { - last_level: Mutex>, -} - -struct TestSubscriber(Arc); - -impl Subscriber for TestSubscriber { - fn enabled(&self, _: &Metadata) -> bool { - true - } - - fn new_span(&self, _span: &Attributes) -> Id { - span::Id::from_u64(42) - } - - fn record(&self, _span: &Id, _values: &Record) {} - - fn record_follows_from(&self, _span: &Id, _follows: &Id) {} - - fn event(&self, event: &Event) { - *self.0.last_level.lock().unwrap() = Some(event.metadata().level().clone()); - } - - fn enter(&self, _span: &Id) {} - - fn exit(&self, _span: &Id) {} -} - -#[cfg(test)] -fn test_static_max_level_features() { - let me = Arc::new(State { - last_level: Mutex::new(None), - }); - let a = me.clone(); - tokio_trace::subscriber::with_default(TestSubscriber(me), || { - error!(""); - last(&a, Some(Level::ERROR)); - warn!(""); - last(&a, Some(Level::WARN)); - info!(""); - last(&a, Some(Level::INFO)); - debug!(""); - last(&a, Some(Level::DEBUG)); - trace!(""); - last(&a, None); - - span!(Level::ERROR, ""); - last(&a, None); - span!(Level::WARN, ""); - last(&a, None); - span!(Level::INFO, ""); - last(&a, None); - span!(Level::DEBUG, ""); - last(&a, None); - span!(Level::TRACE, ""); - last(&a, None); - }); -} - -fn last(state: &State, expected: Option) { - let mut lvl = state.last_level.lock().unwrap(); - assert_eq!(*lvl, expected); - *lvl = None; -} diff --git a/tokio-trace/tests/event.rs b/tokio-trace/tests/event.rs deleted file mode 100644 index 424fb3c13..000000000 --- a/tokio-trace/tests/event.rs +++ /dev/null @@ -1,251 +0,0 @@ -#[macro_use] -extern crate tokio_trace; -mod support; - -use self::support::*; - -use tokio_trace::{ - field::{debug, display}, - subscriber::with_default, - Level, -}; - -#[test] -fn event_without_message() { - let (subscriber, handle) = subscriber::mock() - .event( - event::mock().with_fields( - field::mock("answer") - .with_value(&42) - .and( - field::mock("to_question") - .with_value(&"life, the universe, and everything"), - ) - .only(), - ), - ) - .done() - .run_with_handle(); - - with_default(subscriber, || { - info!( - answer = 42, - to_question = "life, the universe, and everything" - ); - }); - - handle.assert_finished(); -} - -#[test] -fn event_with_message() { - let (subscriber, handle) = subscriber::mock() - .event(event::mock().with_fields(field::mock("message").with_value( - &tokio_trace::field::debug(format_args!( - "hello from my event! yak shaved = {:?}", - true - )), - ))) - .done() - .run_with_handle(); - - with_default(subscriber, || { - debug!("hello from my event! yak shaved = {:?}", true); - }); - - handle.assert_finished(); -} - -#[test] -fn one_with_everything() { - let (subscriber, handle) = subscriber::mock() - .event( - event::mock() - .with_fields( - field::mock("message") - .with_value(&tokio_trace::field::debug(format_args!( - "{:#x} make me one with{what:.>20}", - 4277009102u64, - what = "everything" - ))) - .and(field::mock("foo").with_value(&666)) - .and(field::mock("bar").with_value(&false)) - .only(), - ) - .at_level(Level::ERROR) - .with_target("whatever"), - ) - .done() - .run_with_handle(); - - with_default(subscriber, || { - event!( - target: "whatever", - Level::ERROR, - { foo = 666, bar = false }, - "{:#x} make me one with{what:.>20}", 4277009102u64, what = "everything" - ); - }); - - handle.assert_finished(); -} - -#[test] -fn moved_field() { - let (subscriber, handle) = subscriber::mock() - .event( - event::mock().with_fields( - field::mock("foo") - .with_value(&display("hello from my event")) - .only(), - ), - ) - .done() - .run_with_handle(); - with_default(subscriber, || { - let from = "my event"; - event!(Level::INFO, foo = display(format!("hello from {}", from))) - }); - - handle.assert_finished(); -} - -#[test] -fn dotted_field_name() { - let (subscriber, handle) = subscriber::mock() - .event( - event::mock().with_fields( - field::mock("foo.bar") - .with_value(&true) - .and(field::mock("foo.baz").with_value(&false)) - .only(), - ), - ) - .done() - .run_with_handle(); - with_default(subscriber, || { - event!(Level::INFO, foo.bar = true, foo.baz = false); - }); - - handle.assert_finished(); -} - -#[test] -fn borrowed_field() { - let (subscriber, handle) = subscriber::mock() - .event( - event::mock().with_fields( - field::mock("foo") - .with_value(&display("hello from my event")) - .only(), - ), - ) - .done() - .run_with_handle(); - with_default(subscriber, || { - let from = "my event"; - let mut message = format!("hello from {}", from); - event!(Level::INFO, foo = display(&message)); - message.push_str(", which happened!"); - }); - - handle.assert_finished(); -} - -#[test] -// If emitting log instrumentation, this gets moved anyway, breaking the test. -#[cfg(not(feature = "log"))] -fn move_field_out_of_struct() { - use tokio_trace::field::debug; - - #[derive(Debug)] - struct Position { - x: f32, - y: f32, - } - - let pos = Position { - x: 3.234, - y: -1.223, - }; - let (subscriber, handle) = subscriber::mock() - .event( - event::mock().with_fields( - field::mock("x") - .with_value(&debug(3.234)) - .and(field::mock("y").with_value(&debug(-1.223))) - .only(), - ), - ) - .event(event::mock().with_fields(field::mock("position").with_value(&debug(&pos)))) - .done() - .run_with_handle(); - - with_default(subscriber, || { - let pos = Position { - x: 3.234, - y: -1.223, - }; - debug!(x = debug(pos.x), y = debug(pos.y)); - debug!(target: "app_events", { position = debug(pos) }, "New position"); - }); - handle.assert_finished(); -} - -#[test] -fn display_shorthand() { - let (subscriber, handle) = subscriber::mock() - .event( - event::mock().with_fields( - field::mock("my_field") - .with_value(&display("hello world")) - .only(), - ), - ) - .done() - .run_with_handle(); - with_default(subscriber, || { - event!(Level::TRACE, my_field = %"hello world"); - }); - - handle.assert_finished(); -} - -#[test] -fn debug_shorthand() { - let (subscriber, handle) = subscriber::mock() - .event( - event::mock().with_fields( - field::mock("my_field") - .with_value(&debug("hello world")) - .only(), - ), - ) - .done() - .run_with_handle(); - with_default(subscriber, || { - event!(Level::TRACE, my_field = ?"hello world"); - }); - - handle.assert_finished(); -} - -#[test] -fn both_shorthands() { - let (subscriber, handle) = subscriber::mock() - .event( - event::mock().with_fields( - field::mock("display_field") - .with_value(&display("hello world")) - .and(field::mock("debug_field").with_value(&debug("hello world"))) - .only(), - ), - ) - .done() - .run_with_handle(); - with_default(subscriber, || { - event!(Level::TRACE, display_field = %"hello world", debug_field = ?"hello world"); - }); - - handle.assert_finished(); -} diff --git a/tokio-trace/tests/filter_caching_is_lexically_scoped.rs b/tokio-trace/tests/filter_caching_is_lexically_scoped.rs deleted file mode 100644 index 72c07299e..000000000 --- a/tokio-trace/tests/filter_caching_is_lexically_scoped.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Tests that depend on a count of the number of times their filter is evaluated -// can't exist in the same file with other tests that add subscribers to the -// registry. The registry was changed so that each time a new dispatcher is -// added all filters are re-evaluated. The tests being run only in separate -// threads with shared global state lets them interfere with eachother - -#[macro_use] -extern crate tokio_trace; -mod support; - -use self::support::*; -use tokio_trace::subscriber::with_default; -use tokio_trace::Level; - -use std::sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, -}; - -#[test] -fn filter_caching_is_lexically_scoped() { - pub fn my_great_function() -> bool { - span!(Level::TRACE, "emily").in_scope(|| true) - } - - pub fn my_other_function() -> bool { - span!(Level::TRACE, "frank").in_scope(|| true) - } - - let count = Arc::new(AtomicUsize::new(0)); - let count2 = count.clone(); - - let subscriber = subscriber::mock() - .with_filter(move |meta| match meta.name { - "emily" | "frank" => { - count2.fetch_add(1, Ordering::Relaxed); - true - } - _ => false, - }) - .run(); - - with_default(subscriber, || { - // Call the function once. The filter should be re-evaluated. - assert!(my_great_function()); - assert_eq!(count.load(Ordering::Relaxed), 1); - - // Call the function again. The cached result should be used. - assert!(my_great_function()); - assert_eq!(count.load(Ordering::Relaxed), 1); - - assert!(my_other_function()); - assert_eq!(count.load(Ordering::Relaxed), 2); - - assert!(my_great_function()); - assert_eq!(count.load(Ordering::Relaxed), 2); - - assert!(my_other_function()); - assert_eq!(count.load(Ordering::Relaxed), 2); - - assert!(my_great_function()); - assert_eq!(count.load(Ordering::Relaxed), 2); - }); -} diff --git a/tokio-trace/tests/filters_are_not_reevaluated_for_the_same_span.rs b/tokio-trace/tests/filters_are_not_reevaluated_for_the_same_span.rs deleted file mode 100644 index 3feb766f9..000000000 --- a/tokio-trace/tests/filters_are_not_reevaluated_for_the_same_span.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Tests that depend on a count of the number of times their filter is evaluated -// cant exist in the same file with other tests that add subscribers to the -// registry. The registry was changed so that each time a new dispatcher is -// added all filters are re-evaluated. The tests being run only in separate -// threads with shared global state lets them interfere with eachother - -#[macro_use] -extern crate tokio_trace; -mod support; - -use self::support::*; -use tokio_trace::subscriber::with_default; -use tokio_trace::Level; - -use std::sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, -}; - -#[test] -fn filters_are_not_reevaluated_for_the_same_span() { - // Asserts that the `span!` macro caches the result of calling - // `Subscriber::enabled` for each span. - let alice_count = Arc::new(AtomicUsize::new(0)); - let bob_count = Arc::new(AtomicUsize::new(0)); - let alice_count2 = alice_count.clone(); - let bob_count2 = bob_count.clone(); - - let (subscriber, handle) = subscriber::mock() - .with_filter(move |meta| match meta.name { - "alice" => { - alice_count2.fetch_add(1, Ordering::Relaxed); - false - } - "bob" => { - bob_count2.fetch_add(1, Ordering::Relaxed); - true - } - _ => false, - }) - .run_with_handle(); - - with_default(subscriber, move || { - // Enter "alice" and then "bob". The dispatcher expects to see "bob" but - // not "alice." - let alice = span!(Level::TRACE, "alice"); - let bob = alice.in_scope(|| { - let bob = span!(Level::TRACE, "bob"); - bob.in_scope(|| ()); - bob - }); - - // The filter should have seen each span a single time. - assert_eq!(alice_count.load(Ordering::Relaxed), 1); - assert_eq!(bob_count.load(Ordering::Relaxed), 1); - - alice.in_scope(|| bob.in_scope(|| {})); - - // The subscriber should see "bob" again, but the filter should not have - // been called. - assert_eq!(alice_count.load(Ordering::Relaxed), 1); - assert_eq!(bob_count.load(Ordering::Relaxed), 1); - - bob.in_scope(|| {}); - assert_eq!(alice_count.load(Ordering::Relaxed), 1); - assert_eq!(bob_count.load(Ordering::Relaxed), 1); - }); - handle.assert_finished(); -} diff --git a/tokio-trace/tests/filters_are_reevaluated_for_different_call_sites.rs b/tokio-trace/tests/filters_are_reevaluated_for_different_call_sites.rs deleted file mode 100644 index a773354f0..000000000 --- a/tokio-trace/tests/filters_are_reevaluated_for_different_call_sites.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Tests that depend on a count of the number of times their filter is evaluated -// cant exist in the same file with other tests that add subscribers to the -// registry. The registry was changed so that each time a new dispatcher is -// added all filters are re-evaluated. The tests being run only in separate -// threads with shared global state lets them interfere with eachother - -#[macro_use] -extern crate tokio_trace; -mod support; - -use self::support::*; -use tokio_trace::subscriber::with_default; -use tokio_trace::Level; - -use std::sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, -}; - -#[test] -fn filters_are_reevaluated_for_different_call_sites() { - // Asserts that the `span!` macro caches the result of calling - // `Subscriber::enabled` for each span. - let charlie_count = Arc::new(AtomicUsize::new(0)); - let dave_count = Arc::new(AtomicUsize::new(0)); - let charlie_count2 = charlie_count.clone(); - let dave_count2 = dave_count.clone(); - - let subscriber = subscriber::mock() - .with_filter(move |meta| { - println!("Filter: {:?}", meta.name); - match meta.name { - "charlie" => { - charlie_count2.fetch_add(1, Ordering::Relaxed); - false - } - "dave" => { - dave_count2.fetch_add(1, Ordering::Relaxed); - true - } - _ => false, - } - }) - .run(); - - with_default(subscriber, move || { - // Enter "charlie" and then "dave". The dispatcher expects to see "dave" but - // not "charlie." - let charlie = span!(Level::TRACE, "charlie"); - let dave = charlie.in_scope(|| { - let dave = span!(Level::TRACE, "dave"); - dave.in_scope(|| {}); - dave - }); - - // The filter should have seen each span a single time. - assert_eq!(charlie_count.load(Ordering::Relaxed), 1); - assert_eq!(dave_count.load(Ordering::Relaxed), 1); - - charlie.in_scope(|| dave.in_scope(|| {})); - - // The subscriber should see "dave" again, but the filter should not have - // been called. - assert_eq!(charlie_count.load(Ordering::Relaxed), 1); - assert_eq!(dave_count.load(Ordering::Relaxed), 1); - - // A different span with the same name has a different call site, so it - // should cause the filter to be reapplied. - let charlie2 = span!(Level::TRACE, "charlie"); - charlie.in_scope(|| {}); - assert_eq!(charlie_count.load(Ordering::Relaxed), 2); - assert_eq!(dave_count.load(Ordering::Relaxed), 1); - - // But, the filter should not be re-evaluated for the new "charlie" span - // when it is re-entered. - charlie2.in_scope(|| span!(Level::TRACE, "dave").in_scope(|| {})); - assert_eq!(charlie_count.load(Ordering::Relaxed), 2); - assert_eq!(dave_count.load(Ordering::Relaxed), 2); - }); -} diff --git a/tokio-trace/tests/macros.rs b/tokio-trace/tests/macros.rs deleted file mode 100644 index bbbebb51b..000000000 --- a/tokio-trace/tests/macros.rs +++ /dev/null @@ -1,713 +0,0 @@ -use tokio_trace::Level; - -#[macro_use] -extern crate tokio_trace; -// Tests that macros work across various invocation syntax. -// -// These are quite repetitive, and _could_ be generated by a macro. However, -// they're compile-time tests, so I want to get line numbers etc out of -// failures, and producing them with a macro would muddy the waters a bit. - -#[test] -fn span() { - span!(Level::DEBUG, target: "foo_events", "foo", bar.baz = ?2, quux = %3, quuux = 4); - span!(Level::DEBUG, target: "foo_events", "foo", bar.baz = 2, quux = 3); - span!(Level::DEBUG, target: "foo_events", "foo", bar.baz = 2, quux = 4,); - span!(Level::DEBUG, target: "foo_events", "foo"); - span!(Level::DEBUG, target: "foo_events", "bar",); - span!(Level::DEBUG, "foo", bar.baz = 2, quux = 3); - span!(Level::DEBUG, "foo", bar.baz = 2, quux = 4,); - span!(Level::TRACE, "foo", bar.baz = 2, quux = 3); - span!(Level::TRACE, "foo", bar.baz = 2, quux = 4,); - span!(Level::TRACE, "foo", bar.baz = ?2); - span!(Level::TRACE, "foo", bar.baz = %2); - span!(Level::TRACE, "foo"); - span!(Level::TRACE, "bar",); -} - -#[test] -fn trace_span() { - trace_span!(target: "foo_events", "foo", bar.baz = ?2, quux = %3, quuux = 4); - trace_span!(target: "foo_events", "foo", bar.baz = 2, quux = 3); - trace_span!(target: "foo_events", "foo", bar.baz = 2, quux = 4,); - trace_span!(target: "foo_events", "foo"); - trace_span!(target: "foo_events", "bar",); - trace_span!("foo", bar.baz = 2, quux = 3); - trace_span!("foo", bar.baz = 2, quux = 4,); - trace_span!("foo", bar.baz = ?2); - trace_span!("foo", bar.baz = %2); - trace_span!("bar"); - trace_span!("bar",); -} - -#[test] -fn debug_span() { - debug_span!(target: "foo_events", "foo", bar.baz = ?2, quux = %3, quuux = 4); - debug_span!(target: "foo_events", "foo", bar.baz = 2, quux = 3); - debug_span!(target: "foo_events", "foo", bar.baz = 2, quux = 4,); - debug_span!(target: "foo_events", "foo"); - debug_span!(target: "foo_events", "bar",); - debug_span!("foo", bar.baz = 2, quux = 3); - debug_span!("foo", bar.baz = 2, quux = 4,); - debug_span!("foo", bar.baz = ?2); - debug_span!("foo", bar.baz = %2); - debug_span!("bar"); - debug_span!("bar",); -} - -#[test] -fn info_span() { - info_span!(target: "foo_events", "foo", bar.baz = ?2, quux = %3, quuux = 4); - info_span!(target: "foo_events", "foo", bar.baz = 2, quux = 3); - info_span!(target: "foo_events", "foo", bar.baz = 2, quux = 4,); - info_span!(target: "foo_events", "foo"); - info_span!(target: "foo_events", "bar",); - info_span!("foo", bar.baz = 2, quux = 3); - info_span!("foo", bar.baz = 2, quux = 4,); - info_span!("foo", bar.baz = ?2); - info_span!("foo", bar.baz = %2); - info_span!("bar"); - info_span!("bar",); -} - -#[test] -fn warn_span() { - warn_span!(target: "foo_events", "foo", bar.baz = ?2, quux = %3, quuux = 4); - warn_span!(target: "foo_events", "foo", bar.baz = 2, quux = 3); - warn_span!(target: "foo_events", "foo", bar.baz = 2, quux = 4,); - warn_span!(target: "foo_events", "foo"); - warn_span!(target: "foo_events", "bar",); - warn_span!("foo", bar.baz = 2, quux = 3); - warn_span!("foo", bar.baz = 2, quux = 4,); - warn_span!("foo", bar.baz = ?2); - warn_span!("foo", bar.baz = %2); - warn_span!("bar"); - warn_span!("bar",); -} - -#[test] -fn error_span() { - error_span!(target: "foo_events", "foo", bar.baz = ?2, quux = %3, quuux = 4); - error_span!(target: "foo_events", "foo", bar.baz = 2, quux = 3); - error_span!(target: "foo_events", "foo", bar.baz = 2, quux = 4,); - error_span!(target: "foo_events", "foo"); - error_span!(target: "foo_events", "bar",); - error_span!("foo", bar.baz = 2, quux = 3); - error_span!("foo", bar.baz = 2, quux = 4,); - error_span!("foo", bar.baz = ?2); - error_span!("foo", bar.baz = %2); - error_span!("bar"); - error_span!("bar",); -} - -#[test] -fn span_root() { - span!(Level::DEBUG, target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 3); - span!(Level::DEBUG, target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 3); - span!(Level::DEBUG, target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 4,); - span!(Level::DEBUG, target: "foo_events", parent: None, "foo"); - span!(Level::DEBUG, target: "foo_events", parent: None, "bar",); - span!(Level::TRACE, parent: None, "foo", bar.baz = 2, quux = 3); - span!(Level::TRACE, parent: None, "foo", bar.baz = 2, quux = 4,); - span!(Level::TRACE, parent: None, "foo"); - span!(Level::TRACE, parent: None, "bar",); -} - -#[test] -fn trace_span_root() { - trace_span!(target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 3); - trace_span!(target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 4,); - trace_span!(target: "foo_events", parent: None, "foo"); - trace_span!(target: "foo_events", parent: None, "bar",); - trace_span!(parent: None, "foo", bar.baz = 2, quux = 3); - trace_span!(parent: None, "foo", bar.baz = 2, quux = 4,); - trace_span!(parent: None, "foo"); - trace_span!(parent: None, "bar",); -} - -#[test] -fn debug_span_root() { - debug_span!(target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 3); - debug_span!(target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 4,); - debug_span!(target: "foo_events", parent: None, "foo"); - debug_span!(target: "foo_events", parent: None, "bar",); - debug_span!(parent: None, "foo", bar.baz = 2, quux = 3); - debug_span!(parent: None, "foo", bar.baz = 2, quux = 4,); - debug_span!(parent: None, "foo"); - debug_span!(parent: None, "bar",); -} - -#[test] -fn info_span_root() { - info_span!(target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 3); - info_span!(target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 4,); - info_span!(target: "foo_events", parent: None, "foo"); - info_span!(target: "foo_events", parent: None, "bar",); - info_span!(parent: None, "foo", bar.baz = 2, quux = 3); - info_span!(parent: None, "foo", bar.baz = 2, quux = 4,); - info_span!(parent: None, "foo"); - info_span!(parent: None, "bar",); -} - -#[test] -fn warn_span_root() { - warn_span!(target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 3); - warn_span!(target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 4,); - warn_span!(target: "foo_events", parent: None, "foo"); - warn_span!(target: "foo_events", parent: None, "bar",); - warn_span!(parent: None, "foo", bar.baz = 2, quux = 3); - warn_span!(parent: None, "foo", bar.baz = 2, quux = 4,); - warn_span!(parent: None, "foo"); - warn_span!(parent: None, "bar",); -} - -#[test] -fn error_span_root() { - error_span!(target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 3); - error_span!(target: "foo_events", parent: None, "foo", bar.baz = 2, quux = 4,); - error_span!(target: "foo_events", parent: None, "foo"); - error_span!(target: "foo_events", parent: None, "bar",); - error_span!(parent: None, "foo", bar.baz = 2, quux = 3); - error_span!(parent: None, "foo", bar.baz = 2, quux = 4,); - error_span!(parent: None, "foo"); - error_span!(parent: None, "bar",); -} - -#[test] -fn span_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - span!(Level::DEBUG, target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 3); - span!(Level::DEBUG, target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 4,); - span!(Level::DEBUG, target: "foo_events", parent: &p, "foo"); - span!(Level::DEBUG, target: "foo_events", parent: &p, "bar",); - - span!(Level::DEBUG, parent: &p, "foo", bar.baz = 2, quux = 3); - span!(Level::DEBUG, parent: &p, "foo", bar.baz = 2, quux = 4,); - - span!(Level::DEBUG, parent: &p, "foo"); - span!(Level::DEBUG, parent: &p, "bar",); -} - -#[test] -fn trace_span_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - trace_span!(target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 3); - trace_span!(target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 4,); - trace_span!(target: "foo_events", parent: &p, "foo"); - trace_span!(target: "foo_events", parent: &p, "bar",); - - trace_span!(parent: &p, "foo", bar.baz = 2, quux = 3); - trace_span!(parent: &p, "foo", bar.baz = 2, quux = 4,); - - trace_span!(parent: &p, "foo"); - trace_span!(parent: &p, "bar",); -} - -#[test] -fn debug_span_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - debug_span!(target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 3); - debug_span!(target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 4,); - debug_span!(target: "foo_events", parent: &p, "foo"); - debug_span!(target: "foo_events", parent: &p, "bar",); - - debug_span!(parent: &p, "foo", bar.baz = 2, quux = 3); - debug_span!(parent: &p, "foo", bar.baz = 2, quux = 4,); - - debug_span!(parent: &p, "foo"); - debug_span!(parent: &p, "bar",); -} - -#[test] -fn info_span_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - info_span!(target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 3); - info_span!(target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 4,); - info_span!(target: "foo_events", parent: &p, "foo"); - info_span!(target: "foo_events", parent: &p, "bar",); - - info_span!(parent: &p, "foo", bar.baz = 2, quux = 3); - info_span!(parent: &p, "foo", bar.baz = 2, quux = 4,); - - info_span!(parent: &p, "foo"); - info_span!(parent: &p, "bar",); -} - -#[test] -fn warn_span_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - warn_span!(target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 3); - warn_span!(target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 4,); - warn_span!(target: "foo_events", parent: &p, "foo"); - warn_span!(target: "foo_events", parent: &p, "bar",); - - warn_span!(parent: &p, "foo", bar.baz = 2, quux = 3); - warn_span!(parent: &p, "foo", bar.baz = 2, quux = 4,); - - warn_span!(parent: &p, "foo"); - warn_span!(parent: &p, "bar",); -} - -#[test] -fn error_span_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - error_span!(target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 3); - error_span!(target: "foo_events", parent: &p, "foo", bar.baz = 2, quux = 4,); - error_span!(target: "foo_events", parent: &p, "foo"); - error_span!(target: "foo_events", parent: &p, "bar",); - - error_span!(parent: &p, "foo", bar.baz = 2, quux = 3); - error_span!(parent: &p, "foo", bar.baz = 2, quux = 4,); - - error_span!(parent: &p, "foo"); - error_span!(parent: &p, "bar",); -} - -#[test] -fn event() { - event!(Level::DEBUG, foo = ?3, bar.baz = %2, quux = false); - event!(Level::DEBUG, foo = 3, bar.baz = 2, quux = false); - event!(Level::DEBUG, foo = 3, bar.baz = 3,); - event!(Level::DEBUG, "foo"); - event!(Level::DEBUG, "foo: {}", 3); - event!(Level::DEBUG, { foo = 3, bar.baz = 80 }, "quux"); - event!(Level::DEBUG, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - event!(Level::DEBUG, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - event!(Level::DEBUG, { foo = ?2, bar.baz = %78 }, "quux"); - event!(target: "foo_events", Level::DEBUG, foo = 3, bar.baz = 2, quux = false); - event!(target: "foo_events", Level::DEBUG, foo = 3, bar.baz = 3,); - event!(target: "foo_events", Level::DEBUG, "foo"); - event!(target: "foo_events", Level::DEBUG, "foo: {}", 3); - event!(target: "foo_events", Level::DEBUG, { foo = 3, bar.baz = 80 }, "quux"); - event!(target: "foo_events", Level::DEBUG, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - event!(target: "foo_events", Level::DEBUG, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - event!(target: "foo_events", Level::DEBUG, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn trace() { - trace!(foo = ?3, bar.baz = %2, quux = false); - trace!(foo = 3, bar.baz = 2, quux = false); - trace!(foo = 3, bar.baz = 3,); - trace!("foo"); - trace!("foo: {}", 3); - trace!({ foo = 3, bar.baz = 80 }, "quux"); - trace!({ foo = 2, bar.baz = 79 }, "quux {:?}", true); - trace!({ foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - trace!({ foo = 2, bar.baz = 78 }, "quux"); - trace!({ foo = ?2, bar.baz = %78 }, "quux"); - trace!(target: "foo_events", foo = 3, bar.baz = 2, quux = false); - trace!(target: "foo_events", foo = 3, bar.baz = 3,); - trace!(target: "foo_events", "foo"); - trace!(target: "foo_events", "foo: {}", 3); - trace!(target: "foo_events", { foo = 3, bar.baz = 80 }, "quux"); - trace!(target: "foo_events", { foo = 2, bar.baz = 79 }, "quux {:?}", true); - trace!(target: "foo_events", { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - trace!(target: "foo_events", { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn debug() { - debug!(foo = ?3, bar.baz = %2, quux = false); - debug!(foo = 3, bar.baz = 2, quux = false); - debug!(foo = 3, bar.baz = 3,); - debug!("foo"); - debug!("foo: {}", 3); - debug!({ foo = 3, bar.baz = 80 }, "quux"); - debug!({ foo = 2, bar.baz = 79 }, "quux {:?}", true); - debug!({ foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - debug!({ foo = 2, bar.baz = 78 }, "quux"); - debug!({ foo = ?2, bar.baz = %78 }, "quux"); - debug!(target: "foo_events", foo = 3, bar.baz = 2, quux = false); - debug!(target: "foo_events", foo = 3, bar.baz = 3,); - debug!(target: "foo_events", "foo"); - debug!(target: "foo_events", "foo: {}", 3); - debug!(target: "foo_events", { foo = 3, bar.baz = 80 }, "quux"); - debug!(target: "foo_events", { foo = 2, bar.baz = 79 }, "quux {:?}", true); - debug!(target: "foo_events", { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - debug!(target: "foo_events", { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn info() { - info!(foo = ?3, bar.baz = %2, quux = false); - info!(foo = 3, bar.baz = 2, quux = false); - info!(foo = 3, bar.baz = 3,); - info!("foo"); - info!("foo: {}", 3); - info!({ foo = 3, bar.baz = 80 }, "quux"); - info!({ foo = 2, bar.baz = 79 }, "quux {:?}", true); - info!({ foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - info!({ foo = 2, bar.baz = 78 }, "quux"); - info!({ foo = ?2, bar.baz = %78 }, "quux"); - info!(target: "foo_events", foo = 3, bar.baz = 2, quux = false); - info!(target: "foo_events", foo = 3, bar.baz = 3,); - info!(target: "foo_events", "foo"); - info!(target: "foo_events", "foo: {}", 3); - info!(target: "foo_events", { foo = 3, bar.baz = 80 }, "quux"); - info!(target: "foo_events", { foo = 2, bar.baz = 79 }, "quux {:?}", true); - info!(target: "foo_events", { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - info!(target: "foo_events", { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn warn() { - warn!(foo = ?3, bar.baz = %2, quux = false); - warn!(foo = 3, bar.baz = 2, quux = false); - warn!(foo = 3, bar.baz = 3,); - warn!("foo"); - warn!("foo: {}", 3); - warn!({ foo = 3, bar.baz = 80 }, "quux"); - warn!({ foo = 2, bar.baz = 79 }, "quux {:?}", true); - warn!({ foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - warn!({ foo = 2, bar.baz = 78 }, "quux"); - warn!({ foo = ?2, bar.baz = %78 }, "quux"); - warn!(target: "foo_events", foo = 3, bar.baz = 2, quux = false); - warn!(target: "foo_events", foo = 3, bar.baz = 3,); - warn!(target: "foo_events", "foo"); - warn!(target: "foo_events", "foo: {}", 3); - warn!(target: "foo_events", { foo = 3, bar.baz = 80 }, "quux"); - warn!(target: "foo_events", { foo = 2, bar.baz = 79 }, "quux {:?}", true); - warn!(target: "foo_events", { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - warn!(target: "foo_events", { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn error() { - error!(foo = ?3, bar.baz = %2, quux = false); - error!(foo = 3, bar.baz = 2, quux = false); - error!(foo = 3, bar.baz = 3,); - error!("foo"); - error!("foo: {}", 3); - error!({ foo = 3, bar.baz = 80 }, "quux"); - error!({ foo = 2, bar.baz = 79 }, "quux {:?}", true); - error!({ foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - error!({ foo = 2, bar.baz = 78, }, "quux"); - error!({ foo = ?2, bar.baz = %78 }, "quux"); - error!(target: "foo_events", foo = 3, bar.baz = 2, quux = false); - error!(target: "foo_events", foo = 3, bar.baz = 3,); - error!(target: "foo_events", "foo"); - error!(target: "foo_events", "foo: {}", 3); - error!(target: "foo_events", { foo = 3, bar.baz = 80 }, "quux"); - error!(target: "foo_events", { foo = 2, bar.baz = 79 }, "quux {:?}", true); - error!(target: "foo_events", { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - error!(target: "foo_events", { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn event_root() { - event!(Level::DEBUG, parent: None, foo = ?3, bar.baz = %2, quux = false); - event!( - Level::DEBUG, - parent: None, - foo = 3, - bar.baz = 2, - quux = false - ); - event!(Level::DEBUG, parent: None, foo = 3, bar.baz = 3,); - event!(Level::DEBUG, parent: None, "foo"); - event!(Level::DEBUG, parent: None, "foo: {}", 3); - event!(Level::DEBUG, parent: None, { foo = 3, bar.baz = 80 }, "quux"); - event!(Level::DEBUG, parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - event!(Level::DEBUG, parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - event!(Level::DEBUG, parent: None, { foo = ?2, bar.baz = %78 }, "quux"); - event!(target: "foo_events", Level::DEBUG, parent: None, foo = 3, bar.baz = 2, quux = false); - event!(target: "foo_events", Level::DEBUG, parent: None, foo = 3, bar.baz = 3,); - event!(target: "foo_events", Level::DEBUG, parent: None, "foo"); - event!(target: "foo_events", Level::DEBUG, parent: None, "foo: {}", 3); - event!(target: "foo_events", Level::DEBUG, parent: None, { foo = 3, bar.baz = 80 }, "quux"); - event!(target: "foo_events", Level::DEBUG, parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - event!(target: "foo_events", Level::DEBUG, parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - event!(target: "foo_events", Level::DEBUG, parent: None, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn trace_root() { - trace!(parent: None, foo = ?3, bar.baz = %2, quux = false); - trace!(parent: None, foo = 3, bar.baz = 2, quux = false); - trace!(parent: None, foo = 3, bar.baz = 3,); - trace!(parent: None, "foo"); - trace!(parent: None, "foo: {}", 3); - trace!(parent: None, { foo = 3, bar.baz = 80 }, "quux"); - trace!(parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - trace!(parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - trace!(parent: None, { foo = 2, bar.baz = 78 }, "quux"); - trace!(parent:None, { foo = ?2, bar.baz = %78 }, "quux"); - trace!(target: "foo_events", parent: None, foo = 3, bar.baz = 2, quux = false); - trace!(target: "foo_events", parent: None, foo = 3, bar.baz = 3,); - trace!(target: "foo_events", parent: None, "foo"); - trace!(target: "foo_events", parent: None, "foo: {}", 3); - trace!(target: "foo_events", parent: None, { foo = 3, bar.baz = 80 }, "quux"); - trace!(target: "foo_events", parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - trace!(target: "foo_events", parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - trace!(target: "foo_events", parent: None, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn debug_root() { - debug!(parent: None, foo = ?3, bar.baz = %2, quux = false); - debug!(parent: None, foo = 3, bar.baz = 2, quux = false); - debug!(parent: None, foo = 3, bar.baz = 3,); - debug!(parent: None, "foo"); - debug!(parent: None, "foo: {}", 3); - debug!(parent: None, { foo = 3, bar.baz = 80 }, "quux"); - debug!(parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - debug!(parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - debug!(parent: None, { foo = 2, bar.baz = 78 }, "quux"); - debug!(parent: None, { foo = ?2, bar.baz = %78 }, "quux"); - debug!(target: "foo_events", parent: None, foo = 3, bar.baz = 2, quux = false); - debug!(target: "foo_events", parent: None, foo = 3, bar.baz = 3,); - debug!(target: "foo_events", parent: None, "foo"); - debug!(target: "foo_events", parent: None, "foo: {}", 3); - debug!(target: "foo_events", parent: None, { foo = 3, bar.baz = 80 }, "quux"); - debug!(target: "foo_events", parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - debug!(target: "foo_events", parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - debug!(target: "foo_events", parent: None, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn info_root() { - info!(parent: None, foo = ?3, bar.baz = %2, quux = false); - info!(parent: None, foo = 3, bar.baz = 2, quux = false); - info!(parent: None, foo = 3, bar.baz = 3,); - info!(parent: None, "foo"); - info!(parent: None, "foo: {}", 3); - info!(parent: None, { foo = 3, bar.baz = 80 }, "quux"); - info!(parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - info!(parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - info!(parent: None, { foo = 2, bar.baz = 78 }, "quux"); - info!(parent: None, { foo = ?2, bar.baz = %78 }, "quux"); - info!(target: "foo_events", parent: None, foo = 3, bar.baz = 2, quux = false); - info!(target: "foo_events", parent: None, foo = 3, bar.baz = 3,); - info!(target: "foo_events", parent: None, "foo"); - info!(target: "foo_events", parent: None, "foo: {}", 3); - info!(target: "foo_events", parent: None, { foo = 3, bar.baz = 80 }, "quux"); - info!(target: "foo_events", parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - info!(target: "foo_events", parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - info!(target: "foo_events", parent: None, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn warn_root() { - warn!(parent: None, foo = ?3, bar.baz = %2, quux = false); - warn!(parent: None, foo = 3, bar.baz = 2, quux = false); - warn!(parent: None, foo = 3, bar.baz = 3,); - warn!(parent: None, "foo"); - warn!(parent: None, "foo: {}", 3); - warn!(parent: None, { foo = 3, bar.baz = 80 }, "quux"); - warn!(parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - warn!(parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - warn!(parent: None, { foo = 2, bar.baz = 78 }, "quux"); - warn!(parent: None, { foo = ?2, bar.baz = %78 }, "quux"); - warn!(target: "foo_events", parent: None, foo = 3, bar.baz = 2, quux = false); - warn!(target: "foo_events", parent: None, foo = 3, bar.baz = 3,); - warn!(target: "foo_events", parent: None, "foo"); - warn!(target: "foo_events", parent: None, "foo: {}", 3); - warn!(target: "foo_events", parent: None, { foo = 3, bar.baz = 80 }, "quux"); - warn!(target: "foo_events", parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - warn!(target: "foo_events", parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - warn!(target: "foo_events", parent: None, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn error_root() { - error!(parent: None, foo = ?3, bar.baz = %2, quux = false); - error!(parent: None, foo = 3, bar.baz = 2, quux = false); - error!(parent: None, foo = 3, bar.baz = 3,); - error!(parent: None, "foo"); - error!(parent: None, "foo: {}", 3); - error!(parent: None, { foo = 3, bar.baz = 80 }, "quux"); - error!(parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - error!(parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - error!(parent: None, { foo = 2, bar.baz = 78 }, "quux"); - error!(parent: None, { foo = ?2, bar.baz = %78 }, "quux"); - error!(target: "foo_events", parent: None, foo = 3, bar.baz = 2, quux = false); - error!(target: "foo_events", parent: None, foo = 3, bar.baz = 3,); - error!(target: "foo_events", parent: None, "foo"); - error!(target: "foo_events", parent: None, "foo: {}", 3); - error!(target: "foo_events", parent: None, { foo = 3, bar.baz = 80 }, "quux"); - error!(target: "foo_events", parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - error!(target: "foo_events", parent: None, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - error!(target: "foo_events", parent: None, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn event_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - event!(Level::DEBUG, parent: &p, foo = ?3, bar.baz = %2, quux = false); - event!(Level::DEBUG, parent: &p, foo = 3, bar.baz = 2, quux = false); - event!(Level::DEBUG, parent: &p, foo = 3, bar.baz = 3,); - event!(Level::DEBUG, parent: &p, "foo"); - event!(Level::DEBUG, parent: &p, "foo: {}", 3); - event!(Level::DEBUG, parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - event!(Level::DEBUG, parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - event!(Level::DEBUG, parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - event!(Level::DEBUG, parent: &p, { foo = ?2, bar.baz = %78 }, "quux"); - event!(target: "foo_events", Level::DEBUG, parent: &p, foo = 3, bar.baz = 2, quux = false); - event!(target: "foo_events", Level::DEBUG, parent: &p, foo = 3, bar.baz = 3,); - event!(target: "foo_events", Level::DEBUG, parent: &p, "foo"); - event!(target: "foo_events", Level::DEBUG, parent: &p, "foo: {}", 3); - event!(target: "foo_events", Level::DEBUG, parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - event!(target: "foo_events", Level::DEBUG, parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - event!(target: "foo_events", Level::DEBUG, parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - event!(target: "foo_events", Level::DEBUG, parent: &p, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn trace_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - trace!(parent: &p, foo = ?3, bar.baz = %2, quux = false); - trace!(parent: &p, foo = 3, bar.baz = 2, quux = false); - trace!(parent: &p, foo = 3, bar.baz = 3,); - trace!(parent: &p, "foo"); - trace!(parent: &p, "foo: {}", 3); - trace!(parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - trace!(parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - trace!(parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - trace!(parent: &p, { foo = 2, bar.baz = 78 }, "quux"); - trace!(parent: &p, { foo = ?2, bar.baz = %78 }, "quux"); - trace!(target: "foo_events", parent: &p, foo = 3, bar.baz = 2, quux = false); - trace!(target: "foo_events", parent: &p, foo = 3, bar.baz = 3,); - trace!(target: "foo_events", parent: &p, "foo"); - trace!(target: "foo_events", parent: &p, "foo: {}", 3); - trace!(target: "foo_events", parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - trace!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - trace!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - trace!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn debug_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - debug!(parent: &p, foo = ?3, bar.baz = %2, quux = false); - debug!(parent: &p, foo = 3, bar.baz = 2, quux = false); - debug!(parent: &p, foo = 3, bar.baz = 3,); - debug!(parent: &p, "foo"); - debug!(parent: &p, "foo: {}", 3); - debug!(parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - debug!(parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - debug!(parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - debug!(parent: &p, { foo = 2, bar.baz = 78 }, "quux"); - debug!(parent: &p, { foo = ?2, bar.baz = %78 }, "quux"); - debug!(target: "foo_events", parent: &p, foo = 3, bar.baz = 2, quux = false); - debug!(target: "foo_events", parent: &p, foo = 3, bar.baz = 3,); - debug!(target: "foo_events", parent: &p, "foo"); - debug!(target: "foo_events", parent: &p, "foo: {}", 3); - debug!(target: "foo_events", parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - debug!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - debug!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - debug!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn info_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - info!(parent: &p, foo = ?3, bar.baz = %2, quux = false); - info!(parent: &p, foo = 3, bar.baz = 2, quux = false); - info!(parent: &p, foo = 3, bar.baz = 3,); - info!(parent: &p, "foo"); - info!(parent: &p, "foo: {}", 3); - info!(parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - info!(parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - info!(parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - info!(parent: &p, { foo = 2, bar.baz = 78 }, "quux"); - info!(parent: &p, { foo = ?2, bar.baz = %78 }, "quux"); - info!(target: "foo_events", parent: &p, foo = 3, bar.baz = 2, quux = false); - info!(target: "foo_events", parent: &p, foo = 3, bar.baz = 3,); - info!(target: "foo_events", parent: &p, "foo"); - info!(target: "foo_events", parent: &p, "foo: {}", 3); - info!(target: "foo_events", parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - info!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - info!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - info!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn warn_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - warn!(parent: &p, foo = ?3, bar.baz = %2, quux = false); - warn!(parent: &p, foo = 3, bar.baz = 2, quux = false); - warn!(parent: &p, foo = 3, bar.baz = 3,); - warn!(parent: &p, "foo"); - warn!(parent: &p, "foo: {}", 3); - warn!(parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - warn!(parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - warn!(parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - warn!(parent: &p, { foo = 2, bar.baz = 78 }, "quux"); - warn!(parent: &p, { foo = ?2, bar.baz = %78 }, "quux"); - warn!(target: "foo_events", parent: &p, foo = 3, bar.baz = 2, quux = false); - warn!(target: "foo_events", parent: &p, foo = 3, bar.baz = 3,); - warn!(target: "foo_events", parent: &p, "foo"); - warn!(target: "foo_events", parent: &p, "foo: {}", 3); - warn!(target: "foo_events", parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - warn!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - warn!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - warn!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn error_with_parent() { - let p = span!(Level::TRACE, "im_a_parent!"); - error!(parent: &p, foo = ?3, bar.baz = %2, quux = false); - error!(parent: &p, foo = 3, bar.baz = 2, quux = false); - error!(parent: &p, foo = 3, bar.baz = 3,); - error!(parent: &p, "foo"); - error!(parent: &p, "foo: {}", 3); - error!(parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - error!(parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - error!(parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - error!(parent: &p, { foo = 2, bar.baz = 78 }, "quux"); - error!(parent: &p, { foo = ?2, bar.baz = %78 }, "quux"); - error!(target: "foo_events", parent: &p, foo = 3, bar.baz = 2, quux = false); - error!(target: "foo_events", parent: &p, foo = 3, bar.baz = 3,); - error!(target: "foo_events", parent: &p, "foo"); - error!(target: "foo_events", parent: &p, "foo: {}", 3); - error!(target: "foo_events", parent: &p, { foo = 3, bar.baz = 80 }, "quux"); - error!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}", true); - error!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 79 }, "quux {:?}, {quux}", true, quux = false); - error!(target: "foo_events", parent: &p, { foo = 2, bar.baz = 78, }, "quux"); -} - -#[test] -fn field_shorthand_only() { - #[derive(Debug)] - struct Position { - x: f32, - y: f32, - } - let pos = Position { - x: 3.234, - y: -1.223, - }; - - trace!(?pos.x, ?pos.y); - debug!(?pos.x, ?pos.y); - info!(?pos.x, ?pos.y); - warn!(?pos.x, ?pos.y); - error!(?pos.x, ?pos.y); - event!(Level::TRACE, ?pos.x, ?pos.y); -} - -#[test] -fn callsite_macro_api() { - // This test should catch any inadvertant breaking changes - // caused bu changes to the macro. - let _callsite = callsite! { - name: "test callsite", - kind: tokio_trace::metadata::Kind::EVENT, - target: "test target", - level: tokio_trace::Level::TRACE, - fields: foo, bar, - }; - let _callsite = callsite! { - name: "test callsite", - kind: tokio_trace::metadata::Kind::SPAN, - level: tokio_trace::Level::TRACE, - fields: foo, - }; - let _callsite = callsite! { - name: "test callsite", - kind: tokio_trace::metadata::Kind::SPAN, - fields: foo, - }; -} diff --git a/tokio-trace/tests/span.rs b/tokio-trace/tests/span.rs deleted file mode 100644 index d842da1c8..000000000 --- a/tokio-trace/tests/span.rs +++ /dev/null @@ -1,723 +0,0 @@ -#[macro_use] -extern crate tokio_trace; -mod support; - -use self::support::*; -use std::thread; -use tokio_trace::{ - field::{debug, display}, - subscriber::with_default, - Level, Span, -}; - -#[test] -fn handles_to_the_same_span_are_equal() { - // Create a mock subscriber that will return `true` on calls to - // `Subscriber::enabled`, so that the spans will be constructed. We - // won't enter any spans in this test, so the subscriber won't actually - // expect to see any spans. - with_default(subscriber::mock().run(), || { - let foo1 = span!(Level::TRACE, "foo"); - let foo2 = foo1.clone(); - // Two handles that point to the same span are equal. - assert_eq!(foo1, foo2); - }); -} - -#[test] -fn handles_to_different_spans_are_not_equal() { - with_default(subscriber::mock().run(), || { - // Even though these spans have the same name and fields, they will have - // differing metadata, since they were created on different lines. - let foo1 = span!(Level::TRACE, "foo", bar = 1u64, baz = false); - let foo2 = span!(Level::TRACE, "foo", bar = 1u64, baz = false); - - assert_ne!(foo1, foo2); - }); -} - -#[test] -fn handles_to_different_spans_with_the_same_metadata_are_not_equal() { - // Every time time this function is called, it will return a _new - // instance_ of a span with the same metadata, name, and fields. - fn make_span() -> Span { - span!(Level::TRACE, "foo", bar = 1u64, baz = false) - } - - with_default(subscriber::mock().run(), || { - let foo1 = make_span(); - let foo2 = make_span(); - - assert_ne!(foo1, foo2); - // assert_ne!(foo1.data(), foo2.data()); - }); -} - -#[test] -fn spans_always_go_to_the_subscriber_that_tagged_them() { - let subscriber1 = subscriber::mock() - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run(); - let subscriber2 = subscriber::mock().run(); - - let foo = with_default(subscriber1, || { - let foo = span!(Level::TRACE, "foo"); - foo.in_scope(|| {}); - foo - }); - // Even though we enter subscriber 2's context, the subscriber that - // tagged the span should see the enter/exit. - with_default(subscriber2, move || foo.in_scope(|| {})); -} - -#[test] -fn spans_always_go_to_the_subscriber_that_tagged_them_even_across_threads() { - let subscriber1 = subscriber::mock() - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run(); - let foo = with_default(subscriber1, || { - let foo = span!(Level::TRACE, "foo"); - foo.in_scope(|| {}); - foo - }); - - // Even though we enter subscriber 2's context, the subscriber that - // tagged the span should see the enter/exit. - thread::spawn(move || { - with_default(subscriber::mock().run(), || { - foo.in_scope(|| {}); - }) - }) - .join() - .unwrap(); -} - -#[test] -fn dropping_a_span_calls_drop_span() { - let (subscriber, handle) = subscriber::mock() - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - with_default(subscriber, || { - let span = span!(Level::TRACE, "foo"); - span.in_scope(|| {}); - drop(span); - }); - - handle.assert_finished(); -} - -#[test] -fn span_closes_after_event() { - let (subscriber, handle) = subscriber::mock() - .enter(span::mock().named("foo")) - .event(event::mock()) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - with_default(subscriber, || { - span!(Level::TRACE, "foo").in_scope(|| { - event!(Level::DEBUG, {}, "my event!"); - }); - }); - - handle.assert_finished(); -} - -#[test] -fn new_span_after_event() { - let (subscriber, handle) = subscriber::mock() - .enter(span::mock().named("foo")) - .event(event::mock()) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .enter(span::mock().named("bar")) - .exit(span::mock().named("bar")) - .drop_span(span::mock().named("bar")) - .done() - .run_with_handle(); - with_default(subscriber, || { - span!(Level::TRACE, "foo").in_scope(|| { - event!(Level::DEBUG, {}, "my event!"); - }); - span!(Level::TRACE, "bar").in_scope(|| {}); - }); - - handle.assert_finished(); -} - -#[test] -fn event_outside_of_span() { - let (subscriber, handle) = subscriber::mock() - .event(event::mock()) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - with_default(subscriber, || { - debug!("my event!"); - span!(Level::TRACE, "foo").in_scope(|| {}); - }); - - handle.assert_finished(); -} - -#[test] -fn cloning_a_span_calls_clone_span() { - let (subscriber, handle) = subscriber::mock() - .clone_span(span::mock().named("foo")) - .run_with_handle(); - with_default(subscriber, || { - let span = span!(Level::TRACE, "foo"); - let _span2 = span.clone(); - }); - - handle.assert_finished(); -} - -#[test] -fn drop_span_when_exiting_dispatchers_context() { - let (subscriber, handle) = subscriber::mock() - .clone_span(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .run_with_handle(); - with_default(subscriber, || { - let span = span!(Level::TRACE, "foo"); - let _span2 = span.clone(); - drop(span); - }); - - handle.assert_finished(); -} - -#[test] -fn clone_and_drop_span_always_go_to_the_subscriber_that_tagged_the_span() { - let (subscriber1, handle1) = subscriber::mock() - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .clone_span(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .run_with_handle(); - let subscriber2 = subscriber::mock().done().run(); - - let foo = with_default(subscriber1, || { - let foo = span!(Level::TRACE, "foo"); - foo.in_scope(|| {}); - foo - }); - // Even though we enter subscriber 2's context, the subscriber that - // tagged the span should see the enter/exit. - with_default(subscriber2, move || { - let foo2 = foo.clone(); - foo.in_scope(|| {}); - drop(foo); - drop(foo2); - }); - - handle1.assert_finished(); -} - -#[test] -fn span_closes_when_exited() { - let (subscriber, handle) = subscriber::mock() - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - with_default(subscriber, || { - let foo = span!(Level::TRACE, "foo"); - - foo.in_scope(|| {}); - - drop(foo); - }); - - handle.assert_finished(); -} - -#[test] -fn enter() { - let (subscriber, handle) = subscriber::mock() - .enter(span::mock().named("foo")) - .event(event::mock()) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - with_default(subscriber, || { - let foo = span!(Level::TRACE, "foo"); - let _enter = foo.enter(); - debug!("dropping guard..."); - }); - - handle.assert_finished(); -} - -#[test] -fn moved_field() { - let (subscriber, handle) = subscriber::mock() - .new_span( - span::mock().named("foo").with_field( - field::mock("bar") - .with_value(&display("hello from my span")) - .only(), - ), - ) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - with_default(subscriber, || { - let from = "my span"; - let span = span!( - Level::TRACE, - "foo", - bar = display(format!("hello from {}", from)) - ); - span.in_scope(|| {}); - }); - - handle.assert_finished(); -} - -#[test] -fn dotted_field_name() { - let (subscriber, handle) = subscriber::mock() - .new_span( - span::mock() - .named("foo") - .with_field(field::mock("fields.bar").with_value(&true).only()), - ) - .done() - .run_with_handle(); - with_default(subscriber, || { - span!(Level::TRACE, "foo", fields.bar = true); - }); - - handle.assert_finished(); -} - -#[test] -fn borrowed_field() { - let (subscriber, handle) = subscriber::mock() - .new_span( - span::mock().named("foo").with_field( - field::mock("bar") - .with_value(&display("hello from my span")) - .only(), - ), - ) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - - with_default(subscriber, || { - let from = "my span"; - let mut message = format!("hello from {}", from); - let span = span!(Level::TRACE, "foo", bar = display(&message)); - span.in_scope(|| { - message.insert_str(10, " inside"); - }); - }); - - handle.assert_finished(); -} - -#[test] -// If emitting log instrumentation, this gets moved anyway, breaking the test. -#[cfg(not(feature = "log"))] -fn move_field_out_of_struct() { - use tokio_trace::field::debug; - - #[derive(Debug)] - struct Position { - x: f32, - y: f32, - } - - let pos = Position { - x: 3.234, - y: -1.223, - }; - let (subscriber, handle) = subscriber::mock() - .new_span( - span::mock().named("foo").with_field( - field::mock("x") - .with_value(&debug(3.234)) - .and(field::mock("y").with_value(&debug(-1.223))) - .only(), - ), - ) - .new_span( - span::mock() - .named("bar") - .with_field(field::mock("position").with_value(&debug(&pos)).only()), - ) - .run_with_handle(); - - with_default(subscriber, || { - let pos = Position { - x: 3.234, - y: -1.223, - }; - let foo = span!(Level::TRACE, "foo", x = debug(pos.x), y = debug(pos.y)); - let bar = span!(Level::TRACE, "bar", position = debug(pos)); - foo.in_scope(|| {}); - bar.in_scope(|| {}); - }); - - handle.assert_finished(); -} - -// TODO(#1138): determine a new syntax for uninitialized span fields, and -// re-enable these. -/* -#[test] -fn add_field_after_new_span() { - let (subscriber, handle) = subscriber::mock() - .new_span( - span::mock() - .named("foo") - .with_field(field::mock("bar").with_value(&5) - .and(field::mock("baz").with_value).only()), - ) - .record( - span::mock().named("foo"), - field::mock("baz").with_value(&true).only(), - ) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - - with_default(subscriber, || { - let span = span!(Level::TRACE, "foo", bar = 5, baz = false); - span.record("baz", &true); - span.in_scope(|| {}) - }); - - handle.assert_finished(); -} - -#[test] -fn add_fields_only_after_new_span() { - let (subscriber, handle) = subscriber::mock() - .new_span(span::mock().named("foo")) - .record( - span::mock().named("foo"), - field::mock("bar").with_value(&5).only(), - ) - .record( - span::mock().named("foo"), - field::mock("baz").with_value(&true).only(), - ) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - - with_default(subscriber, || { - let span = span!(Level::TRACE, "foo", bar = _, baz = _); - span.record("bar", &5); - span.record("baz", &true); - span.in_scope(|| {}) - }); - - handle.assert_finished(); -} -*/ - -#[test] -fn record_new_value_for_field() { - let (subscriber, handle) = subscriber::mock() - .new_span( - span::mock().named("foo").with_field( - field::mock("bar") - .with_value(&5) - .and(field::mock("baz").with_value(&false)) - .only(), - ), - ) - .record( - span::mock().named("foo"), - field::mock("baz").with_value(&true).only(), - ) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - - with_default(subscriber, || { - let span = span!(Level::TRACE, "foo", bar = 5, baz = false); - span.record("baz", &true); - span.in_scope(|| {}) - }); - - handle.assert_finished(); -} - -#[test] -fn record_new_values_for_fields() { - let (subscriber, handle) = subscriber::mock() - .new_span( - span::mock().named("foo").with_field( - field::mock("bar") - .with_value(&4) - .and(field::mock("baz").with_value(&false)) - .only(), - ), - ) - .record( - span::mock().named("foo"), - field::mock("bar").with_value(&5).only(), - ) - .record( - span::mock().named("foo"), - field::mock("baz").with_value(&true).only(), - ) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - - with_default(subscriber, || { - let span = span!(Level::TRACE, "foo", bar = 4, baz = false); - span.record("bar", &5); - span.record("baz", &true); - span.in_scope(|| {}) - }); - - handle.assert_finished(); -} - -#[test] -fn new_span_with_target_and_log_level() { - let (subscriber, handle) = subscriber::mock() - .new_span( - span::mock() - .named("foo") - .with_target("app_span") - .at_level(Level::DEBUG), - ) - .done() - .run_with_handle(); - - with_default(subscriber, || { - span!(Level::DEBUG, target: "app_span", "foo"); - }); - - handle.assert_finished(); -} - -#[test] -fn explicit_root_span_is_root() { - let (subscriber, handle) = subscriber::mock() - .new_span(span::mock().named("foo").with_explicit_parent(None)) - .done() - .run_with_handle(); - - with_default(subscriber, || { - span!(Level::TRACE, parent: None, "foo"); - }); - - handle.assert_finished(); -} - -#[test] -fn explicit_root_span_is_root_regardless_of_ctx() { - let (subscriber, handle) = subscriber::mock() - .new_span(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .new_span(span::mock().named("bar").with_explicit_parent(None)) - .exit(span::mock().named("foo")) - .done() - .run_with_handle(); - - with_default(subscriber, || { - span!(Level::TRACE, "foo").in_scope(|| { - span!(Level::TRACE, parent: None, "bar"); - }) - }); - - handle.assert_finished(); -} - -#[test] -fn explicit_child() { - let (subscriber, handle) = subscriber::mock() - .new_span(span::mock().named("foo")) - .new_span(span::mock().named("bar").with_explicit_parent(Some("foo"))) - .done() - .run_with_handle(); - - with_default(subscriber, || { - let foo = span!(Level::TRACE, "foo"); - span!(Level::TRACE, parent: foo.id(), "bar"); - }); - - handle.assert_finished(); -} - -#[test] -fn explicit_child_at_levels() { - let (subscriber, handle) = subscriber::mock() - .new_span(span::mock().named("foo")) - .new_span(span::mock().named("a").with_explicit_parent(Some("foo"))) - .new_span(span::mock().named("b").with_explicit_parent(Some("foo"))) - .new_span(span::mock().named("c").with_explicit_parent(Some("foo"))) - .new_span(span::mock().named("d").with_explicit_parent(Some("foo"))) - .new_span(span::mock().named("e").with_explicit_parent(Some("foo"))) - .done() - .run_with_handle(); - - with_default(subscriber, || { - let foo = span!(Level::TRACE, "foo"); - trace_span!(parent: foo.id(), "a"); - debug_span!(parent: foo.id(), "b"); - info_span!(parent: foo.id(), "c"); - warn_span!(parent: foo.id(), "d"); - error_span!(parent: foo.id(), "e"); - }); - - handle.assert_finished(); -} - -#[test] -fn explicit_child_regardless_of_ctx() { - let (subscriber, handle) = subscriber::mock() - .new_span(span::mock().named("foo")) - .new_span(span::mock().named("bar")) - .enter(span::mock().named("bar")) - .new_span(span::mock().named("baz").with_explicit_parent(Some("foo"))) - .exit(span::mock().named("bar")) - .done() - .run_with_handle(); - - with_default(subscriber, || { - let foo = span!(Level::TRACE, "foo"); - span!(Level::TRACE, "bar").in_scope(|| span!(Level::TRACE, parent: foo.id(), "baz")) - }); - - handle.assert_finished(); -} - -#[test] -fn contextual_root() { - let (subscriber, handle) = subscriber::mock() - .new_span(span::mock().named("foo").with_contextual_parent(None)) - .done() - .run_with_handle(); - - with_default(subscriber, || { - span!(Level::TRACE, "foo"); - }); - - handle.assert_finished(); -} - -#[test] -fn contextual_child() { - let (subscriber, handle) = subscriber::mock() - .new_span(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .new_span( - span::mock() - .named("bar") - .with_contextual_parent(Some("foo")), - ) - .exit(span::mock().named("foo")) - .done() - .run_with_handle(); - - with_default(subscriber, || { - span!(Level::TRACE, "foo").in_scope(|| { - span!(Level::TRACE, "bar"); - }) - }); - - handle.assert_finished(); -} - -#[test] -fn display_shorthand() { - let (subscriber, handle) = subscriber::mock() - .new_span( - span::mock().named("my_span").with_field( - field::mock("my_field") - .with_value(&display("hello world")) - .only(), - ), - ) - .done() - .run_with_handle(); - with_default(subscriber, || { - span!(Level::TRACE, "my_span", my_field = %"hello world"); - }); - - handle.assert_finished(); -} - -#[test] -fn debug_shorthand() { - let (subscriber, handle) = subscriber::mock() - .new_span( - span::mock().named("my_span").with_field( - field::mock("my_field") - .with_value(&debug("hello world")) - .only(), - ), - ) - .done() - .run_with_handle(); - with_default(subscriber, || { - span!(Level::TRACE, "my_span", my_field = ?"hello world"); - }); - - handle.assert_finished(); -} - -#[test] -fn both_shorthands() { - let (subscriber, handle) = subscriber::mock() - .new_span( - span::mock().named("my_span").with_field( - field::mock("display_field") - .with_value(&display("hello world")) - .and(field::mock("debug_field").with_value(&debug("hello world"))) - .only(), - ), - ) - .done() - .run_with_handle(); - with_default(subscriber, || { - span!(Level::TRACE, "my_span", display_field = %"hello world", debug_field = ?"hello world"); - }); - - handle.assert_finished(); -} diff --git a/tokio-trace/tests/subscriber.rs b/tokio-trace/tests/subscriber.rs deleted file mode 100644 index 99635b8aa..000000000 --- a/tokio-trace/tests/subscriber.rs +++ /dev/null @@ -1,48 +0,0 @@ -#[macro_use] -extern crate tokio_trace; -use tokio_trace::{ - span, - subscriber::{with_default, Interest, Subscriber}, - Event, Level, Metadata, -}; - -#[test] -fn event_macros_dont_infinite_loop() { - // This test ensures that an event macro within a subscriber - // won't cause an infinite loop of events. - struct TestSubscriber; - impl Subscriber for TestSubscriber { - fn register_callsite(&self, _: &Metadata) -> Interest { - // Always return sometimes so that `enabled` will be called - // (which can loop). - Interest::sometimes() - } - - fn enabled(&self, meta: &Metadata) -> bool { - assert!(meta.fields().iter().any(|f| f.name() == "foo")); - event!(Level::TRACE, bar = false); - true - } - - fn new_span(&self, _: &span::Attributes) -> span::Id { - span::Id::from_u64(0xAAAA) - } - - fn record(&self, _: &span::Id, _: &span::Record) {} - - fn record_follows_from(&self, _: &span::Id, _: &span::Id) {} - - fn event(&self, event: &Event) { - assert!(event.metadata().fields().iter().any(|f| f.name() == "foo")); - event!(Level::TRACE, baz = false); - } - - fn enter(&self, _: &span::Id) {} - - fn exit(&self, _: &span::Id) {} - } - - with_default(TestSubscriber, || { - event!(Level::TRACE, foo = false); - }) -} diff --git a/tokio-trace/tests/support/event.rs b/tokio-trace/tests/support/event.rs deleted file mode 100644 index de51848be..000000000 --- a/tokio-trace/tests/support/event.rs +++ /dev/null @@ -1,93 +0,0 @@ -#![allow(missing_docs)] -use super::{field, metadata}; - -use std::fmt; - -/// A mock event. -/// -/// This is intended for use with the mock subscriber API in the -/// `subscriber` module. -#[derive(Debug, Default, Eq, PartialEq)] -pub struct MockEvent { - pub fields: Option, - metadata: metadata::Expect, -} - -pub fn mock() -> MockEvent { - MockEvent { - ..Default::default() - } -} - -impl MockEvent { - pub fn named(self, name: I) -> Self - where - I: Into, - { - Self { - metadata: metadata::Expect { - name: Some(name.into()), - ..self.metadata - }, - ..self - } - } - - pub fn with_fields(self, fields: I) -> Self - where - I: Into, - { - Self { - fields: Some(fields.into()), - ..self - } - } - - pub fn at_level(self, level: tokio_trace::Level) -> Self { - Self { - metadata: metadata::Expect { - level: Some(level), - ..self.metadata - }, - ..self - } - } - - pub fn with_target(self, target: I) -> Self - where - I: Into, - { - Self { - metadata: metadata::Expect { - target: Some(target.into()), - ..self.metadata - }, - ..self - } - } - - pub(in support) fn check(self, event: &tokio_trace::Event) { - let meta = event.metadata(); - let name = meta.name(); - self.metadata.check(meta, format_args!("event {}", name)); - assert!(meta.is_event(), "expected an event but got {:?}", event); - if let Some(mut expected_fields) = self.fields { - let mut checker = expected_fields.checker(format!("{}", name)); - event.record(&mut checker); - checker.finish(); - } - } -} - -impl fmt::Display for MockEvent { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "an event")?; - if let Some(ref name) = self.metadata.name { - write!(f, " named {:?}", name)?; - } - if let Some(ref fields) = self.fields { - write!(f, " with {}", fields)? - } - Ok(()) - } -} diff --git a/tokio-trace/tests/support/field.rs b/tokio-trace/tests/support/field.rs deleted file mode 100644 index 469fac1e1..000000000 --- a/tokio-trace/tests/support/field.rs +++ /dev/null @@ -1,225 +0,0 @@ -use tokio_trace::{ - callsite::Callsite, - field::{self, Field, Value, Visit}, - metadata::Kind, -}; - -use std::{collections::HashMap, fmt}; - -#[derive(Default, Debug, Eq, PartialEq)] -pub struct Expect { - fields: HashMap, - only: bool, -} - -#[derive(Debug)] -pub struct MockField { - name: String, - value: MockValue, -} - -#[derive(Debug, Eq, PartialEq)] -pub enum MockValue { - I64(i64), - U64(u64), - Bool(bool), - Str(String), - Debug(String), - Any, -} - -pub fn mock(name: K) -> MockField -where - String: From, -{ - MockField { - name: name.into(), - value: MockValue::Any, - } -} - -impl MockField { - /// Expect a field with the given name and value. - pub fn with_value(self, value: &Value) -> Self { - Self { - value: MockValue::from(value), - ..self - } - } - - pub fn and(self, other: MockField) -> Expect { - Expect { - fields: HashMap::new(), - only: false, - } - .and(self) - .and(other) - } - - pub fn only(self) -> Expect { - Expect { - fields: HashMap::new(), - only: true, - } - .and(self) - } -} - -impl Into for MockField { - fn into(self) -> Expect { - Expect { - fields: HashMap::new(), - only: false, - } - .and(self) - } -} - -impl Expect { - pub fn and(mut self, field: MockField) -> Self { - self.fields.insert(field.name, field.value); - self - } - - /// Indicates that no fields other than those specified should be expected. - pub fn only(self) -> Self { - Self { only: true, ..self } - } - - fn compare_or_panic(&mut self, name: &str, value: &Value, ctx: &str) { - let value = value.into(); - match self.fields.remove(name) { - Some(MockValue::Any) => {} - Some(expected) => assert!( - expected == value, - "\nexpected `{}` to contain:\n\t`{}{}`\nbut got:\n\t`{}{}`", - ctx, - name, - expected, - name, - value - ), - None if self.only => panic!( - "\nexpected `{}` to contain only:\n\t`{}`\nbut got:\n\t`{}{}`", - ctx, self, name, value - ), - _ => {} - } - } - - pub fn checker<'a>(&'a mut self, ctx: String) -> CheckVisitor<'a> { - CheckVisitor { expect: self, ctx } - } - - pub fn is_empty(&self) -> bool { - self.fields.is_empty() - } -} - -impl fmt::Display for MockValue { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - MockValue::I64(v) => write!(f, ": i64 = {:?}", v), - MockValue::U64(v) => write!(f, ": u64 = {:?}", v), - MockValue::Bool(v) => write!(f, ": bool = {:?}", v), - MockValue::Str(v) => write!(f, ": &str = {:?}", v), - MockValue::Debug(v) => write!(f, ": &fmt::Debug = {:?}", v), - MockValue::Any => write!(f, ": _ = _"), - } - } -} - -pub struct CheckVisitor<'a> { - expect: &'a mut Expect, - ctx: String, -} - -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[..]) - } - - fn record_u64(&mut self, field: &Field, value: u64) { - self.expect - .compare_or_panic(field.name(), &value, &self.ctx[..]) - } - - fn record_bool(&mut self, field: &Field, value: bool) { - self.expect - .compare_or_panic(field.name(), &value, &self.ctx[..]) - } - - fn record_str(&mut self, field: &Field, value: &str) { - self.expect - .compare_or_panic(field.name(), &value, &self.ctx[..]) - } - - fn record_debug(&mut self, field: &Field, value: &fmt::Debug) { - self.expect - .compare_or_panic(field.name(), &field::debug(value), &self.ctx) - } -} - -impl<'a> CheckVisitor<'a> { - pub fn finish(self) { - assert!( - self.expect.fields.is_empty(), - "{}missing {}", - self.expect, - self.ctx - ); - } -} - -impl<'a> From<&'a Value> for MockValue { - fn from(value: &'a Value) -> Self { - struct MockValueBuilder { - value: Option, - } - - impl Visit for MockValueBuilder { - fn record_i64(&mut self, _: &Field, value: i64) { - self.value = Some(MockValue::I64(value)); - } - - fn record_u64(&mut self, _: &Field, value: u64) { - self.value = Some(MockValue::U64(value)); - } - - fn record_bool(&mut self, _: &Field, value: bool) { - self.value = Some(MockValue::Bool(value)); - } - - fn record_str(&mut self, _: &Field, value: &str) { - self.value = Some(MockValue::Str(value.to_owned())); - } - - fn record_debug(&mut self, _: &Field, value: &fmt::Debug) { - self.value = Some(MockValue::Debug(format!("{:?}", value))); - } - } - - let fake_field = callsite!(name: "fake", kind: Kind::EVENT, fields: fake_field) - .metadata() - .fields() - .field("fake_field") - .unwrap(); - let mut builder = MockValueBuilder { value: None }; - value.record(&fake_field, &mut builder); - builder - .value - .expect("finish called before a value was recorded") - } -} - -impl fmt::Display for Expect { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "fields ")?; - let entries = self - .fields - .iter() - .map(|(k, v)| (field::display(k), field::display(v))); - f.debug_map().entries(entries).finish() - } -} diff --git a/tokio-trace/tests/support/metadata.rs b/tokio-trace/tests/support/metadata.rs deleted file mode 100644 index 502c04e44..000000000 --- a/tokio-trace/tests/support/metadata.rs +++ /dev/null @@ -1,64 +0,0 @@ -use std::fmt; -use tokio_trace::Metadata; - -#[derive(Debug, Eq, PartialEq, Default)] -pub struct Expect { - pub name: Option, - pub level: Option, - pub target: Option, -} - -impl Expect { - pub(in support) fn check(&self, actual: &Metadata, ctx: fmt::Arguments) { - if let Some(ref expected_name) = self.name { - let name = actual.name(); - assert!( - expected_name == name, - "expected {} to be named `{}`, but got one named `{}`", - ctx, - expected_name, - name - ) - } - - if let Some(ref expected_level) = self.level { - let level = actual.level(); - assert!( - expected_level == level, - "expected {} to be at level `{:?}`, but it was at level `{:?}` instead", - ctx, - expected_level, - level, - ) - } - - if let Some(ref expected_target) = self.target { - let target = actual.target(); - assert!( - expected_target == &target, - "expected {} to have target `{}`, but it had target `{}` instead", - ctx, - expected_target, - target, - ) - } - } -} - -impl fmt::Display for Expect { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(ref name) = self.name { - write!(f, "named `{}`", name)?; - } - - if let Some(ref level) = self.level { - write!(f, " at the `{:?}` level", level)?; - } - - if let Some(ref target) = self.target { - write!(f, " with target `{}`", target)?; - } - - Ok(()) - } -} diff --git a/tokio-trace/tests/support/mod.rs b/tokio-trace/tests/support/mod.rs deleted file mode 100644 index 1bf62ec55..000000000 --- a/tokio-trace/tests/support/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![allow(dead_code)] -pub mod event; -pub mod field; -mod metadata; -pub mod span; -pub mod subscriber; - -extern crate tokio_trace_core; diff --git a/tokio-trace/tests/support/span.rs b/tokio-trace/tests/support/span.rs deleted file mode 100644 index 8d5ce4240..000000000 --- a/tokio-trace/tests/support/span.rs +++ /dev/null @@ -1,178 +0,0 @@ -#![allow(missing_docs)] -use super::{field, metadata}; -use std::fmt; - -/// A mock span. -/// -/// This is intended for use with the mock subscriber API in the -/// `subscriber` module. -#[derive(Debug, Default, Eq, PartialEq)] -pub struct MockSpan { - pub(in support) metadata: metadata::Expect, -} - -#[derive(Debug, Eq, PartialEq)] -pub(in support) enum Parent { - ContextualRoot, - Contextual(String), - ExplicitRoot, - Explicit(String), -} - -#[derive(Debug, Default, Eq, PartialEq)] -pub struct NewSpan { - pub(in support) span: MockSpan, - pub(in support) fields: field::Expect, - pub(in support) parent: Option, -} - -pub fn mock() -> MockSpan { - MockSpan { - ..Default::default() - } -} - -impl MockSpan { - pub fn named(self, name: I) -> Self - where - I: Into, - { - Self { - metadata: metadata::Expect { - name: Some(name.into()), - ..self.metadata - }, - ..self - } - } - - pub fn at_level(self, level: tokio_trace::Level) -> Self { - Self { - metadata: metadata::Expect { - level: Some(level), - ..self.metadata - }, - ..self - } - } - - pub fn with_target(self, target: I) -> Self - where - I: Into, - { - Self { - metadata: metadata::Expect { - target: Some(target.into()), - ..self.metadata - }, - ..self - } - } - - pub fn with_explicit_parent(self, parent: Option<&str>) -> NewSpan { - let parent = match parent { - Some(name) => Parent::Explicit(name.into()), - None => Parent::ExplicitRoot, - }; - NewSpan { - parent: Some(parent), - span: self, - ..Default::default() - } - } - - pub fn with_contextual_parent(self, parent: Option<&str>) -> NewSpan { - let parent = match parent { - Some(name) => Parent::Contextual(name.into()), - None => Parent::ContextualRoot, - }; - NewSpan { - parent: Some(parent), - span: self, - ..Default::default() - } - } - - pub fn name(&self) -> Option<&str> { - self.metadata.name.as_ref().map(String::as_ref) - } - - pub fn with_field(self, fields: I) -> NewSpan - where - I: Into, - { - NewSpan { - span: self, - fields: fields.into(), - ..Default::default() - } - } - - pub(in support) fn check_metadata(&self, actual: &tokio_trace::Metadata) { - self.metadata.check(actual, format_args!("span {}", self)); - assert!(actual.is_span(), "expected a span but got {:?}", actual); - } -} - -impl fmt::Display for MockSpan { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.metadata.name.is_some() { - write!(f, "a span{}", self.metadata) - } else { - write!(f, "any span{}", self.metadata) - } - } -} - -impl Into for MockSpan { - fn into(self) -> NewSpan { - NewSpan { - span: self, - ..Default::default() - } - } -} - -impl NewSpan { - pub fn with_explicit_parent(self, parent: Option<&str>) -> NewSpan { - let parent = match parent { - Some(name) => Parent::Explicit(name.into()), - None => Parent::ExplicitRoot, - }; - NewSpan { - parent: Some(parent), - ..self - } - } - - pub fn with_contextual_parent(self, parent: Option<&str>) -> NewSpan { - let parent = match parent { - Some(name) => Parent::Contextual(name.into()), - None => Parent::ContextualRoot, - }; - NewSpan { - parent: Some(parent), - ..self - } - } - - pub fn with_field(self, fields: I) -> NewSpan - where - I: Into, - { - NewSpan { - fields: fields.into(), - ..self - } - } -} - -impl fmt::Display for NewSpan { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "a new span{}", self.span.metadata)?; - if !self.fields.is_empty() { - write!(f, " with {}", self.fields)?; - } - Ok(()) - } -} diff --git a/tokio-trace/tests/support/subscriber.rs b/tokio-trace/tests/support/subscriber.rs deleted file mode 100644 index 9c976165d..000000000 --- a/tokio-trace/tests/support/subscriber.rs +++ /dev/null @@ -1,409 +0,0 @@ -#![allow(missing_docs)] -use super::{ - event::MockEvent, - field as mock_field, - span::{MockSpan, NewSpan}, -}; -use std::{ - collections::{HashMap, VecDeque}, - fmt, - sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, Mutex, - }, -}; -use tokio_trace::{ - span::{self, Attributes, Id}, - Event, Metadata, Subscriber, -}; - -#[derive(Debug, Eq, PartialEq)] -enum Expect { - Event(MockEvent), - Enter(MockSpan), - Exit(MockSpan), - CloneSpan(MockSpan), - DropSpan(MockSpan), - Visit(MockSpan, mock_field::Expect), - NewSpan(NewSpan), - Nothing, -} - -struct SpanState { - name: &'static str, - refs: usize, -} - -struct Running bool> { - spans: Mutex>, - expected: Arc>>, - current: Mutex>, - ids: AtomicUsize, - filter: F, -} - -pub struct MockSubscriber bool> { - expected: VecDeque, - filter: F, -} - -pub struct MockHandle(Arc>>); - -pub fn mock() -> MockSubscriber bool> { - MockSubscriber { - expected: VecDeque::new(), - filter: (|_: &Metadata| true) as for<'r, 's> fn(&'r Metadata<'s>) -> _, - } -} - -impl MockSubscriber -where - F: Fn(&Metadata) -> bool + 'static, -{ - pub fn enter(mut self, span: MockSpan) -> Self { - self.expected.push_back(Expect::Enter(span)); - self - } - - pub fn event(mut self, event: MockEvent) -> Self { - self.expected.push_back(Expect::Event(event)); - self - } - - pub fn exit(mut self, span: MockSpan) -> Self { - self.expected.push_back(Expect::Exit(span)); - self - } - - pub fn clone_span(mut self, span: MockSpan) -> Self { - self.expected.push_back(Expect::CloneSpan(span)); - self - } - - pub fn drop_span(mut self, span: MockSpan) -> Self { - self.expected.push_back(Expect::DropSpan(span)); - self - } - - pub fn done(mut self) -> Self { - self.expected.push_back(Expect::Nothing); - self - } - - pub fn record(mut self, span: MockSpan, fields: I) -> Self - where - I: Into, - { - self.expected.push_back(Expect::Visit(span, fields.into())); - self - } - - pub fn new_span(mut self, new_span: I) -> Self - where - I: Into, - { - self.expected.push_back(Expect::NewSpan(new_span.into())); - self - } - - pub fn with_filter(self, filter: G) -> MockSubscriber - where - G: Fn(&Metadata) -> bool + 'static, - { - MockSubscriber { - filter, - expected: self.expected, - } - } - - pub fn run(self) -> impl Subscriber { - let (subscriber, _) = self.run_with_handle(); - subscriber - } - - pub fn run_with_handle(self) -> (impl Subscriber, MockHandle) { - let expected = Arc::new(Mutex::new(self.expected)); - let handle = MockHandle(expected.clone()); - let subscriber = Running { - spans: Mutex::new(HashMap::new()), - expected, - current: Mutex::new(Vec::new()), - ids: AtomicUsize::new(1), - filter: self.filter, - }; - (subscriber, handle) - } -} - -impl Subscriber for Running -where - F: Fn(&Metadata) -> bool + 'static, -{ - fn enabled(&self, meta: &Metadata) -> bool { - (self.filter)(meta) - } - - 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::Visit(_, _)) = expected.front() { - true - } else { - false - }; - if was_expected { - 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); - } - let mut checker = expected_values.checker(format!("span {}: ", span.name)); - values.record(&mut checker); - checker.finish(); - } - } - } - - fn event(&self, event: &Event) { - let name = event.metadata().name(); - println!("event: {};", name); - match self.expected.lock().unwrap().pop_front() { - None => {} - Some(Expect::Event(expected)) => expected.check(event), - Some(ex) => ex.bad(format_args!("observed event {:?}", event)), - } - } - - fn record_follows_from(&self, _span: &Id, _follows: &Id) { - // TODO: it should be possible to expect spans to follow from other spans - } - - fn new_span(&self, span: &Attributes) -> Id { - use span::Parent; - let meta = span.metadata(); - let id = self.ids.fetch_add(1, Ordering::SeqCst); - let id = Id::from_u64(id as u64); - println!( - "new_span: name={:?}; target={:?}; id={:?};", - meta.name(), - meta.target(), - id - ); - let mut expected = self.expected.lock().unwrap(); - let was_expected = match expected.front() { - Some(Expect::NewSpan(_)) => true, - _ => false, - }; - let mut spans = self.spans.lock().unwrap(); - if was_expected { - if let Expect::NewSpan(mut expected) = expected.pop_front().unwrap() { - let name = meta.name(); - expected - .span - .metadata - .check(meta, format_args!("span `{}`", name)); - let mut checker = expected.fields.checker(format!("{}", name)); - span.record(&mut checker); - checker.finish(); - match expected.parent { - Some(Parent::ExplicitRoot) => { - assert!( - span.is_root(), - "expected {:?} to be an explicit root span", - name - ); - } - Some(Parent::Explicit(expected_parent)) => { - let actual_parent = - span.parent().and_then(|id| spans.get(id)).map(|s| s.name); - assert_eq!( - Some(expected_parent.as_ref()), - actual_parent, - "expected {:?} to have explicit parent {:?}", - name, - expected_parent, - ); - } - Some(Parent::ContextualRoot) => { - assert!( - span.is_contextual(), - "expected {:?} to have a contextual parent", - name - ); - assert!( - self.current.lock().unwrap().last().is_none(), - "expected {:?} to be a root, but we were inside a span", - name - ); - } - Some(Parent::Contextual(expected_parent)) => { - assert!( - span.is_contextual(), - "expected {:?} to have a contextual parent", - name - ); - let stack = self.current.lock().unwrap(); - let actual_parent = - stack.last().and_then(|id| spans.get(id)).map(|s| s.name); - assert_eq!( - Some(expected_parent.as_ref()), - actual_parent, - "expected {:?} to have contextual parent {:?}", - name, - expected_parent, - ); - } - None => {} - } - } - } - spans.insert( - id.clone(), - SpanState { - name: meta.name(), - refs: 1, - }, - ); - id - } - - fn enter(&self, id: &Id) { - let spans = self.spans.lock().unwrap(); - if let Some(span) = spans.get(id) { - println!("enter: {}; id={:?};", span.name, id); - match self.expected.lock().unwrap().pop_front() { - None => {} - Some(Expect::Enter(ref expected_span)) => { - if let Some(name) = expected_span.name() { - assert_eq!(name, span.name); - } - } - Some(ex) => ex.bad(format_args!("entered span {:?}", span.name)), - } - }; - self.current.lock().unwrap().push(id.clone()); - } - - fn exit(&self, id: &Id) { - let spans = self.spans.lock().unwrap(); - let span = spans - .get(id) - .unwrap_or_else(|| panic!("no span for ID {:?}", id)); - println!("exit: {}; id={:?};", span.name, id); - match self.expected.lock().unwrap().pop_front() { - None => {} - Some(Expect::Exit(ref expected_span)) => { - if let Some(name) = expected_span.name() { - assert_eq!(name, span.name); - } - let curr = self.current.lock().unwrap().pop(); - assert_eq!( - Some(id), - curr.as_ref(), - "exited span {:?}, but the current span was {:?}", - span.name, - curr.as_ref().and_then(|id| spans.get(id)).map(|s| s.name) - ); - } - Some(ex) => ex.bad(format_args!("exited span {:?}", span.name)), - }; - } - - fn clone_span(&self, id: &Id) -> Id { - let name = self.spans.lock().unwrap().get_mut(id).map(|span| { - let name = span.name; - println!("clone_span: {}; id={:?}; refs={:?};", name, id, span.refs); - span.refs += 1; - name - }); - if name.is_none() { - println!("clone_span: id={:?};", id); - } - let mut expected = self.expected.lock().unwrap(); - let was_expected = if let Some(Expect::CloneSpan(ref span)) = expected.front() { - assert_eq!(name, span.name()); - true - } else { - false - }; - if was_expected { - expected.pop_front(); - } - id.clone() - } - - fn drop_span(&self, id: Id) { - let mut is_event = false; - let name = if let Ok(mut spans) = self.spans.try_lock() { - spans.get_mut(&id).map(|span| { - let name = span.name; - if name.contains("event") { - is_event = true; - } - println!("drop_span: {}; id={:?}; refs={:?};", name, id, span.refs); - span.refs -= 1; - name - }) - } else { - None - }; - if name.is_none() { - println!("drop_span: id={:?}", id); - } - if let Ok(mut expected) = self.expected.try_lock() { - let was_expected = match expected.front() { - Some(Expect::DropSpan(ref span)) => { - // Don't assert if this function was called while panicking, - // as failing the assertion can cause a double panic. - if !::std::thread::panicking() { - assert_eq!(name, span.name()); - } - true - } - Some(Expect::Event(_)) => { - if !::std::thread::panicking() { - assert!(is_event); - } - true - } - _ => false, - }; - if was_expected { - expected.pop_front(); - } - } - } -} - -impl MockHandle { - pub fn assert_finished(&self) { - if let Ok(ref expected) = self.0.lock() { - assert!( - !expected.iter().any(|thing| thing != &Expect::Nothing), - "more notifications expected: {:?}", - **expected - ); - } - } -} - -impl Expect { - fn bad<'a>(&self, what: fmt::Arguments<'a>) { - match self { - Expect::Event(e) => panic!("expected event {}, but {} instead", e, what,), - Expect::Enter(e) => panic!("expected to enter {} but {} instead", e, what,), - 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::Visit(e, fields) => { - panic!("expected {} to record {} but {} instead", e, fields, what,) - } - Expect::NewSpan(e) => panic!("expected {} but {} instead", e, what), - Expect::Nothing => panic!("expected nothing else to happen, but {} instead", what,), - } - } -} diff --git a/tokio-trace/tokio-trace-core/CHANGELOG.md b/tokio-trace/tokio-trace-core/CHANGELOG.md deleted file mode 100644 index 705a40e39..000000000 --- a/tokio-trace/tokio-trace-core/CHANGELOG.md +++ /dev/null @@ -1,22 +0,0 @@ -# 0.2.0 (April 21, 2019) - -### Breaking Changes -- Remove `Callsite::clear_interest` and `Callsite::add_interest` (#1039) -- `metadata!` macro now requires a `Kind` field (#1046) - -### Added -- Add a function to rebuild cached interest (#1039) -- Add overrideable downcasting to `Subscriber`s (#974) -- Add slightly more useful debug impls (#1014) -- Introduce callsite classification in metadata (#1046) - -### Fixed -- `fmt::Debug` impls for `field::Display` and `field::Debug` not passing through - to the inner value (#992) -- Entering a `Dispatch` function unsets the default dispatcher for the duration - of the function (so that events inside the subscriber cannot cause infinite - loops) (#1033) - -# 0.1.0 (March 13, 2019) - -- Initial release diff --git a/tokio-trace/tokio-trace-core/Cargo.toml b/tokio-trace/tokio-trace-core/Cargo.toml deleted file mode 100644 index 9e3fffc35..000000000 --- a/tokio-trace/tokio-trace-core/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "tokio-trace-core" -# When releasing to crates.io: -# - Remove path dependencies -# - Update html_root_url. -# - Update doc url -# - Cargo.toml -# - README.md -# - Update CHANGELOG.md. -# - Create "v0.2.x" git tag. -version = "0.2.0" -authors = ["Tokio Contributors "] -license = "MIT" -repository = "https://github.com/tokio-rs/tokio" -homepage = "https://tokio.rs" -documentation = "https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core" -description = """ -Core primitives for tokio-trace. -""" -categories = ["development-tools::debugging"] -keywords = ["logging", "tracing"] - -[dependencies] -lazy_static = "1.0.0" diff --git a/tokio-trace/tokio-trace-core/LICENSE b/tokio-trace/tokio-trace-core/LICENSE deleted file mode 100644 index cdb28b4b5..000000000 --- a/tokio-trace/tokio-trace-core/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2019 Tokio Contributors - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/tokio-trace/tokio-trace-core/README.md b/tokio-trace/tokio-trace-core/README.md deleted file mode 100644 index 61442a727..000000000 --- a/tokio-trace/tokio-trace-core/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# tokio-trace-core - -Core primitives for `tokio-trace`. - -[Documentation](https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core/index.html) - -## Overview - -`tokio-trace` is a framework for instrumenting Rust programs to collect -structured, event-based diagnostic information. This crate defines the core -primitives of `tokio-trace`. - -The crate provides: - -* [`Span`] identifies a span within the execution of a program. - -* [`Event`] represents a single event within a trace. - -* [`Subscriber`], the trait implemented to collect trace data. - -* [`Metadata`] and [`Callsite`] provide information describing `Span`s. - -* [`Field`], [`FieldSet`], [`Value`], and [`ValueSet`] represent the - structured data attached to a `Span`. - -* [`Dispatch`] allows span events to be dispatched to `Subscriber`s. - -In addition, it defines the global callsite registry and per-thread current -dispatcher which other components of the tracing system rely on. - -Application authors will typically not use this crate directly. Instead, they -will use the [`tokio-trace`] crate, which provides a much more fully-featured -API. However, this crate's API will change very infrequently, so it may be used -when dependencies must be very stable. - -[`tokio-trace`]: ../ -[`Span`]: https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core/span/struct.Span.html -[`Event`]: https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core/event/struct.Event.html -[`Subscriber`]: https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core/subscriber/trait.Subscriber.html -[`Metadata`]: https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core/metadata/struct.Metadata.html -[`Callsite`]: https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core/callsite/trait.Callsite.html -[`Field`]: https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core/field/struct.Field.html -[`FieldSet`]: https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core/field/struct.FieldSet.html -[`Value`]: https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core/field/trait.Value.html -[`ValueSet`]: https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core/field/struct.ValueSet.html -[`Dispatch`]: https://docs.rs/tokio-trace-core/0.2.0/tokio_trace_core/dispatcher/struct.Dispatch.html - -## License - -This project is licensed under the [MIT license](LICENSE). - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in Tokio by you, shall be licensed as MIT, without any additional -terms or conditions. diff --git a/tokio-trace/tokio-trace-core/src/callsite.rs b/tokio-trace/tokio-trace-core/src/callsite.rs deleted file mode 100644 index 1d69a459c..000000000 --- a/tokio-trace/tokio-trace-core/src/callsite.rs +++ /dev/null @@ -1,142 +0,0 @@ -//! Callsites represent the source locations from which spans or events -//! originate. -use std::{ - fmt, - hash::{Hash, Hasher}, - ptr, - sync::Mutex, -}; -use { - dispatcher::{self, Dispatch, Registrar}, - subscriber::Interest, - Metadata, -}; - -lazy_static! { - static ref REGISTRY: Mutex = Mutex::new(Registry { - callsites: Vec::new(), - dispatchers: Vec::new(), - }); -} - -struct Registry { - callsites: Vec<&'static Callsite>, - dispatchers: Vec, -} - -impl Registry { - fn rebuild_callsite_interest(&self, callsite: &'static Callsite) { - let meta = callsite.metadata(); - - let mut interest = Interest::never(); - - for registrar in &self.dispatchers { - if let Some(sub_interest) = registrar.try_register(meta) { - interest = interest.and(sub_interest); - } - } - - callsite.set_interest(interest) - } - - fn rebuild_interest(&mut self) { - self.dispatchers.retain(Registrar::is_alive); - - self.callsites.iter().for_each(|&callsite| { - self.rebuild_callsite_interest(callsite); - }); - } -} - -/// Trait implemented by callsites. -/// -/// These functions are only intended to be called by the [`Registry`] which -/// correctly handles determining the common interest between all subscribers. -pub trait Callsite: Sync { - /// Sets the [`Interest`] for this callsite. - /// - /// [`Interest`]: ../subscriber/struct.Interest.html - fn set_interest(&self, interest: Interest); - - /// Returns the [metadata] associated with the callsite. - /// - /// [metadata]: ../metadata/struct.Metadata.html - fn metadata(&self) -> &Metadata; -} - -/// Uniquely identifies a [`Callsite`] -/// -/// Two `Identifier`s are equal if they both refer to the same callsite. -/// -/// [`Callsite`]: ../callsite/trait.Callsite.html -#[derive(Clone)] -pub struct Identifier( - /// **Warning**: The fields on this type are currently `pub` because it must - /// be able to be constructed statically by macros. However, when `const - /// fn`s are available on stable Rust, this will no longer be necessary. - /// Thus, these fields are *not* considered stable public API, and they may - /// change warning. Do not rely on any fields on `Identifier`. When - /// constructing new `Identifier`s, use the `identify_callsite!` macro or - /// the `Callsite::id` function instead. - // TODO: When `Callsite::id` is a const fn, this need no longer be `pub`. - #[doc(hidden)] - pub &'static Callsite, -); - -/// Clear and reregister interest on every [`Callsite`] -/// -/// This function is intended for runtime reconfiguration of filters on traces -/// when the filter recalculation is much less frequent than trace events are. -/// The alternative is to have the [`Subscriber`] that supports runtime -/// reconfiguration of filters always return [`Interest::sometimes()`] so that -/// [`enabled`] is evaluated for every event. -/// -/// [`Callsite`]: ../callsite/trait.Callsite.html -/// [`enabled`]: ../subscriber/trait.Subscriber.html#tymethod.enabled -/// [`Interest::sometimes()`]: ../subscriber/struct.Interest.html#method.sometimes -/// [`Subscriber`]: ../subscriber/trait.Subscriber.html -pub fn rebuild_interest_cache() { - let mut registry = REGISTRY.lock().unwrap(); - registry.rebuild_interest(); -} - -/// Register a new `Callsite` with the global registry. -/// -/// This should be called once per callsite after the callsite has been -/// constructed. -pub fn register(callsite: &'static Callsite) { - let mut registry = REGISTRY.lock().unwrap(); - registry.rebuild_callsite_interest(callsite); - registry.callsites.push(callsite); -} - -pub(crate) fn register_dispatch(dispatch: &Dispatch) { - let mut registry = REGISTRY.lock().unwrap(); - registry.dispatchers.push(dispatch.registrar()); - registry.rebuild_interest(); -} - -// ===== impl Identifier ===== - -impl PartialEq for Identifier { - fn eq(&self, other: &Identifier) -> bool { - ptr::eq(self.0, other.0) - } -} - -impl Eq for Identifier {} - -impl fmt::Debug for Identifier { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Identifier({:p})", self.0) - } -} - -impl Hash for Identifier { - fn hash(&self, state: &mut H) - where - H: Hasher, - { - (self.0 as *const Callsite).hash(state) - } -} diff --git a/tokio-trace/tokio-trace-core/src/dispatcher.rs b/tokio-trace/tokio-trace-core/src/dispatcher.rs deleted file mode 100644 index d79ad07ad..000000000 --- a/tokio-trace/tokio-trace-core/src/dispatcher.rs +++ /dev/null @@ -1,612 +0,0 @@ -//! Dispatches trace events to `Subscriber`s.c -use { - callsite, span, - subscriber::{self, Subscriber}, - Event, Metadata, -}; - -use std::{ - any::Any, - cell::{Cell, RefCell}, - error, fmt, - sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, Weak, - }, -}; - -/// `Dispatch` trace data to a [`Subscriber`]. -/// -/// [`Subscriber`]: ../subscriber/trait.Subscriber.html -#[derive(Clone)] -pub struct Dispatch { - subscriber: Arc, -} - -thread_local! { - static CURRENT_STATE: State = State { - default: RefCell::new(Dispatch::none()), - can_enter: Cell::new(true), - }; -} - -static GLOBAL_INIT: AtomicUsize = AtomicUsize::new(UNINITIALIZED); -const UNINITIALIZED: usize = 0; -const INITIALIZING: usize = 1; -const INITIALIZED: usize = 2; - -static mut GLOBAL_DISPATCH: Option = None; - -/// The dispatch state of a thread. -struct State { - /// This thread's current default dispatcher. - default: RefCell, - /// Whether or not we can currently begin dispatching a trace event. - /// - /// This is set to `false` when functions such as `enter`, `exit`, `event`, - /// and `new_span` are called on this thread's default dispatcher, to - /// prevent further trace events triggered inside those functions from - /// creating an infinite recursion. When we finish handling a dispatch, this - /// is set back to `true`. - can_enter: Cell, -} - -/// A guard that resets the current default dispatcher to the prior -/// default dispatcher when dropped. -struct ResetGuard(Option); - -/// Sets this dispatch as the default for the duration of a closure. -/// -/// The default dispatcher is used when creating a new [span] or -/// [`Event`], _if no span is currently executing_. If a span is currently -/// executing, new spans or events are dispatched to the subscriber that -/// tagged that span, instead. -/// -/// [span]: ../span/index.html -/// [`Subscriber`]: ../subscriber/trait.Subscriber.html -/// [`Event`]: ../event/struct.Event.html -pub fn with_default(dispatcher: &Dispatch, f: impl FnOnce() -> T) -> T { - // When this guard is dropped, the default dispatcher will be reset to the - // prior default. Using this (rather than simply resetting after calling - // `f`) ensures that we always reset to the prior dispatcher even if `f` - // panics. - let _guard = State::set_default(dispatcher.clone()); - f() -} - -/// Sets this dispatch as the global default for the duration of the entire program. -/// Will be used as a fallback if no thread-local dispatch has been set in a thread -/// (using `with_default`.) -/// -/// Can only be set once; subsequent attempts to set the global default will fail. -/// Returns `Err` if the global default has already been set. -/// -/// Note: Libraries should *NOT* call `set_global_default()`! That will cause conflicts when -/// executables try to set them later. -/// -/// [span]: ../span/index.html -/// [`Subscriber`]: ../subscriber/trait.Subscriber.html -/// [`Event`]: ../event/struct.Event.html -pub fn set_global_default(dispatcher: Dispatch) -> Result<(), SetGlobalDefaultError> { - if GLOBAL_INIT.compare_and_swap(UNINITIALIZED, INITIALIZING, Ordering::SeqCst) == UNINITIALIZED - { - unsafe { - GLOBAL_DISPATCH = Some(dispatcher.clone()); - } - GLOBAL_INIT.store(INITIALIZED, Ordering::SeqCst); - Ok(()) - } else { - Err(SetGlobalDefaultError { _no_construct: () }) - } -} - -/// Returned if setting the global dispatcher fails. -#[derive(Debug)] -pub struct SetGlobalDefaultError { - _no_construct: (), -} - -impl fmt::Display for SetGlobalDefaultError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("a global default trace dispatcher has already been set") - } -} - -impl error::Error for SetGlobalDefaultError {} - -/// Executes a closure with a reference to this thread's current [dispatcher]. -/// -/// Note that calls to `get_default` should not be nested; if this function is -/// called while inside of another `get_default`, that closure will be provided -/// with `Dispatch::none` rather than the previously set dispatcher. -/// -/// [dispatcher]: ../dispatcher/struct.Dispatch.html -pub fn get_default(mut f: F) -> T -where - F: FnMut(&Dispatch) -> T, -{ - // While this guard is active, additional calls to subscriber functions on - // the default dispatcher will not be able to access the dispatch context. - // Dropping the guard will allow the dispatch context to be re-entered. - struct Entered<'a>(&'a Cell); - impl<'a> Drop for Entered<'a> { - #[inline] - fn drop(&mut self) { - self.0.set(true); - } - } - - CURRENT_STATE - .try_with(|state| { - if state.can_enter.replace(false) { - let _guard = Entered(&state.can_enter); - - let mut default = state.default.borrow_mut(); - - if default.is::() && GLOBAL_INIT.load(Ordering::SeqCst) == INITIALIZED - { - // don't redo this call on the next check - unsafe { - *default = GLOBAL_DISPATCH - .as_ref() - .expect("invariant violated: GLOBAL_DISPATCH must be initialized before GLOBAL_INIT is set") - .clone() - } - } - f(&*default) - } else { - f(&Dispatch::none()) - } - }) - .unwrap_or_else(|_| f(&Dispatch::none())) -} - -pub(crate) struct Registrar(Weak); - -impl Dispatch { - /// Returns a new `Dispatch` that discards events and spans. - #[inline] - pub fn none() -> Self { - Dispatch { - subscriber: Arc::new(NoSubscriber), - } - } - - /// Returns a `Dispatch` that forwards to the given [`Subscriber`]. - /// - /// [`Subscriber`]: ../subscriber/trait.Subscriber.html - pub fn new(subscriber: S) -> Self - where - S: Subscriber + Send + Sync + 'static, - { - let me = Dispatch { - subscriber: Arc::new(subscriber), - }; - callsite::register_dispatch(&me); - me - } - - pub(crate) fn registrar(&self) -> Registrar { - Registrar(Arc::downgrade(&self.subscriber)) - } - - /// Registers a new callsite with this subscriber, returning whether or not - /// the subscriber is interested in being notified about the callsite. - /// - /// This calls the [`register_callsite`] function on the [`Subscriber`] - /// that this `Dispatch` forwards to. - /// - /// [`Subscriber`]: ../subscriber/trait.Subscriber.html - /// [`register_callsite`]: ../subscriber/trait.Subscriber.html#method.register_callsite - #[inline] - pub fn register_callsite(&self, metadata: &Metadata) -> subscriber::Interest { - self.subscriber.register_callsite(metadata) - } - - /// Record the construction of a new span, returning a new [ID] for the - /// span being constructed. - /// - /// This calls the [`new_span`] function on the [`Subscriber`] that this - /// `Dispatch` forwards to. - /// - /// [ID]: ../span/struct.Id.html - /// [`Subscriber`]: ../subscriber/trait.Subscriber.html - /// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span - #[inline] - pub fn new_span(&self, span: &span::Attributes) -> span::Id { - self.subscriber.new_span(span) - } - - /// Record a set of values on a span. - /// - /// This calls the [`record`] function on the [`Subscriber`] that this - /// `Dispatch` forwards to. - /// - /// [`Subscriber`]: ../subscriber/trait.Subscriber.html - /// [`record`]: ../subscriber/trait.Subscriber.html#method.record - #[inline] - pub fn record(&self, span: &span::Id, values: &span::Record) { - self.subscriber.record(span, values) - } - - /// Adds an indication that `span` follows from the span with the id - /// `follows`. - /// - /// This calls the [`record_follows_from`] function on the [`Subscriber`] - /// that this `Dispatch` forwards to. - /// - /// [`Subscriber`]: ../subscriber/trait.Subscriber.html - /// [`record_follows_from`]: ../subscriber/trait.Subscriber.html#method.record_follows_from - #[inline] - pub fn record_follows_from(&self, span: &span::Id, follows: &span::Id) { - self.subscriber.record_follows_from(span, follows) - } - - /// Returns true if a span with the specified [metadata] would be - /// recorded. - /// - /// This calls the [`enabled`] function on the [`Subscriber`] that this - /// `Dispatch` forwards to. - /// - /// [metadata]: ../metadata/struct.Metadata.html - /// [`Subscriber`]: ../subscriber/trait.Subscriber.html - /// [`enabled`]: ../subscriber/trait.Subscriber.html#method.enabled - #[inline] - pub fn enabled(&self, metadata: &Metadata) -> bool { - self.subscriber.enabled(metadata) - } - - /// Records that an [`Event`] has occurred. - /// - /// This calls the [`event`] function on the [`Subscriber`] that this - /// `Dispatch` forwards to. - /// - /// [`Event`]: ../event/struct.Event.html - /// [`Subscriber`]: ../subscriber/trait.Subscriber.html - /// [`event`]: ../subscriber/trait.Subscriber.html#method.event - #[inline] - pub fn event(&self, event: &Event) { - self.subscriber.event(event) - } - - /// Records that a span has been can_enter. - /// - /// This calls the [`enter`] function on the [`Subscriber`] that this - /// `Dispatch` forwards to. - /// - /// [`Subscriber`]: ../subscriber/trait.Subscriber.html - /// [`event`]: ../subscriber/trait.Subscriber.html#method.event - #[inline] - pub fn enter(&self, span: &span::Id) { - self.subscriber.enter(span); - } - - /// Records that a span has been exited. - /// - /// This calls the [`exit`](::Subscriber::exit) function on the `Subscriber` - /// that this `Dispatch` forwards to. - #[inline] - pub fn exit(&self, span: &span::Id) { - self.subscriber.exit(span); - } - - /// Notifies the subscriber that a [span ID] has been cloned. - /// - /// This function is guaranteed to only be called with span IDs that were - /// returned by this `Dispatch`'s [`new_span`] function. - /// - /// This calls the [`clone_span`] function on the `Subscriber` that this - /// `Dispatch` forwards to. - /// - /// [span ID]: ../span/struct.Id.html - /// [`Subscriber`]: ../subscriber/trait.Subscriber.html - /// [`clone_span`]: ../subscriber/trait.Subscriber.html#method.clone_span - /// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span - #[inline] - pub fn clone_span(&self, id: &span::Id) -> span::Id { - self.subscriber.clone_span(&id) - } - - /// Notifies the subscriber that a [span ID] has been dropped. - /// - /// This function is guaranteed to only be called with span IDs that were - /// returned by this `Dispatch`'s [`new_span`] function. - /// - /// This calls the [`drop_span`] function on the [`Subscriber`] that this - /// `Dispatch` forwards to. - /// - /// [span ID]: ../span/struct.Id.html - /// [`Subscriber`]: ../subscriber/trait.Subscriber.html - /// [`clone_span`]: ../subscriber/trait.Subscriber.html#method.clone_span - /// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span - #[inline] - pub fn drop_span(&self, id: span::Id) { - self.subscriber.drop_span(id) - } - - /// Returns `true` if this `Dispatch` forwards to a `Subscriber` of type - /// `T`. - #[inline] - pub fn is(&self) -> bool { - Subscriber::is::(&*self.subscriber) - } - - /// Returns some reference to the `Subscriber` this `Dispatch` forwards to - /// if it is of type `T`, or `None` if it isn't. - #[inline] - pub fn downcast_ref(&self) -> Option<&T> { - Subscriber::downcast_ref(&*self.subscriber) - } -} - -impl fmt::Debug for Dispatch { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("Dispatch(...)") - } -} - -impl From for Dispatch -where - S: Subscriber + Send + Sync + 'static, -{ - #[inline] - fn from(subscriber: S) -> Self { - Dispatch::new(subscriber) - } -} - -struct NoSubscriber; -impl Subscriber for NoSubscriber { - #[inline] - fn register_callsite(&self, _: &Metadata) -> subscriber::Interest { - subscriber::Interest::never() - } - - fn new_span(&self, _: &span::Attributes) -> span::Id { - span::Id::from_u64(0xDEAD) - } - - fn event(&self, _event: &Event) {} - - fn record(&self, _span: &span::Id, _values: &span::Record) {} - - fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {} - - #[inline] - fn enabled(&self, _metadata: &Metadata) -> bool { - false - } - - fn enter(&self, _span: &span::Id) {} - fn exit(&self, _span: &span::Id) {} -} - -impl Registrar { - pub(crate) fn try_register(&self, metadata: &Metadata) -> Option { - self.0.upgrade().map(|s| s.register_callsite(metadata)) - } - - pub(crate) fn is_alive(&self) -> bool { - self.0.upgrade().is_some() - } -} - -// ===== impl State ===== - -impl State { - /// Replaces the current default dispatcher on this thread with the provided - /// dispatcher.Any - /// - /// Dropping the returned `ResetGuard` will reset the default dispatcher to - /// the previous value. - #[inline] - fn set_default(new_dispatch: Dispatch) -> ResetGuard { - let prior = CURRENT_STATE - .try_with(|state| { - state.can_enter.set(true); - state.default.replace(new_dispatch) - }) - .ok(); - ResetGuard(prior) - } -} - -// ===== impl ResetGuard ===== - -impl Drop for ResetGuard { - #[inline] - fn drop(&mut self) { - if let Some(dispatch) = self.0.take() { - let _ = CURRENT_STATE.try_with(|state| { - *state.default.borrow_mut() = dispatch; - }); - } - } -} - -#[cfg(test)] -mod test { - use super::*; - use std::sync::atomic::{AtomicUsize, Ordering}; - use { - callsite::Callsite, - metadata::{Kind, Level, Metadata}, - span, - subscriber::{Interest, Subscriber}, - Event, - }; - - #[test] - fn dispatch_is() { - let dispatcher = Dispatch::new(NoSubscriber); - assert!(dispatcher.is::()); - } - - #[test] - fn dispatch_downcasts() { - let dispatcher = Dispatch::new(NoSubscriber); - assert!(dispatcher.downcast_ref::().is_some()); - } - - struct TestCallsite; - static TEST_CALLSITE: TestCallsite = TestCallsite; - static TEST_META: Metadata<'static> = metadata! { - name: "test", - target: module_path!(), - level: Level::DEBUG, - fields: &[], - callsite: &TEST_CALLSITE, - kind: Kind::EVENT - }; - - impl Callsite for TestCallsite { - fn set_interest(&self, _: Interest) {} - fn metadata(&self) -> &Metadata { - &TEST_META - } - } - - #[test] - fn events_dont_infinite_loop() { - // This test ensures that an event triggered within a subscriber - // won't cause an infinite loop of events. - struct TestSubscriber; - impl Subscriber for TestSubscriber { - fn enabled(&self, _: &Metadata) -> bool { - true - } - - fn new_span(&self, _: &span::Attributes) -> span::Id { - span::Id::from_u64(0xAAAA) - } - - fn record(&self, _: &span::Id, _: &span::Record) {} - - fn record_follows_from(&self, _: &span::Id, _: &span::Id) {} - - fn event(&self, _: &Event) { - static EVENTS: AtomicUsize = AtomicUsize::new(0); - assert_eq!( - EVENTS.fetch_add(1, Ordering::Relaxed), - 0, - "event method called twice!" - ); - Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[])) - } - - fn enter(&self, _: &span::Id) {} - - fn exit(&self, _: &span::Id) {} - } - - with_default(&Dispatch::new(TestSubscriber), || { - Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[])) - }) - } - - #[test] - fn spans_dont_infinite_loop() { - // This test ensures that a span created within a subscriber - // won't cause an infinite loop of new spans. - - fn mk_span() { - get_default(|current| { - current.new_span(&span::Attributes::new( - &TEST_META, - &TEST_META.fields().value_set(&[]), - )) - }); - } - - struct TestSubscriber; - impl Subscriber for TestSubscriber { - fn enabled(&self, _: &Metadata) -> bool { - true - } - - fn new_span(&self, _: &span::Attributes) -> span::Id { - static NEW_SPANS: AtomicUsize = AtomicUsize::new(0); - assert_eq!( - NEW_SPANS.fetch_add(1, Ordering::Relaxed), - 0, - "new_span method called twice!" - ); - mk_span(); - span::Id::from_u64(0xAAAA) - } - - fn record(&self, _: &span::Id, _: &span::Record) {} - - fn record_follows_from(&self, _: &span::Id, _: &span::Id) {} - - fn event(&self, _: &Event) {} - - fn enter(&self, _: &span::Id) {} - - fn exit(&self, _: &span::Id) {} - } - - with_default(&Dispatch::new(TestSubscriber), || mk_span()) - } - - #[test] - fn global_dispatch() { - struct TestSubscriberA; - impl Subscriber for TestSubscriberA { - fn enabled(&self, _: &Metadata) -> bool { - true - } - fn new_span(&self, _: &span::Attributes) -> span::Id { - span::Id::from_u64(1) - } - fn record(&self, _: &span::Id, _: &span::Record) {} - fn record_follows_from(&self, _: &span::Id, _: &span::Id) {} - fn event(&self, _: &Event) {} - fn enter(&self, _: &span::Id) {} - fn exit(&self, _: &span::Id) {} - } - struct TestSubscriberB; - impl Subscriber for TestSubscriberB { - fn enabled(&self, _: &Metadata) -> bool { - true - } - fn new_span(&self, _: &span::Attributes) -> span::Id { - span::Id::from_u64(1) - } - fn record(&self, _: &span::Id, _: &span::Record) {} - fn record_follows_from(&self, _: &span::Id, _: &span::Id) {} - fn event(&self, _: &Event) {} - fn enter(&self, _: &span::Id) {} - fn exit(&self, _: &span::Id) {} - } - - // NOTE: if you want to have other tests that set the default dispatch you'll need to - // write them as integration tests in ../tests/ - set_global_default(Dispatch::new(TestSubscriberA)).expect("global dispatch set failed"); - get_default(|current| { - assert!( - current.is::(), - "global dispatch get failed" - ) - }); - - with_default(&Dispatch::new(TestSubscriberB), || { - get_default(|current| { - assert!( - current.is::(), - "thread-local override of global dispatch failed" - ) - }); - }); - - get_default(|current| { - assert!( - current.is::(), - "reset to global override failed" - ) - }); - - set_global_default(Dispatch::new(TestSubscriberA)) - .expect_err("double global dispatch set succeeded"); - } -} diff --git a/tokio-trace/tokio-trace-core/src/event.rs b/tokio-trace/tokio-trace-core/src/event.rs deleted file mode 100644 index 3e2ff29aa..000000000 --- a/tokio-trace/tokio-trace-core/src/event.rs +++ /dev/null @@ -1,119 +0,0 @@ -//! Events represent single points in time during the execution of a program. -use parent::Parent; -use span::Id; -use {field, Metadata}; - -/// `Event`s represent single points in time where something occurred during the -/// execution of a program. -/// -/// An `Event` can be compared to a log record in unstructured logging, but with -/// two key differences: -/// - `Event`s exist _within the context of a [span]_. Unlike log lines, they -/// may be located within the trace tree, allowing visibility into the -/// _temporal_ context in which the event occurred, as well as the source -/// code location. -/// - Like spans, `Event`s have structured key-value data known as _[fields]_, -/// which may include textual message. In general, a majority of the data -/// associated with an event should be in the event's fields rather than in -/// the textual message, as the fields are more structed. -/// -/// [span]: ../span -/// [fields]: ../field -#[derive(Debug)] -pub struct Event<'a> { - fields: &'a field::ValueSet<'a>, - metadata: &'a Metadata<'a>, - parent: Parent, -} - -impl<'a> Event<'a> { - /// Constructs a new `Event` with the specified metadata and set of values, - /// and observes it with the current subscriber. - #[inline] - pub fn dispatch(metadata: &'a Metadata<'a>, fields: &'a field::ValueSet) { - let event = Event { - metadata, - fields, - parent: Parent::Current, - }; - ::dispatcher::get_default(|current| { - current.event(&event); - }); - } - - /// Constructs a new `Event` with the specified metadata and set of values, - /// and observes it with the current subscriber and an explicit parent. - #[inline] - pub fn child_of( - parent: impl Into>, - metadata: &'a Metadata<'a>, - fields: &'a field::ValueSet, - ) { - let parent = match parent.into() { - Some(p) => Parent::Explicit(p), - None => Parent::Root, - }; - - let event = Event { - metadata, - fields, - parent, - }; - ::dispatcher::get_default(|current| { - current.event(&event); - }); - } - - /// Visits all the fields on this `Event` with the specified [visitor]. - /// - /// [visitor]: ../field/trait.Visit.html - #[inline] - pub fn record(&self, visitor: &mut field::Visit) { - self.fields.record(visitor); - } - - /// Returns an iterator over the set of values on this `Event`. - pub fn fields(&self) -> field::Iter { - self.fields.field_set().iter() - } - - /// Returns [metadata] describing this `Event`. - /// - /// [metadata]: ../metadata/struct.Metadata.html - pub fn metadata(&self) -> &Metadata { - self.metadata - } - - /// Returns true if the new event shoold be a root. - pub fn is_root(&self) -> bool { - match self.parent { - Parent::Root => true, - _ => false, - } - } - - /// Returns true if the new event's parent should be determined based on the - /// current context. - /// - /// If this is true and the current thread is currently inside a span, then - /// that span should be the new events's parent. Otherwise, if the current - /// thread is _not_ inside a span, then the new event will be the root of its - /// own trace tree. - pub fn is_contextual(&self) -> bool { - match self.parent { - Parent::Current => true, - _ => false, - } - } - - /// Returns the new event's explicitly-specified parent, if there is one. - /// - /// Otherwise (if the new event is a root or is a child of the current span), - /// returns false. - pub fn parent(&self) -> Option<&Id> { - match self.parent { - Parent::Explicit(ref p) => Some(p), - _ => None, - } - } -} diff --git a/tokio-trace/tokio-trace-core/src/field.rs b/tokio-trace/tokio-trace-core/src/field.rs deleted file mode 100644 index 85615d6b8..000000000 --- a/tokio-trace/tokio-trace-core/src/field.rs +++ /dev/null @@ -1,801 +0,0 @@ -//! Span and `Event` key-value data. -//! -//! Spans and events may be annotated with key-value data, referred to as known -//! as _fields_. These fields consist of a mapping from a key (corresponding to -//! a `&str` but represented internally as an array index) to a [`Value`]. -//! -//! # `Value`s and `Subscriber`s -//! -//! `Subscriber`s consume `Value`s as fields attached to [span]s or [`Event`]s. -//! The set of field keys on a given span or is defined on its [`Metadata`]. -//! When a span is created, it provides [`Attributes`] to the `Subscriber`'s -//! [`new_span`] method, containing any fields whose values were provided when -//! the span was created; and may call the `Subscriber`'s [`record`] method -//! with additional [`Record`]s if values are added for more of its fields. -//! Similarly, the [`Event`] type passed to the subscriber's [`event`] method -//! will contain any fields attached to each event. -//! -//! `tokio_trace` represents values as either one of a set of Rust primitives -//! (`i64`, `u64`, `bool`, and `&str`) or using a `fmt::Display` or `fmt::Debug` -//! implementation. The [`record`] trait method on the `Subscriber` trait -//! allow `Subscriber` implementations to provide type-specific behaviour for -//! consuming values of each type. -//! -//! Instances of the [`Visit`] trait are provided by `Subscriber`s to record the -//! values attached to spans 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 -//! them. -//! -//! [`Value`]: trait.Value.html -//! [span]: ../span/ -//! [`Event`]: ../event/struct.Event.html -//! [`Metadata`]: ../metadata/struct.Metadata.html -//! [`Attributes`]: ../span/struct.Attributes.html -//! [`Record`]: ../span/struct.Record.html -//! [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span -//! [`record`]: ../subscriber/trait.Subscriber.html#method.record -//! [`event`]: ../subscriber/trait.Subscriber.html#method.record -//! [`Visit`]: trait.Visit.html -use callsite; -use std::{ - borrow::Borrow, - fmt, - hash::{Hash, Hasher}, - ops::Range, -}; - -use self::private::ValidLen; - -/// An opaque key allowing _O_(1) access to a field in a `Span`'s key-value -/// data. -/// -/// As keys are defined by the _metadata_ of a span, rather than by an -/// individual instance of a span, a key may be used to access the same field -/// across all instances of a given span with the same metadata. Thus, when a -/// subscriber observes a new span, it need only access a field by name _once_, -/// and use the key for that name for all other accesses. -#[derive(Debug)] -pub struct Field { - i: usize, - fields: FieldSet, -} - -/// Describes the fields present on a span. -// TODO: When `const fn` is stable, make this type's fields private. -pub struct FieldSet { - /// The names of each field on the described span. - /// - /// **Warning**: The fields on this type are currently `pub` because it must be able - /// to be constructed statically by macros. However, when `const fn`s are - /// available on stable Rust, this will no longer be necessary. Thus, these - /// fields are *not* considered stable public API, and they may change - /// warning. Do not rely on any fields on `FieldSet`! - #[doc(hidden)] - pub names: &'static [&'static str], - /// The callsite where the described span originates. - /// - /// **Warning**: The fields on this type are currently `pub` because it must be able - /// to be constructed statically by macros. However, when `const fn`s are - /// available on stable Rust, this will no longer be necessary. Thus, these - /// fields are *not* considered stable public API, and they may change - /// warning. Do not rely on any fields on `FieldSet`! - #[doc(hidden)] - pub callsite: callsite::Identifier, -} - -/// A set of fields and values for a span. -pub struct ValueSet<'a> { - values: &'a [(&'a Field, Option<&'a (Value + 'a)>)], - fields: &'a FieldSet, -} - -/// An iterator over a set of fields. -#[derive(Debug)] -pub struct Iter { - idxs: Range, - fields: FieldSet, -} - -/// Visits typed values. -/// -/// 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 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 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 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, Visit, Field}; -/// # fn main() { -/// pub struct StringVisitor<'a> { -/// string: &'a mut String, -/// } -/// -/// impl<'a> Visit for StringVisitor<'a> { -/// fn record_debug(&mut self, field: &Field, value: &fmt::Debug) { -/// write!(self.string, "{} = {:?}; ", field.name(), value).unwrap(); -/// } -/// } -/// # } -/// ``` -/// 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 `StringVisitor` may be dropped, allowing the string -/// to be printed or stored in some other data structure. -/// -/// 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 `Visit` implementation *must* implement. However, visitors may -/// override the default implementations of these functions in order to -/// implement type-specific behavior. -/// -/// 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 -/// 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, Visit, Field}; -/// # fn main() { -/// pub struct SumVisitor { -/// sum: i64, -/// } -/// -/// impl Visit for SumVisitor { -/// fn record_i64(&mut self, _field: &Field, value: i64) { -/// self.sum += value; -/// } -/// -/// fn record_u64(&mut self, _field: &Field, value: u64) { -/// self.sum += value as i64; -/// } -/// -/// fn record_debug(&mut self, _field: &Field, _value: &fmt::Debug) { -/// // Do nothing -/// } -/// } -/// # } -/// ``` -/// -/// 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 -/// implemented using `tokio-trace`. -/// -/// [`Value`]: trait.Value.html -/// [recorded]: trait.Value.html#method.record -/// [`Subscriber`]: ../subscriber/trait.Subscriber.html -/// [records an `Event`]: ../subscriber/trait.Subscriber.html#method.event -/// [set of `Value`s added to a `Span`]: ../subscriber/trait.Subscriber.html#method.record -/// [`Event`]: ../event/struct.Event.html -/// [`ValueSet`]: struct.ValueSet.html -pub trait Visit { - /// Visit a signed 64-bit integer value. - fn record_i64(&mut self, field: &Field, value: i64) { - self.record_debug(field, &value) - } - - /// Visit an umsigned 64-bit integer value. - fn record_u64(&mut self, field: &Field, value: u64) { - self.record_debug(field, &value) - } - - /// Visit a boolean value. - fn record_bool(&mut self, field: &Field, value: bool) { - self.record_debug(field, &value) - } - - /// Visit a string value. - fn record_str(&mut self, field: &Field, value: &str) { - self.record_debug(field, &value) - } - - /// 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 [visitor] passed to their `record` method in order to indicate how -/// their data should be recorded. -/// -/// [visitor]: trait.Visit.html -pub trait Value: ::sealed::Sealed { - /// 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`. -#[derive(Clone)] -pub struct DisplayValue(T); - -/// A `Value` which serializes as a string using `fmt::Debug`. -#[derive(Clone)] -pub struct DebugValue(T); - -/// Wraps a type implementing `fmt::Display` as a `Value` that can be -/// recorded using its `Display` implementation. -pub fn display(t: T) -> DisplayValue -where - T: fmt::Display, -{ - DisplayValue(t) -} - -/// Wraps a type implementing `fmt::Debug` as a `Value` that can be -/// recorded using its `Debug` implementation. -pub fn debug(t: T) -> DebugValue -where - T: fmt::Debug, -{ - DebugValue(t) -} - -// ===== impl Visit ===== - -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> Visit for fmt::DebugMap<'a, 'b> { - fn record_debug(&mut self, field: &Field, value: &fmt::Debug) { - self.entry(&format_args!("{}", field), value); - } -} - -impl Visit for F -where - F: FnMut(&Field, &fmt::Debug), -{ - fn record_debug(&mut self, field: &Field, value: &fmt::Debug) { - (self)(field, value) - } -} - -// ===== impl Value ===== - -macro_rules! impl_values { - ( $( $record:ident( $( $whatever:tt)+ ) ),+ ) => { - $( - impl_value!{ $record( $( $whatever )+ ) } - )+ - } -} -macro_rules! impl_value { - ( $record:ident( $( $value_ty:ty ),+ ) ) => { - $( - impl $crate::sealed::Sealed for $value_ty {} - impl $crate::field::Value for $value_ty { - fn record( - &self, - key: &$crate::field::Field, - visitor: &mut $crate::field::Visit, - ) { - visitor.$record(key, *self) - } - } - )+ - }; - ( $record:ident( $( $value_ty:ty ),+ as $as_ty:ty) ) => { - $( - impl $crate::sealed::Sealed for $value_ty {} - impl Value for $value_ty { - fn record( - &self, - key: &$crate::field::Field, - visitor: &mut $crate::field::Visit, - ) { - visitor.$record(key, *self as $as_ty) - } - } - )+ - }; -} - -// ===== impl Value ===== - -impl_values! { - record_u64(u64), - record_u64(usize, u32, u16 as u64), - record_i64(i64), - record_i64(isize, i32, i16, i8 as i64), - record_bool(bool) -} - -impl ::sealed::Sealed for str {} - -impl Value for str { - fn record(&self, key: &Field, visitor: &mut Visit) { - visitor.record_str(key, &self) - } -} - -impl<'a, T: ?Sized> ::sealed::Sealed for &'a T where T: Value + ::sealed::Sealed + 'a {} - -impl<'a, T: ?Sized> Value for &'a T -where - T: Value + 'a, -{ - 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, visitor: &mut Visit) { - visitor.record_debug(key, self) - } -} - -// ===== impl DisplayValue ===== - -impl ::sealed::Sealed for DisplayValue {} - -impl Value for DisplayValue -where - T: fmt::Display, -{ - fn record(&self, key: &Field, visitor: &mut Visit) { - visitor.record_debug(key, &format_args!("{}", self.0)) - } -} - -impl fmt::Debug for DisplayValue { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -// ===== impl DebugValue ===== - -impl ::sealed::Sealed for DebugValue {} - -impl Value for DebugValue -where - T: fmt::Debug, -{ - fn record(&self, key: &Field, visitor: &mut Visit) { - visitor.record_debug(key, &self.0) - } -} - -impl fmt::Debug for DebugValue { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.0) - } -} - -// ===== impl Field ===== - -impl Field { - /// Returns an [`Identifier`] that uniquely identifies the [`Callsite`] - /// which defines this field. - /// - /// [`Identifier`]: ../callsite/struct.Identifier.html - /// [`Callsite`]: ../callsite/trait.Callsite.html - #[inline] - pub fn callsite(&self) -> callsite::Identifier { - self.fields.callsite() - } - - /// Returns a string representing the name of the field. - pub fn name(&self) -> &'static str { - self.fields.names[self.i] - } -} - -impl fmt::Display for Field { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(self.name()) - } -} - -impl AsRef for Field { - fn as_ref(&self) -> &str { - self.name() - } -} - -impl PartialEq for Field { - fn eq(&self, other: &Self) -> bool { - self.callsite() == other.callsite() && self.i == other.i - } -} - -impl Eq for Field {} - -impl Hash for Field { - fn hash(&self, state: &mut H) - where - H: Hasher, - { - self.callsite().hash(state); - self.i.hash(state); - } -} - -impl Clone for Field { - fn clone(&self) -> Self { - Field { - i: self.i, - fields: FieldSet { - names: self.fields.names, - callsite: self.fields.callsite(), - }, - } - } -} - -// ===== impl FieldSet ===== - -impl FieldSet { - /// Returns an [`Identifier`] that uniquely identifies the [`Callsite`] - /// which defines this set of fields.. - /// - /// [`Identifier`]: ../callsite/struct.Identifier.html - /// [`Callsite`]: ../callsite/trait.Callsite.html - pub(crate) fn callsite(&self) -> callsite::Identifier { - callsite::Identifier(self.callsite.0) - } - - /// Returns the [`Field`] named `name`, or `None` if no such field exists. - /// - /// [`Field`]: ../struct.Field.html - pub fn field(&self, name: &Q) -> Option - where - Q: Borrow, - { - let name = &name.borrow(); - self.names.iter().position(|f| f == name).map(|i| Field { - i, - fields: FieldSet { - names: self.names, - callsite: self.callsite(), - }, - }) - } - - /// Returns `true` if `self` contains the given `field`. - /// - /// **Note**: If `field` shares a name with a field in this `FieldSet`, but - /// was created by a `FieldSet` with a different callsite, this `FieldSet` - /// does _not_ contain it. This is so that if two separate span callsites - /// define a field named "foo", the `Field` corresponding to "foo" for each - /// of those callsites are not equivalent. - pub fn contains(&self, field: &Field) -> bool { - field.callsite() == self.callsite() && field.i <= self.len() - } - - /// Returns an iterator over the `Field`s in this `FieldSet`. - pub fn iter(&self) -> Iter { - let idxs = 0..self.len(); - Iter { - idxs, - fields: FieldSet { - names: self.names, - callsite: self.callsite(), - }, - } - } - - /// Returns a new `ValueSet` with entries for this `FieldSet`'s values. - /// - /// Note that a `ValueSet` may not be constructed with arrays of over 32 - /// elements. - #[doc(hidden)] - pub fn value_set<'v, V>(&'v self, values: &'v V) -> ValueSet<'v> - where - V: ValidLen<'v>, - { - ValueSet { - fields: self, - values: &values.borrow()[..], - } - } - - /// Returns the number of fields in this `FieldSet`. - #[inline] - pub fn len(&self) -> usize { - self.names.len() - } -} - -impl<'a> IntoIterator for &'a FieldSet { - type IntoIter = Iter; - type Item = Field; - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl fmt::Debug for FieldSet { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("FieldSet") - .field("names", &self.names) - .field("callsite", &self.callsite) - .finish() - } -} - -impl fmt::Display for FieldSet { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_set() - .entries(self.names.iter().map(|n| display(n))) - .finish() - } -} - -// ===== impl Iter ===== - -impl Iterator for Iter { - type Item = Field; - fn next(&mut self) -> Option { - let i = self.idxs.next()?; - Some(Field { - i, - fields: FieldSet { - names: self.fields.names, - callsite: self.fields.callsite(), - }, - }) - } -} - -// ===== impl ValueSet ===== - -impl<'a> ValueSet<'a> { - /// Returns an [`Identifier`] that uniquely identifies the [`Callsite`] - /// defining the fields this `ValueSet` refers to. - /// - /// [`Identifier`]: ../callsite/struct.Identifier.html - /// [`Callsite`]: ../callsite/trait.Callsite.html - #[inline] - pub fn callsite(&self) -> callsite::Identifier { - self.fields.callsite() - } - - /// Visits all the fields in this `ValueSet` with the provided [visitor]. - /// - /// [visitor]: ../trait.Visit.html - 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, visitor); - } - } - } - - /// Returns `true` if this `ValueSet` contains a value for the given `Field`. - pub(crate) fn contains(&self, field: &Field) -> bool { - field.callsite() == self.callsite() - && self - .values - .iter() - .any(|(key, val)| *key == field && val.is_some()) - } - - /// Returns true if this `ValueSet` contains _no_ values. - pub(crate) fn is_empty(&self) -> bool { - let my_callsite = self.callsite(); - self.values - .iter() - .all(|(key, val)| val.is_none() || key.callsite() != my_callsite) - } - - pub(crate) fn field_set(&self) -> &FieldSet { - self.fields - } -} - -impl<'a> fmt::Debug for ValueSet<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.values - .iter() - .fold(&mut f.debug_struct("ValueSet"), |dbg, (key, v)| { - if let Some(val) = v { - val.record(key, dbg); - } - dbg - }) - .field("callsite", &self.callsite()) - .finish() - } -} - -impl<'a> fmt::Display for ValueSet<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.values - .iter() - .fold(&mut f.debug_map(), |dbg, (key, v)| { - if let Some(val) = v { - val.record(key, dbg); - } - dbg - }) - .finish() - } -} - -// ===== impl ValidLen ===== - -mod private { - use super::*; - - /// Marker trait implemented by arrays which are of valid length to - /// construct a `ValueSet`. - /// - /// `ValueSet`s may only be constructed from arrays containing 32 or fewer - /// elements, to ensure the array is small enough to always be allocated on the - /// stack. This trait is only implemented by arrays of an appropriate length, - /// ensuring that the correct size arrays are used at compile-time. - pub trait ValidLen<'a>: Borrow<[(&'a Field, Option<&'a (Value + 'a)>)]> {} -} - -macro_rules! impl_valid_len { - ( $( $len:tt ),+ ) => { - $( - impl<'a> private::ValidLen<'a> for - [(&'a Field, Option<&'a (Value + 'a)>); $len] {} - )+ - } -} - -impl_valid_len! { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 -} - -#[cfg(test)] -mod test { - use super::*; - use metadata::{Kind, Level, Metadata}; - - struct TestCallsite1; - static TEST_CALLSITE_1: TestCallsite1 = TestCallsite1; - static TEST_META_1: Metadata<'static> = metadata! { - name: "field_test1", - target: module_path!(), - level: Level::INFO, - fields: &["foo", "bar", "baz"], - callsite: &TEST_CALLSITE_1, - kind: Kind::SPAN, - }; - - impl ::callsite::Callsite for TestCallsite1 { - fn set_interest(&self, _: ::subscriber::Interest) { - unimplemented!() - } - - fn metadata(&self) -> &Metadata { - &TEST_META_1 - } - } - - struct TestCallsite2; - static TEST_CALLSITE_2: TestCallsite2 = TestCallsite2; - static TEST_META_2: Metadata<'static> = metadata! { - name: "field_test2", - target: module_path!(), - level: Level::INFO, - fields: &["foo", "bar", "baz"], - callsite: &TEST_CALLSITE_2, - kind: Kind::SPAN, - }; - - impl ::callsite::Callsite for TestCallsite2 { - fn set_interest(&self, _: ::subscriber::Interest) { - unimplemented!() - } - - fn metadata(&self) -> &Metadata { - &TEST_META_2 - } - } - - #[test] - fn value_set_with_no_values_is_empty() { - let fields = TEST_META_1.fields(); - let values = &[ - (&fields.field("foo").unwrap(), None), - (&fields.field("bar").unwrap(), None), - (&fields.field("baz").unwrap(), None), - ]; - let valueset = fields.value_set(values); - assert!(valueset.is_empty()); - } - - #[test] - fn empty_value_set_is_empty() { - let fields = TEST_META_1.fields(); - let valueset = fields.value_set(&[]); - assert!(valueset.is_empty()); - } - - #[test] - fn value_sets_with_fields_from_other_callsites_are_empty() { - let fields = TEST_META_1.fields(); - let values = &[ - (&fields.field("foo").unwrap(), Some(&1 as &Value)), - (&fields.field("bar").unwrap(), Some(&2 as &Value)), - (&fields.field("baz").unwrap(), Some(&3 as &Value)), - ]; - let valueset = TEST_META_2.fields().value_set(values); - assert!(valueset.is_empty()) - } - - #[test] - fn sparse_value_sets_are_not_empty() { - let fields = TEST_META_1.fields(); - let values = &[ - (&fields.field("foo").unwrap(), None), - (&fields.field("bar").unwrap(), Some(&57 as &Value)), - (&fields.field("baz").unwrap(), None), - ]; - let valueset = fields.value_set(values); - assert!(!valueset.is_empty()); - } - - #[test] - fn fields_from_other_callsets_are_skipped() { - let fields = TEST_META_1.fields(); - let values = &[ - (&fields.field("foo").unwrap(), None), - ( - &TEST_META_2.fields().field("bar").unwrap(), - Some(&57 as &Value), - ), - (&fields.field("baz").unwrap(), None), - ]; - - 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 MyVisitor); - } - - #[test] - fn record_debug_fn() { - let fields = TEST_META_1.fields(); - let values = &[ - (&fields.field("foo").unwrap(), Some(&1 as &Value)), - (&fields.field("bar").unwrap(), Some(&2 as &Value)), - (&fields.field("baz").unwrap(), Some(&3 as &Value)), - ]; - let valueset = fields.value_set(values); - let mut result = String::new(); - valueset.record(&mut |_: &Field, value: &fmt::Debug| { - use std::fmt::Write; - write!(&mut result, "{:?}", value).unwrap(); - }); - assert_eq!(result, "123".to_owned()); - } -} diff --git a/tokio-trace/tokio-trace-core/src/lib.rs b/tokio-trace/tokio-trace-core/src/lib.rs deleted file mode 100644 index b72670c32..000000000 --- a/tokio-trace/tokio-trace-core/src/lib.rs +++ /dev/null @@ -1,213 +0,0 @@ -#![doc(html_root_url = "https://docs.rs/tokio-trace-core/0.2.0")] -#![deny(missing_debug_implementations, missing_docs, unreachable_pub)] -#![cfg_attr(test, deny(warnings))] - -//! Core primitives for `tokio-trace`. -//! -//! `tokio-trace` is a framework for instrumenting Rust programs to collect -//! structured, event-based diagnostic information. This crate defines the core -//! primitives of `tokio-trace`. -//! -//! This crate provides: -//! -//! * [`Span`] identifies a span within the execution of a program. -//! -//! * [`Event`] represents a single event within a trace. -//! -//! * [`Subscriber`], the trait implemented to collect trace data. -//! -//! * [`Metadata`] and [`Callsite`] provide information describing `Span`s. -//! -//! * [`Field`], [`FieldSet`], [`Value`], and [`ValueSet`] represent the -//! structured data attached to a `Span`. -//! -//! * [`Dispatch`] allows span events to be dispatched to `Subscriber`s. -//! -//! In addition, it defines the global callsite registry and per-thread current -//! dispatcher which other components of the tracing system rely on. -//! -//! Application authors will typically not use this crate directly. Instead, -//! they will use the `tokio-trace` crate, which provides a much more -//! fully-featured API. However, this crate's API will change very infrequently, -//! so it may be used when dependencies must be very stable. -//! -//! The [`tokio-trace-nursery`] repository contains less stable crates designed to -//! be used with the `tokio-trace` ecosystem. It includes a collection of -//! `Subscriber` implementations, as well as utility and adapter crates. -//! -//! [`Span`]: span/struct.Span.html -//! [`Event`]: event/struct.Event.html -//! [`Subscriber`]: subscriber/trait.Subscriber.html -//! [`Metadata`]: metadata/struct.Metadata.html -//! [`Callsite`]: callsite/trait.Callsite.html -//! [`Field`]: field/struct.Field.html -//! [`FieldSet`]: field/struct.FieldSet.html -//! [`Value`]: field/trait.Value.html -//! [`ValueSet`]: field/struct.ValueSet.html -//! [`Dispatch`]: dispatcher/struct.Dispatch.html -//! [`tokio-trace-nursery`]: https://github.com/tokio-rs/tokio-trace-nursery -#[macro_use] -extern crate lazy_static; - -/// Statically constructs an [`Identifier`] for the provided [`Callsite`]. -/// -/// This may be used in contexts, such as static initializers, where the -/// [`Callsite::id`] function is not currently usable. -/// -/// For example: -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace_core; -/// use tokio_trace_core::callsite; -/// # use tokio_trace_core::{Metadata, subscriber::Interest}; -/// # fn main() { -/// pub struct MyCallsite { -/// // ... -/// } -/// impl callsite::Callsite for MyCallsite { -/// # fn set_interest(&self, _: Interest) { unimplemented!() } -/// # fn metadata(&self) -> &Metadata { unimplemented!() } -/// // ... -/// } -/// -/// static CALLSITE: MyCallsite = MyCallsite { -/// // ... -/// }; -/// -/// static CALLSITE_ID: callsite::Identifier = identify_callsite!(&CALLSITE); -/// # } -/// ``` -/// -/// [`Identifier`]: callsite/struct.Identifier.html -/// [`Callsite`]: callsite/trait.Callsite.html -/// [`Callsite`]: callsite/trait.Callsite.html#method.id -#[macro_export] -macro_rules! identify_callsite { - ($callsite:expr) => { - $crate::callsite::Identifier($callsite) - }; -} - -/// Statically constructs new span [metadata]. -/// -/// This may be used in contexts, such as static initializers, where the -/// [`Metadata::new`] function is not currently usable. -/// -/// /// For example: -/// ```rust -/// # #[macro_use] -/// # extern crate tokio_trace_core; -/// # use tokio_trace_core::{callsite::Callsite, subscriber::Interest}; -/// use tokio_trace_core::metadata::{Kind, Level, Metadata}; -/// # fn main() { -/// # pub struct MyCallsite { } -/// # impl Callsite for MyCallsite { -/// # fn set_interest(&self, _: Interest) { unimplemented!() } -/// # fn metadata(&self) -> &Metadata { unimplemented!() } -/// # } -/// # -/// static FOO_CALLSITE: MyCallsite = MyCallsite { -/// // ... -/// }; -/// -/// static FOO_METADATA: Metadata = metadata!{ -/// name: "foo", -/// target: module_path!(), -/// level: Level::DEBUG, -/// fields: &["bar", "baz"], -/// callsite: &FOO_CALLSITE, -/// kind: Kind::SPAN, -/// }; -/// # } -/// ``` -/// -/// [metadata]: metadata/struct.Metadata.html -/// [`Metadata::new`]: metadata/struct.Metadata.html#method.new -#[macro_export(local_inner_macros)] -macro_rules! metadata { - ( - name: $name:expr, - target: $target:expr, - level: $level:expr, - fields: $fields:expr, - callsite: $callsite:expr, - kind: $kind:expr - ) => { - metadata! { - name: $name, - target: $target, - level: $level, - fields: $fields, - callsite: $callsite, - kind: $kind, - } - }; - ( - name: $name:expr, - target: $target:expr, - level: $level:expr, - fields: $fields:expr, - callsite: $callsite:expr, - kind: $kind:expr, - ) => { - $crate::metadata::Metadata { - name: $name, - target: $target, - level: $level, - file: Some(__tokio_trace_core_file!()), - line: Some(__tokio_trace_core_line!()), - module_path: Some(__tokio_trace_core_module_path!()), - fields: $crate::field::FieldSet { - names: $fields, - callsite: identify_callsite!($callsite), - }, - kind: $kind, - } - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_core_module_path { - () => { - module_path!() - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_core_file { - () => { - file!() - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __tokio_trace_core_line { - () => { - line!() - }; -} - -pub mod callsite; -pub mod dispatcher; -pub mod event; -pub mod field; -pub mod metadata; -mod parent; -pub mod span; -pub mod subscriber; - -pub use self::{ - callsite::Callsite, - dispatcher::Dispatch, - event::Event, - field::Field, - metadata::{Kind, Level, Metadata}, - subscriber::{Interest, Subscriber}, -}; - -mod sealed { - pub trait Sealed {} -} diff --git a/tokio-trace/tokio-trace-core/src/metadata.rs b/tokio-trace/tokio-trace-core/src/metadata.rs deleted file mode 100644 index 545920b15..000000000 --- a/tokio-trace/tokio-trace-core/src/metadata.rs +++ /dev/null @@ -1,370 +0,0 @@ -//! Metadata describing trace data. -use super::{ - callsite::{self, Callsite}, - field, -}; -use std::fmt; - -/// Metadata describing a [span] or [event]. -/// -/// All spans and events have the following metadata: -/// - A [name], represented as a static string. -/// - A [target], a string that categorizes part of the system where the span -/// or event occurred. The `tokio_trace` macros default to using the module -/// path where the span or event originated as the target, but it may be -/// overridden. -/// - A [verbosity level]. -/// - The names of the [fields] defined by the span or event. -/// - Whether the metadata corresponds to a span or event. -/// -/// In addition, the following optional metadata describing the source code -/// location where the span or event originated _may_ be provided: -/// - The [file name] -/// - The [line number] -/// - The [module path] -/// -/// Metadata is used by [`Subscriber`]s when filtering spans and events, and it -/// may also be used as part of their data payload. -/// -/// When created by the `event!` or `span!` macro, the metadata describing a -/// particular event or span is constructed statically and exists as a single -/// static instance. Thus, the overhead of creating the metadata is -/// _significantly_ lower than that of creating the actual span. Therefore, -/// filtering is based on metadata, rather than on the constructed span. -/// -/// **Note**: Although instances of `Metadata` cannot be compared directly, they -/// provide a method [`id`] which returns an an opaque [callsite identifier] -/// which uniquely identifies the callsite where the metadata originated. -/// This can be used for determining if two Metadata correspond to -/// the same callsite. -/// -/// [span]: ../span/index.html -/// [event]: ../event/index.html -/// [name]: #method.name -/// [target]: #method.target -/// [fields]: #method.fields -/// [verbosity level]: #method.level -/// [file name]: #method.file -/// [line number]: #method.line -/// [module path]: #method.module -/// [`Subscriber`]: ../subscriber/trait.Subscriber.html -/// [`id`]: struct.Metadata.html#method.id -/// [callsite identifier]: ../callsite/struct.Identifier.html -// TODO: When `const fn` is stable, make this type's fields private. -pub struct Metadata<'a> { - /// The name of the span described by this metadata. - /// - /// **Warning**: The fields on this type are currently `pub` because it must - /// be able to be constructed statically by macros. However, when `const - /// fn`s are available on stable Rust, this will no longer be necessary. - /// Thus, these fields are *not* considered stable public API, and they may - /// change warning. Do not rely on any fields on `Metadata`. When - /// constructing new `Metadata`, use the `metadata!` macro or the - /// `Metadata::new` constructor instead! - #[doc(hidden)] - pub name: &'static str, - - /// The part of the system that the span that this metadata describes - /// occurred in. - /// - /// Typically, this is the module path, but alternate targets may be set - /// when spans or events are constructed. - /// - /// **Warning**: The fields on this type are currently `pub` because it must - /// be able to be constructed statically by macros. However, when `const - /// fn`s are available on stable Rust, this will no longer be necessary. - /// Thus, these fields are *not* considered stable public API, and they may - /// change warning. Do not rely on any fields on `Metadata`. When - /// constructing new `Metadata`, use the `metadata!` macro or the - /// `Metadata::new` constructor instead! - #[doc(hidden)] - pub target: &'a str, - - /// The level of verbosity of the described span. - /// - /// **Warning**: The fields on this type are currently `pub` because it must - /// be able to be constructed statically by macros. However, when `const - /// fn`s are available on stable Rust, this will no longer be necessary. - /// Thus, these fields are *not* considered stable public API, and they may - /// change warning. Do not rely on any fields on `Metadata`. When - /// constructing new `Metadata`, use the `metadata!` macro or the - /// `Metadata::new` constructor instead! - #[doc(hidden)] - pub level: Level, - - /// The name of the Rust module where the span occurred, or `None` if this - /// could not be determined. - /// - /// **Warning**: The fields on this type are currently `pub` because it must - /// be able to be constructed statically by macros. However, when `const - /// fn`s are available on stable Rust, this will no longer be necessary. - /// Thus, these fields are *not* considered stable public API, and they may - /// change warning. Do not rely on any fields on `Metadata`. When - /// constructing new `Metadata`, use the `metadata!` macro or the - /// `Metadata::new` constructor instead! - #[doc(hidden)] - pub module_path: Option<&'a str>, - - /// The name of the source code file where the span occurred, or `None` if - /// this could not be determined. - /// - /// **Warning**: The fields on this type are currently `pub` because it must - /// be able to be constructed statically by macros. However, when `const - /// fn`s are available on stable Rust, this will no longer be necessary. - /// Thus, these fields are *not* considered stable public API, and they may - /// change warning. Do not rely on any fields on `Metadata`. When - /// constructing new `Metadata`, use the `metadata!` macro or the - /// `Metadata::new` constructor instead! - #[doc(hidden)] - pub file: Option<&'a str>, - - /// The line number in the source code file where the span occurred, or - /// `None` if this could not be determined. - /// - /// **Warning**: The fields on this type are currently `pub` because it must - /// be able to be constructed statically by macros. However, when `const - /// fn`s are available on stable Rust, this will no longer be necessary. - /// Thus, these fields are *not* considered stable public API, and they may - /// change warning. Do not rely on any fields on `Metadata`. When - /// constructing new `Metadata`, use the `metadata!` macro or the - /// `Metadata::new` constructor instead! - #[doc(hidden)] - pub line: Option, - - /// The names of the key-value fields attached to the described span or - /// event. - /// - /// **Warning**: The fields on this type are currently `pub` because it must - /// be able to be constructed statically by macros. However, when `const - /// fn`s are available on stable Rust, this will no longer be necessary. - /// Thus, these fields are *not* considered stable public API, and they may - /// change warning. Do not rely on any fields on `Metadata`. When - /// constructing new `Metadata`, use the `metadata!` macro or the - /// `Metadata::new` constructor instead! - #[doc(hidden)] - pub fields: field::FieldSet, - - /// The kind of the callsite. - /// - /// **Warning**: The fields on this type are currently `pub` because it must - /// be able to be constructed statically by macros. However, when `const - /// fn`s are available on stable Rust, this will no longer be necessary. - /// Thus, these fields are *not* considered stable public API, and they may - /// change warning. Do not rely on any fields on `Metadata`. When - /// constructing new `Metadata`, use the `metadata!` macro or the - /// `Metadata::new` constructor instead! - #[doc(hidden)] - pub kind: Kind, -} - -/// Indicates whether the callsite is a span or event. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct Kind(KindInner); - -/// Describes the level of verbosity of a span or event. -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] -pub struct Level(LevelInner); - -// ===== impl Metadata ===== - -impl<'a> Metadata<'a> { - /// Construct new metadata for a span, with a name, target, level, field - /// names, and optional source code location. - pub fn new( - name: &'static str, - target: &'a str, - level: Level, - module_path: Option<&'a str>, - file: Option<&'a str>, - line: Option, - field_names: &'static [&'static str], - callsite: &'static Callsite, - kind: Kind, - ) -> Self { - Metadata { - name, - target, - level, - module_path, - file, - line, - fields: field::FieldSet { - names: field_names, - callsite: callsite::Identifier(callsite), - }, - kind, - } - } - - /// Returns the names of the fields on the described span or event. - pub fn fields(&self) -> &field::FieldSet { - &self.fields - } - - /// Returns the level of verbosity of the described span or event. - pub fn level(&self) -> &Level { - &self.level - } - - /// Returns the name of the span. - pub fn name(&self) -> &'static str { - self.name - } - - /// Returns a string describing the part of the system where the span or - /// event that this metadata describes occurred. - /// - /// Typically, this is the module path, but alternate targets may be set - /// when spans or events are constructed. - pub fn target(&self) -> &'a str { - self.target - } - - /// Returns the path to the Rust module where the span occurred, or - /// `None` if the module path is unknown. - pub fn module_path(&self) -> Option<&'a str> { - self.module_path - } - - /// Returns the name of the source code file where the span - /// occurred, or `None` if the file is unknown - pub fn file(&self) -> Option<&'a str> { - self.file - } - - /// Returns the line number in the source code file where the span - /// occurred, or `None` if the line number is unknown. - pub fn line(&self) -> Option { - self.line - } - - /// Returns an opaque `Identifier` that uniquely identifies the callsite - /// this `Metadata` originated from. - #[inline] - pub fn callsite(&self) -> callsite::Identifier { - self.fields.callsite() - } - - /// Returns true if the callsite kind is `Event`. - pub fn is_event(&self) -> bool { - self.kind.is_event() - } - - /// Return true if the callsite kind is `Span`. - pub fn is_span(&self) -> bool { - self.kind.is_span() - } -} - -impl<'a> fmt::Debug for Metadata<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut meta = f.debug_struct("Metadata"); - meta.field("name", &self.name) - .field("target", &self.target) - .field("level", &self.level); - - if let Some(path) = self.module_path() { - meta.field("module_path", &path); - } - - match (self.file(), self.line()) { - (Some(file), Some(line)) => { - meta.field("location", &format_args!("{}:{}", file, line)); - } - (Some(file), None) => { - meta.field("file", &format_args!("{}", file)); - } - - // Note: a line num with no file is a kind of weird case that _probably_ never occurs... - (None, Some(line)) => { - meta.field("line", &line); - } - (None, None) => {} - }; - - meta.field("fields", &format_args!("{}", self.fields)) - .field("callsite", &self.callsite()) - .field("kind", &self.kind) - .finish() - } -} - -#[derive(Clone, Debug, Eq, PartialEq)] -enum KindInner { - Event, - Span, -} - -impl Kind { - /// `Event` callsite - pub const EVENT: Kind = Kind(KindInner::Event); - - /// `Span` callsite - pub const SPAN: Kind = Kind(KindInner::Span); - - /// Return true if the callsite kind is `Span` - pub fn is_span(&self) -> bool { - match self { - Kind(KindInner::Span) => true, - _ => false, - } - } - - /// Return true if the callsite kind is `Event` - pub fn is_event(&self) -> bool { - match self { - Kind(KindInner::Event) => true, - _ => false, - } - } -} - -// ===== impl Level ===== - -impl Level { - /// The "error" level. - /// - /// Designates very serious errors. - pub const ERROR: Level = Level(LevelInner::Error); - /// The "warn" level. - /// - /// Designates hazardous situations. - pub const WARN: Level = Level(LevelInner::Warn); - /// The "info" level. - /// - /// Designates useful information. - pub const INFO: Level = Level(LevelInner::Info); - /// The "debug" level. - /// - /// Designates lower priority information. - pub const DEBUG: Level = Level(LevelInner::Debug); - /// The "trace" level. - /// - /// Designates very low priority, often extremely verbose, information. - pub const TRACE: Level = Level(LevelInner::Trace); -} - -#[repr(usize)] -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] -enum LevelInner { - /// The "error" level. - /// - /// Designates very serious errors. - Error = 1, - /// The "warn" level. - /// - /// Designates hazardous situations. - Warn, - /// The "info" level. - /// - /// Designates useful information. - Info, - /// The "debug" level. - /// - /// Designates lower priority information. - Debug, - /// The "trace" level. - /// - /// Designates very low priority, often extremely verbose, information. - Trace, -} diff --git a/tokio-trace/tokio-trace-core/src/parent.rs b/tokio-trace/tokio-trace-core/src/parent.rs deleted file mode 100644 index 91715ad93..000000000 --- a/tokio-trace/tokio-trace-core/src/parent.rs +++ /dev/null @@ -1,11 +0,0 @@ -use span::Id; - -#[derive(Debug)] -pub(crate) enum Parent { - /// The new span will be a root span. - Root, - /// The new span will be rooted in the current span. - Current, - /// The new span has an explicitly-specified parent. - Explicit(Id), -} diff --git a/tokio-trace/tokio-trace-core/src/span.rs b/tokio-trace/tokio-trace-core/src/span.rs deleted file mode 100644 index 64d32c9d2..000000000 --- a/tokio-trace/tokio-trace-core/src/span.rs +++ /dev/null @@ -1,185 +0,0 @@ -//! Spans represent periods of time in the execution of a program. - -use parent::Parent; -use {field, Metadata}; - -/// Identifies a span within the context of a subscriber. -/// -/// They are generated by [`Subscriber`]s for each span as it is created, by -/// the [`new_span`] trait method. See the documentation for that method for -/// more information on span ID generation. -/// -/// [`Subscriber`]: ../subscriber/trait.Subscriber.html -/// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -// TODO(eliza): when Tokio's minimum Rust version is >= 1.28, change the -// internal representation to a `NonZeroU64`. -pub struct Id(u64); - -/// Attributes provided to a `Subscriber` describing a new span when it is -/// created. -#[derive(Debug)] -pub struct Attributes<'a> { - metadata: &'a Metadata<'a>, - values: &'a field::ValueSet<'a>, - parent: Parent, -} - -/// A set of fields recorded by a span. -#[derive(Debug)] -pub struct Record<'a> { - values: &'a field::ValueSet<'a>, -} - -// ===== impl Span ===== - -impl Id { - /// Constructs a new span ID from the given `u64`. - /// - /// **Note**: Span IDs must be greater than zero. - /// - /// # Panics - /// - If the provided `u64` is 0 - pub fn from_u64(u: u64) -> Self { - assert!(u > 0); - Id(u) - } - - /// Returns the span's ID as a `u64`. - pub fn into_u64(&self) -> u64 { - self.0 - } -} - -impl<'a> Into> for &'a Id { - fn into(self) -> Option { - Some(self.clone()) - } -} - -// ===== impl Attributes ===== - -impl<'a> Attributes<'a> { - /// Returns `Attributes` describing a new child span of the current span, - /// with the provided metadata and values. - pub fn new(metadata: &'a Metadata<'a>, values: &'a field::ValueSet<'a>) -> Self { - Attributes { - metadata, - values, - parent: Parent::Current, - } - } - - /// Returns `Attributes` describing a new span at the root of its own trace - /// tree, with the provided metadata and values. - pub fn new_root(metadata: &'a Metadata<'a>, values: &'a field::ValueSet<'a>) -> Self { - Attributes { - metadata, - values, - parent: Parent::Root, - } - } - - /// Returns `Attributes` describing a new child span of the specified - /// parent span, with the provided metadata and values. - pub fn child_of( - parent: Id, - metadata: &'a Metadata<'a>, - values: &'a field::ValueSet<'a>, - ) -> Self { - Attributes { - metadata, - values, - parent: Parent::Explicit(parent), - } - } - - /// Returns a reference to the new span's metadata. - pub fn metadata(&self) -> &Metadata<'a> { - self.metadata - } - - /// Returns a reference to a `ValueSet` containing any values the new span - /// was created with. - pub fn values(&self) -> &field::ValueSet<'a> { - self.values - } - - /// Returns true if the new span shoold be a root. - pub fn is_root(&self) -> bool { - match self.parent { - Parent::Root => true, - _ => false, - } - } - - /// Returns true if the new span's parent should be determined based on the - /// current context. - /// - /// If this is true and the current thread is currently inside a span, then - /// that span should be the new span's parent. Otherwise, if the current - /// thread is _not_ inside a span, then the new span will be the root of its - /// own trace tree. - pub fn is_contextual(&self) -> bool { - match self.parent { - Parent::Current => true, - _ => false, - } - } - - /// Returns the new span's explicitly-specified parent, if there is one. - /// - /// Otherwise (if the new span is a root or is a child of the current span), - /// returns false. - pub fn parent(&self) -> Option<&Id> { - match self.parent { - Parent::Explicit(ref p) => Some(p), - _ => None, - } - } - - /// Records all the fields in this set of `Attributes` with the provided - /// [Visitor]. - /// - /// [visitor]: ../field/trait.Visit.html - 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/trait.Visit.html - 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() - } -} diff --git a/tokio-trace/tokio-trace-core/src/subscriber.rs b/tokio-trace/tokio-trace-core/src/subscriber.rs deleted file mode 100644 index b052bb274..000000000 --- a/tokio-trace/tokio-trace-core/src/subscriber.rs +++ /dev/null @@ -1,477 +0,0 @@ -//! Subscribers collect and record trace data. -use {span, Event, Metadata}; - -use std::{ - any::{Any, TypeId}, - ptr, -}; - -/// Trait representing the functions required to collect trace data. -/// -/// Crates that provide implementations of methods for collecting or recording -/// trace data should implement the `Subscriber` interface. This trait is -/// intended to represent fundamental primitives for collecting trace events and -/// spans — other libraries may offer utility functions and types to make -/// subscriber implementations more modular or improve the ergonomics of writing -/// subscribers. -/// -/// A subscriber is responsible for the following: -/// - 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 -/// spans. -/// - Filtering spans and events, and determining when those filters must be -/// invalidated. -/// - Observing spans as they are entered, exited, and closed, and events as -/// they occur. -/// -/// When a span is entered or exited, the subscriber is provided only with the -/// [ID] with which it tagged that span when it was created. This means -/// that it is up to the subscriber to determine whether and how span _data_ — -/// the fields and metadata describing the span — should be stored. The -/// [`new_span`] function is called when a new span is created, and at that -/// point, the subscriber _may_ choose to store the associated data if it will -/// be referenced again. However, if the data has already been recorded and will -/// not be needed by the implementations of `enter` and `exit`, the subscriber -/// may freely discard that data without allocating space to store it. -/// -/// [ID]: ../span/struct.Id.html -/// [`new_span`]: trait.Subscriber.html#method.new_span -pub trait Subscriber: 'static { - // === Span registry methods ============================================== - - /// Registers a new callsite with this subscriber, returning whether or not - /// the subscriber is interested in being notified about the callsite. - /// - /// By default, this function assumes that the subscriber's [filter] - /// represents an unchanging view of its interest in the callsite. However, - /// if this is not the case, subscribers may override this function to - /// indicate different interests, or to implement behaviour that should run - /// once for every callsite. - /// - /// This function is guaranteed to be called at least once per callsite on - /// every active subscriber. The subscriber may store the keys to fields it - /// cares about in order to reduce the cost of accessing fields by name, - /// preallocate storage for that callsite, or perform any other actions it - /// wishes to perform once for each callsite. - /// - /// The subscriber should then return an [`Interest`], indicating - /// whether it is interested in being notified about that callsite in the - /// future. This may be `Always` indicating that the subscriber always - /// wishes to be notified about the callsite, and its filter need not be - /// re-evaluated; `Sometimes`, indicating that the subscriber may sometimes - /// care about the callsite but not always (such as when sampling), or - /// `Never`, indicating that the subscriber never wishes to be notified about - /// that callsite. If all active subscribers return `Never`, a callsite will - /// never be enabled unless a new subscriber expresses interest in it. - /// - /// `Subscriber`s which require their filters to be run every time an event - /// occurs or a span is entered/exited should return `Interest::sometimes`. - /// If a subscriber returns `Interest::sometimes`, then its' [`enabled`] method - /// will be called every time an event or span is created from that callsite. - /// - /// For example, suppose a sampling subscriber is implemented by - /// incrementing a counter every time `enabled` is called and only returning - /// `true` when the counter is divisible by a specified sampling rate. If - /// that subscriber returns `Interest::always` from `register_callsite`, then - /// the filter will not be re-evaluated once it has been applied to a given - /// set of metadata. Thus, the counter will not be incremented, and the span - /// or event that correspands to the metadata will never be `enabled`. - /// - /// `Subscriber`s that need to change their filters occasionally should call - /// [`rebuild_interest_cache`] to re-evaluate `register_callsite` for all - /// callsites. - /// - /// Similarly, if a `Subscriber` has a filtering strategy that can be - /// changed dynamically at runtime, it would need to re-evaluate that filter - /// if the cached results have changed. - /// - /// A subscriber which manages fanout to multiple other subscribers - /// should proxy this decision to all of its child subscribers, - /// returning `Interest::never` only if _all_ such children return - /// `Interest::never`. If the set of subscribers to which spans are - /// broadcast may change dynamically, the subscriber should also never - /// return `Interest::Never`, as a new subscriber may be added that _is_ - /// interested. - /// - /// # Notes - /// This function may be called again when a new subscriber is created or - /// when the registry is invalidated. - /// - /// If a subscriber returns `Interest::never` for a particular callsite, it - /// _may_ still see spans and events originating from that callsite, if - /// another subscriber expressed interest in it. - /// - /// [filter]: #method.enabled - /// [metadata]: ../metadata/struct.Metadata.html - /// [`Interest`]: struct.Interest.html - /// [`enabled`]: #method.enabled - /// [`rebuild_interest_cache`]: ../callsite/fn.rebuild_interest_cache.html - fn register_callsite(&self, metadata: &Metadata) -> Interest { - match self.enabled(metadata) { - true => Interest::always(), - false => Interest::never(), - } - } - - /// Returns true if a span or event with the specified [metadata] would be - /// recorded. - /// - /// By default, it is assumed that this filter needs only be evaluated once - /// for each callsite, so it is called by [`register_callsite`] when each - /// callsite is registered. The result is used to determine if the subscriber - /// is always [interested] or never interested in that callsite. This is intended - /// primarily as an optimization, so that expensive filters (such as those - /// involving string search, et cetera) need not be re-evaluated. - /// - /// However, if the subscriber's interest in a particular span or event may - /// change, or depends on contexts only determined dynamically at runtime, - /// then the `register_callsite` method should be overridden to return - /// [`Interest::sometimes`]. In that case, this function will be called every - /// time that span or event occurs. - /// - /// [metadata]: ../metadata/struct.Metadata.html - /// [interested]: struct.Interest.html - /// [`Interest::sometimes`]: struct.Interest.html#method.sometimes - /// [`register_callsite`]: #method.register_callsite - fn enabled(&self, metadata: &Metadata) -> bool; - - /// Visit the construction of a new span, returning a new [span ID] for the - /// span being constructed. - /// - /// The provided [`Attributes`] contains any field values that were provided - /// when the span was created. The subscriber may pass a [visitor] to the - /// `Attributes`' [`record` method] to record these values. - /// - /// IDs are used to uniquely identify spans and events within the context of a - /// subscriber, so span equality will be based on the returned ID. Thus, if - /// the subscriber wishes for all spans with the same metadata to be - /// considered equal, it should return the same ID every time it is given a - /// particular set of metadata. Similarly, if it wishes for two separate - /// instances of a span with the same metadata to *not* be equal, it should - /// return a distinct ID every time this function is called, regardless of - /// the metadata. - /// - /// Note that the subscriber is free to assign span IDs based on whatever - /// scheme it sees fit. Any guarantees about uniqueness, ordering, or ID - /// reuse are left up to the subscriber implementation to determine. - /// - /// [span ID]: ../span/struct.Id.html - /// [`Attributes`]: ../span/struct.Attributes.html - /// [visitor]: ../field/trait.Visit.html - /// [`record` method]: ../span/struct.Attributes.html#method.record - fn new_span(&self, span: &span::Attributes) -> span::Id; - - // === Notification methods =============================================== - - /// Record a set of values on a span. - /// - /// This method will be invoked when value is recorded on a span. - /// Recording multiple values for the same field is possible, - /// but the actual behaviour is defined by the subscriber implementation. - /// - /// Keep in mind that a span might not provide a value - /// for each field it declares. - /// - /// The subscriber is expected to provide a [visitor] to the `Record`'s - /// [`record` method] in order to record the added values. - /// - /// # Example - /// "foo = 3" will be recorded when [`record`] is called on the - /// `Attributes` passed to `new_span`. - /// Since values are not provided for the `bar` and `baz` fields, - /// the span's `Metadata` will indicate that it _has_ those fields, - /// but values for them won't be recorded at this time. - /// - /// ```rust,ignore - /// #[macro_use] - /// extern crate tokio_trace; - /// - /// let mut span = span!("my_span", foo = 3, bar, baz); - /// - /// // `Subscriber::record` will be called with a `Record` - /// // containing "bar = false" - /// span.record("bar", &false); - /// - /// // `Subscriber::record` will be called with a `Record` - /// // containing "baz = "a string"" - /// span.record("baz", &"a string"); - /// ``` - /// - /// [visitor]: ../field/trait.Visit.html - /// [`record`]: ../span/struct.Attributes.html#method.record - /// [`record` method]: ../span/struct.Record.html#method.record - fn record(&self, span: &span::Id, values: &span::Record); - - /// Adds an indication that `span` follows from the span with the id - /// `follows`. - /// - /// This relationship differs somewhat from the parent-child relationship: a - /// span may have any number of prior spans, rather than a single one; and - /// spans are not considered to be executing _inside_ of the spans they - /// follow from. This means that a span may close even if subsequent spans - /// that follow from it are still open, and time spent inside of a - /// subsequent span should not be included in the time its precedents were - /// executing. This is used to model causal relationships such as when a - /// single future spawns several related background tasks, et cetera. - /// - /// If the subscriber has spans corresponding to the given IDs, it should - /// record this relationship in whatever way it deems necessary. Otherwise, - /// if one or both of the given span IDs do not correspond to spans that the - /// subscriber knows about, or if a cyclical relationship would be created - /// (i.e., some span _a_ which proceeds some other span _b_ may not also - /// 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. - /// - /// This method will be invoked when an Event is constructed by - /// the `Event`'s [`dispatch` method]. For example, this happens internally - /// when an event macro from `tokio-trace` is called. - /// - /// The key difference between this method and `record` is that `record` is - /// called when a value is recorded for a field defined by a span, - /// while `event` is called when a new event occurs. - /// - /// The provided `Event` struct contains any field values attached to the - /// event. The subscriber may pass a [visitor] to the `Event`'s - /// [`record` method] to record these values. - /// - /// [`Event`]: ../event/struct.Event.html - /// [visitor]: ../field/trait.Visit.html - /// [`record` method]: ../event/struct.Event.html#method.record - /// [`dispatch` method]: ../event/struct.Event.html#method.dispatch - fn event(&self, event: &Event); - - /// Records that a span has 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 - /// [span ID] of the entered span, and should update any internal state - /// tracking the current span accordingly. - /// - /// [span ID]: ../span/struct.Id.html - fn enter(&self, span: &span::Id); - - /// Records 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 - /// [span ID] of the exited span, and should update any internal state - /// tracking the current span accordingly. - /// - /// Exiting a span does not imply that the span will not be re-entered. - /// - /// [span ID]: ../span/struct.Id.html - fn exit(&self, span: &span::Id); - - /// Notifies the subscriber that a [span ID] has been cloned. - /// - /// This function is guaranteed to only be called with span IDs that were - /// returned by this subscriber's `new_span` function. - /// - /// Note that the default implementation of this function this is just the - /// identity function, passing through the identifier. However, it can be - /// used in conjunction with [`drop_span`] to track the number of handles - /// capable of `enter`ing a span. When all the handles have been dropped - /// (i.e., `drop_span` has been called one more time than `clone_span` for a - /// given ID), the subscriber may assume that the span will not be entered - /// again. It is then free to deallocate storage for data associated with - /// that span, write data from that span to IO, and so on. - /// - /// For more unsafe situations, however, if `id` is itself a pointer of some - /// kind this can be used as a hook to "clone" the pointer, depending on - /// what that means for the specified pointer. - /// - /// [span ID]: ../span/struct.Id.html - /// [`drop_span`]: trait.Subscriber.html#method.drop_span - fn clone_span(&self, id: &span::Id) -> span::Id { - id.clone() - } - - /// Notifies the subscriber that a [span ID] has been dropped. - /// - /// This function is guaranteed to only be called with span IDs that were - /// returned by this subscriber's `new_span` function. - /// - /// It's guaranteed that if this function has been called once more than the - /// number of times `clone_span` was called with the same `id`, then no more - /// spans using that `id` exist. This means that it can be used in - /// conjunction with [`clone_span`] to track the number of handles - /// capable of `enter`ing a span. When all the handles have been dropped - /// (i.e., `drop_span` has been called one more time than `clone_span` for a - /// given ID), the subscriber may assume that the span will not be entered - /// again. It is then free to deallocate storage for data associated with - /// that span, write data from that span to IO, and so on. - /// - /// **Note**: since this function is called when spans are dropped, - /// implementations should ensure that they are unwind-safe. Panicking from - /// inside of a `drop_span` function may cause a double panic, if the span - /// was dropped due to a thread unwinding. - /// - /// [span ID]: ../span/struct.Id.html - /// [`clone_span`]: trait.Subscriber.html#method.clone_span - fn drop_span(&self, id: span::Id) { - let _ = id; - } - - // === Downcasting methods ================================================ - - /// If `self` is the same type as the provided `TypeId`, returns an untyped - /// `*const` pointer to that type. Otherwise, returns `None`. - /// - /// If you wish to downcast a `Subscriber`, it is strongly advised to use - /// the safe API provided by [`downcast_ref`] instead. - /// - /// This API is required for `downcast_raw` to be a trait method; a method - /// signature like [`downcast_ref`] (with a generic type parameter) is not - /// object-safe, and thus cannot be a trait method for `Subscriber`. This - /// means that if we only exposed `downcast_ref`, `Subscriber` - /// implementations could not override the downcasting behavior - /// - /// This method may be overridden by "fan out" or "chained" subscriber - /// implementations which consist of multiple composed types. Such - /// subscribers might allow `downcast_raw` by returning references to those - /// component if they contain components with the given `TypeId`. - /// - /// # Safety - /// - /// The [`downcast_ref`] method expects that the pointer returned by - /// `downcast_raw` is non-null and points to a valid instance of the type - /// with the provided `TypeId`. Failure to ensure this will result in - /// undefined behaviour, so implementing `downcast_raw` is unsafe. - /// - /// [`downcast_ref`]: #method.downcast_ref - unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { - if id == TypeId::of::() { - Some(self as *const Self as *const ()) - } else { - None - } - } -} - -impl Subscriber { - /// Returns `true` if this `Subscriber` is the same type as `T`. - pub fn is(&self) -> bool { - self.downcast_ref::().is_some() - } - - /// Returns some reference to this `Subscriber` value if it is of type `T`, - /// or `None` if it isn't. - pub fn downcast_ref(&self) -> Option<&T> { - unsafe { - let raw = self.downcast_raw(TypeId::of::())?; - if raw == ptr::null() { - None - } else { - Some(&*(raw as *const _)) - } - } - } -} - -/// Indicates a [`Subscriber`]'s interest in a particular callsite. -/// -/// `Subscriber`s return an `Interest` from their [`register_callsite`] methods -/// in order to determine whether that span should be enabled or disabled. -/// -/// [`Subscriber`] trait.Subscriber.html -/// [clone_span]: trait.Subscriber.html#method.register_callsite -#[derive(Clone, Debug)] -pub struct Interest(InterestKind); - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] -enum InterestKind { - Never = 0, - Sometimes = 1, - Always = 2, -} - -impl Interest { - /// Returns an `Interest` indicating that the subscriber is never interested - /// in being notified about a callsite. - /// - /// If all active subscribers are `never()` interested in a callsite, it will - /// be completely disabled unless a new subscriber becomes active. - #[inline] - pub fn never() -> Self { - Interest(InterestKind::Never) - } - - /// Returns an `Interest` indicating the subscriber is sometimes interested - /// in being notified about a callsite. - /// - /// If all active subscribers are `sometimes` or `never` interested in a - /// callsite, the currently active subscriber will be asked to filter that - /// callsite every time it creates a span. This will be the case until a new - /// subscriber expresses that it is `always` interested in the callsite. - #[inline] - pub fn sometimes() -> Self { - Interest(InterestKind::Sometimes) - } - - /// Returns an `Interest` indicating the subscriber is always interested in - /// being notified about a callsite. - /// - /// If any subscriber expresses that it is `always()` interested in a given - /// callsite, then the callsite will always be enabled. - #[inline] - pub fn always() -> Self { - Interest(InterestKind::Always) - } - - /// Returns `true` if the subscriber is never interested in being notified - /// about this callsite. - #[inline] - pub fn is_never(&self) -> bool { - match self.0 { - InterestKind::Never => true, - _ => false, - } - } - - /// Returns `true` if the subscriber is sometimes interested in being notified - /// about this callsite. - #[inline] - pub fn is_sometimes(&self) -> bool { - match self.0 { - InterestKind::Sometimes => true, - _ => false, - } - } - - /// Returns `true` if the subscriber is always interested in being notified - /// about this callsite. - #[inline] - pub fn is_always(&self) -> bool { - match self.0 { - InterestKind::Always => true, - _ => false, - } - } - - /// Returns the common interest between these two Interests. - /// - /// The common interest is defined as the least restrictive, so if one - /// interest is `never` and the other is `always` the common interest is - /// `always`. - pub(crate) fn and(self, rhs: Interest) -> Self { - match rhs.0 { - // If the added interest is `never()`, don't change anything — - // either a different subscriber added a higher interest, which we - // want to preserve, or the interest is 0 anyway (as it's - // initialized to 0). - InterestKind::Never => self, - // If the interest is `sometimes()`, that overwrites a `never()` - // interest, but doesn't downgrade an `always()` interest. - InterestKind::Sometimes if self.0 == InterestKind::Never => rhs, - // If the interest is `always()`, we overwrite the current interest, - // as always() is the highest interest level and should take - // precedent. - InterestKind::Always => rhs, - _ => self, - } - } -} diff --git a/tokio-trace/tokio-trace-core/tests/macros.rs b/tokio-trace/tokio-trace-core/tests/macros.rs deleted file mode 100644 index 9fa43250e..000000000 --- a/tokio-trace/tokio-trace-core/tests/macros.rs +++ /dev/null @@ -1,49 +0,0 @@ -#[macro_use] -extern crate tokio_trace_core; -use tokio_trace_core::{ - callsite::Callsite, - metadata::{Kind, Level, Metadata}, - subscriber::Interest, -}; - -#[test] -fn metadata_macro_api() { - // This test should catch any inadvertant breaking changes - // caused bu changes to the macro. - struct TestCallsite; - - impl Callsite for TestCallsite { - fn set_interest(&self, _: Interest) { - unimplemented!("test") - } - fn metadata(&self) -> &Metadata { - unimplemented!("test") - } - } - - static CALLSITE: TestCallsite = TestCallsite; - let _metadata = metadata! { - name: "test_metadata", - target: "test_target", - level: Level::DEBUG, - fields: &["foo", "bar", "baz"], - callsite: &CALLSITE, - kind: Kind::SPAN, - }; - let _metadata = metadata! { - name: "test_metadata", - target: "test_target", - level: Level::TRACE, - fields: &[], - callsite: &CALLSITE, - kind: Kind::EVENT, - }; - let _metadata = metadata! { - name: "test_metadata", - target: "test_target", - level: Level::INFO, - fields: &[], - callsite: &CALLSITE, - kind: Kind::EVENT - }; -} diff --git a/tokio/Cargo.toml b/tokio/Cargo.toml index 13610ee9d..161d3b639 100644 --- a/tokio/Cargo.toml +++ b/tokio/Cargo.toml @@ -50,7 +50,7 @@ rt-full = [ "tokio-executor", "tokio-macros", # "tokio-threadpool", -# "tokio-trace-core", + "tracing-core", ] sync = ["tokio-sync"] tcp = ["tokio-tcp"] @@ -77,7 +77,7 @@ tokio-sync = { version = "0.2.0", optional = true, path = "../tokio-sync" } tokio-tcp = { version = "0.2.0", optional = true, path = "../tokio-tcp" } tokio-udp = { version = "0.2.0", optional = true, path = "../tokio-udp" } #tokio-timer = { version = "0.3.0", optional = true, path = "../tokio-timer" } -#tokio-trace-core = { version = "0.2", optional = true } +tracing-core = { version = "0.1", optional = true } # Needed for async/await preview support #tokio-futures = { version = "0.2.0", optional = true, path = "../tokio-futures" } diff --git a/tokio/src/runtime/threadpool/builder.rs b/tokio/src/runtime/threadpool/builder.rs index f85d0fa1e..f8c1c4856 100644 --- a/tokio/src/runtime/threadpool/builder.rs +++ b/tokio/src/runtime/threadpool/builder.rs @@ -4,7 +4,7 @@ use tokio_reactor; use tokio_threadpool::Builder as ThreadPoolBuilder; use tokio_timer::clock::{self, Clock}; use tokio_timer::timer::{self, Timer}; -use tokio_trace_core as trace; +use tracing_core as trace; use std::io; use std::sync::Mutex; use std::time::Duration;