trace: Switch to using local_inner_macros for instrumentation API (#969)

## Motivation

Currently, it isn't possible to import individual macros from
`tokio-trace` using the macros 1.2 syntax:

```rust
use tokio_trace::{debug, info, span};
```

This is because these macros require that `callsite` and `enabled` are
imported as well.

## Solution

This branch resolves the problem by adding the [`local_inner_macros`]
attribute to the instrumentation API's macros. This allows other macros
from within the crate to be used without requiring them to be explicitly
imported. 

However, this also requires duplicating any macros from other sources
(such as std and `tokio-trace-core`) with wrappers due to the behaviour
of `local_inner_macros`. I've added these wrapper macros as well.

Since the macros got even longer as a result of this, I've moved them
to a separate file to make `lib.rs` easier to read. I've also wrapped
some very long lines in the macros, and removed the explicit drop of
the result of evaluating some event macros (it's no longer necessary
as all event macros now evaluate to `()`).

[`local_inner_macros`]: https://doc.rust-lang.org/nightly/edition-guide/rust-2018/macros/macro-changes.html#local-helper-macros

Fixes #968

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This commit is contained in:
Eliza Weisman 2019-03-11 14:48:23 -07:00 committed by GitHub
parent e780fccce4
commit 4313d65b38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 1035 additions and 799 deletions

View File

@ -335,802 +335,9 @@ pub use self::{
},
};
/// Constructs a new static callsite for a span or event.
#[doc(hidden)]
#[macro_export]
macro_rules! callsite {
(name: $name:expr, fields: $( $field_name:expr ),* $(,)*) => ({
callsite! {
name: $name,
target: module_path!(),
level: $crate::Level::TRACE,
fields: $( $field_name ),*
}
});
(name: $name:expr, level: $lvl:expr, fields: $( $field_name:expr ),* $(,)*) => ({
callsite! {
name: $name,
target: module_path!(),
level: $lvl,
fields: $( $field_name ),*
}
});
(
name: $name:expr,
target: $target:expr,
level: $lvl:expr,
fields: $( $field_name:expr ),*
$(,)*
) => ({
use std::sync::{Once, atomic::{self, AtomicUsize, Ordering}};
use $crate::{callsite, Metadata, subscriber::Interest};
struct MyCallsite;
static META: Metadata<'static> = {
metadata! {
name: $name,
target: $target,
level: $lvl,
fields: &[ $( stringify!($field_name) ),* ],
callsite: &MyCallsite,
}
};
// 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 add_interest(&self, interest: Interest) {
let current_interest = self.interest();
let interest = match () {
// 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).
_ if interest.is_never() => return,
// If the interest is `sometimes()`, that overwrites a `never()`
// interest, but doesn't downgrade an `always()` interest.
_ if interest.is_sometimes() && current_interest.is_never() => 1,
// If the interest is `always()`, we overwrite the current
// interest, as always() is the highest interest level and
// should take precedent.
_ if interest.is_always() => 2,
_ => return,
};
INTEREST.store(interest, Ordering::Relaxed);
}
fn clear_interest(&self) {
INTEREST.store(0, Ordering::Relaxed);
}
fn metadata(&self) -> &Metadata {
&META
}
}
REGISTRATION.call_once(|| {
callsite::register(&MyCallsite);
});
&MyCallsite
})
}
#[macro_use]
mod macros;
/// Constructs a new span.
///
/// # Examples
///
/// Creating a new span with no fields:
/// ```
/// # #[macro_use]
/// # extern crate tokio_trace;
/// # fn main() {
/// let mut span = span!("my span");
/// span.enter(|| {
/// // do work inside the span...
/// });
/// # }
/// ```
///
/// Creating a span with fields:
/// ```
/// # #[macro_use]
/// # extern crate tokio_trace;
/// # fn main() {
/// span!("my span", foo = 2, bar = "a string").enter(|| {
/// // do work inside the span...
/// });
/// # }
/// ```
///
/// Note that a trailing comma on the final field is valid:
/// ```
/// # #[macro_use]
/// # extern crate tokio_trace;
/// # fn main() {
/// span!(
/// "my span",
/// foo = 2,
/// bar = "a string",
/// );
/// # }
/// ```
///
/// Creating a span with custom target and log level:
/// ```
/// # #[macro_use]
/// # extern crate tokio_trace;
/// # fn main() {
/// span!(
/// target: "app_span",
/// level: tokio_trace::Level::TRACE,
/// "my span",
/// foo = 3,
/// bar = "another string"
/// );
/// # }
/// ```
///
/// Field values may be recorded after the span is created:
/// ```
/// # #[macro_use]
/// # extern crate tokio_trace;
/// # fn main() {
/// let mut my_span = span!("my span", foo = 2, bar);
/// my_span.record("bar", &7);
/// # }
/// ```
///
/// Note that a span may have up to 32 fields. The following will not compile:
/// ```rust,compile_fail
/// # #[macro_use]
/// # extern crate tokio_trace;
/// # fn main() {
/// span!(
/// "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
/// );
/// # }
/// ```
#[macro_export]
macro_rules! span {
(
target: $target:expr,
level: $lvl:expr,
parent: $parent:expr,
$name:expr,
$($k:ident $( = $val:expr )* ),*,
) => {
span!(
target: $target,
level: $lvl,
parent: $parent,
$name,
$($k $( = $val)*),*
)
};
(
target: $target:expr,
level: $lvl:expr,
parent: $parent:expr,
$name:expr,
$($k:ident $( = $val:expr )* ),*
) => {
{
use $crate::callsite;
use $crate::callsite::Callsite;
let callsite = callsite! {
name: $name,
target: $target,
level: $lvl,
fields: $($k),*
};
if is_enabled!(callsite) {
let meta = callsite.metadata();
$crate::Span::child_of(
$parent,
meta,
&valueset!(meta.fields(), $($k $( = $val)*),*),
)
} else {
$crate::Span::new_disabled()
}
}
};
(
target: $target:expr,
level: $lvl:expr,
$name:expr,
$($k:ident $( = $val:expr )* ),*
) => {
{
use $crate::callsite;
use $crate::callsite::Callsite;
let callsite = callsite! {
name: $name,
target: $target,
level: $lvl,
fields: $($k),*
};
if is_enabled!(callsite) {
let meta = callsite.metadata();
$crate::Span::new(
meta,
&valueset!(meta.fields(), $($k $( = $val)*),*),
)
} else {
$crate::Span::new_disabled()
}
}
};
(target: $target:expr, level: $lvl:expr, parent: $parent:expr, $name:expr) => {
span!(target: $target, level: $lvl, parent: $parent, $name,)
};
(level: $lvl:expr, parent: $parent:expr, $name:expr, $($k:ident $( = $val:expr )* ),*,) => {
span!(
target: module_path!(),
level: $lvl,
parent: $parent,
$name,
$($k $( = $val)*),*
)
};
(level: $lvl:expr, parent: $parent:expr, $name:expr, $($k:ident $( = $val:expr )* ),*) => {
span!(
target: module_path!(),
level: $lvl,
parent: $parent,
$name,
$($k $( = $val)*),*
)
};
(level: $lvl:expr, parent: $parent:expr, $name:expr) => {
span!(target: module_path!(), level: $lvl, parent: $parent, $name,)
};
(parent: $parent:expr, $name:expr, $($k:ident $( = $val:expr)*),*,) => {
span!(
target: module_path!(),
level: $crate::Level::TRACE,
parent: $parent,
$name,
$($k $( = $val)*),*
)
};
(parent: $parent:expr, $name:expr, $($k:ident $( = $val:expr)*),*) => {
span!(
target: module_path!(),
level: $crate::Level::TRACE,
parent: $parent,
$name,
$($k $( = $val)*),*
)
};
(parent: $parent:expr, $name:expr) => {
span!(
target: module_path!(),
level: $crate::Level::TRACE,
parent: $parent,
$name,
)
};
(
target: $target:expr,
level: $lvl:expr,
$name:expr,
$($k:ident $( = $val:expr )* ),*,
) => {
span!(
target: $target,
level: $lvl,
$name,
$($k $( = $val)*),*
)
};
(
target: $target:expr,
level: $lvl:expr,
$name:expr,
$($k:ident $( = $val:expr )* ),*
) => {
span!(
target: $target,
level: $lvl,
$name,
$($k $( = $val)*),*
)
};
(target: $target:expr, level: $lvl:expr, $name:expr) => {
span!(target: $target, level: $lvl, $name,)
};
(target: $target:expr, level: $lvl:expr, $name:expr,) => {
span!(
target: $target,
level: $lvl,
$name,
)
};
(level: $lvl:expr, $name:expr, $($k:ident $( = $val:expr )* ),*,) => {
span!(
target: module_path!(),
level: $lvl,
$name,
$($k $( = $val)*),*
)
};
(level: $lvl:expr, $name:expr, $($k:ident $( = $val:expr )* ),*) => {
span!(target: module_path!(), level: $lvl, $name, $($k $( = $val)*),*)
};
(level: $lvl:expr, $name:expr) => {
span!(target: module_path!(), level: $lvl, $name,)
};
($name:expr, $($k:ident $( = $val:expr)*),*,) => {
span!(target: module_path!(), level: $crate::Level::TRACE, $name, $($k $( = $val)*),*)
};
($name:expr, $($k:ident $( = $val:expr)*),*) => {
span!(
target: module_path!(),
level: $crate::Level::TRACE,
$name,
$($k $( = $val)*),*
)
};
($name:expr) => { span!(target: module_path!(), level: $crate::Level::TRACE, $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, field};
///
/// # fn main() {
/// event!(Level::Info, foo = 5, bad_field, bar = field::display("hello"))
/// #}
/// ```
///
/// Events may have up to 32 fields. The following will not compile:
/// ```rust,compile_fail
/// # #[macro_use]
/// # extern crate tokio_trace;
/// # fn main() {
/// event!(tokio_trace::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]
macro_rules! event {
(target: $target:expr, $lvl:expr, { $( $k:ident = $val:expr ),* $(,)*} )=> ({
{
#[allow(unused_imports)]
use $crate::{callsite, dispatcher, Event, field::{Value, ValueSet}};
use $crate::callsite::Callsite;
let callsite = callsite! {
name: concat!("event ", file!(), ":", line!()),
target: $target,
level: $lvl,
fields: $( $k ),*
};
if is_enabled!(callsite) {
let meta = callsite.metadata();
Event::dispatch(meta, &valueset!(meta.fields(), $( $k = $val),* ));
}
}
});
(target: $target:expr, $lvl:expr, { $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => ({
event!(target: $target, $lvl, { message = format_args!($($arg)+), $( $k = $val ),* })
});
(target: $target:expr, $lvl:expr, { $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => ({
event!(target: $target, $lvl, { message = format_args!($($arg)+), $( $k = $val ),* })
});
(target: $target:expr, $lvl:expr, $( $k:ident = $val:expr ),+, ) => (
event!(target: $target, $lvl, { $($k = $val),+ })
);
(target: $target:expr, $lvl:expr, $( $k:ident = $val:expr ),+ ) => (
event!(target: $target, $lvl, { $($k = $val),+ })
);
(target: $target:expr, $lvl:expr, $($arg:tt)+ ) => (
event!(target: $target, $lvl, { }, $($arg)+)
);
( $lvl:expr, { $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => (
event!(target: module_path!(), $lvl, { message = format_args!($($arg)+), $($k = $val),* })
);
( $lvl:expr, { $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => (
event!(target: module_path!(), $lvl, { message = format_args!($($arg)+), $($k = $val),* })
);
( $lvl:expr, $( $k:ident = $val:expr ),*, ) => (
event!(target: module_path!(), $lvl, { $($k = $val),* })
);
( $lvl:expr, $( $k:ident = $val:expr ),* ) => (
event!(target: module_path!(), $lvl, { $($k = $val),* })
);
( $lvl:expr, $($arg:tt)+ ) => (
event!(target: 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]
macro_rules! trace {
(target: $target:expr, { $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => (
event!(target: $target, $crate::Level::TRACE, { $($k = $val),* }, $($arg)+)
);
(target: $target:expr, { $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => (
event!(target: $target, $crate::Level::TRACE, { $($k = $val),* }, $($arg)+)
);
(target: $target:expr, $( $k:ident = $val:expr ),*, ) => (
event!(target: $target, $crate::Level::TRACE, { $($k = $val),* })
);
(target: $target:expr, $( $k:ident = $val:expr ),* ) => (
event!(target: $target, $crate::Level::TRACE, { $($k = $val),* })
);
(target: $target:expr, $($arg:tt)+ ) => (
// When invoking this macro with `log`-style syntax (no fields), we
// drop the event immediately — the `log` crate's macros don't
// expand to an item, and if this did, it would break drop-in
// compatibility with `log`'s macros. Since it defines no fields,
// the handle won't be used later to add values to them.
drop(event!(target: $target, $crate::Level::TRACE, {}, $($arg)+));
);
({ $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => (
event!(target: module_path!(), $crate::Level::TRACE, { $($k = $val),* }, $($arg)+)
);
({ $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => (
event!(target: module_path!(), $crate::Level::TRACE, { $($k = $val),* }, $($arg)+)
);
($( $k:ident = $val:expr ),*, ) => (
event!(target: module_path!(), $crate::Level::TRACE, { $($k = $val),* })
);
($( $k:ident = $val:expr ),* ) => (
event!(target: module_path!(), $crate::Level::TRACE, { $($k = $val),* })
);
($($arg:tt)+ ) => (
drop(event!(target: 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!(x = field::debug(pos.x), y = field::debug(pos.y));
/// debug!(target: "app_events", { position = field::debug(pos) }, "New position");
/// # }
/// ```
#[macro_export]
macro_rules! debug {
(target: $target:expr, { $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => (
event!(target: $target, $crate::Level::DEBUG, { $($k = $val),* }, $($arg)+)
);
(target: $target:expr, { $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => (
event!(target: $target, $crate::Level::DEBUG, { $($k = $val),* }, $($arg)+)
);
(target: $target:expr, $( $k:ident = $val:expr ),*, ) => (
event!(target: $target, $crate::Level::DEBUG, { $($k = $val),* })
);
(target: $target:expr, $( $k:ident = $val:expr ),* ) => (
event!(target: $target, $crate::Level::DEBUG, { $($k = $val),* })
);
(target: $target:expr, $($arg:tt)+ ) => (
drop(event!(target: $target, $crate::Level::DEBUG, {}, $($arg)+));
);
({ $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => (
event!(target: module_path!(), $crate::Level::DEBUG, { $($k = $val),* }, $($arg)+)
);
({ $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => (
event!(target: module_path!(), $crate::Level::DEBUG, { $($k = $val),* }, $($arg)+)
);
($( $k:ident = $val:expr ),*, ) => (
event!(target: module_path!(), $crate::Level::DEBUG, { $($k = $val),* })
);
($( $k:ident = $val:expr ),* ) => (
event!(target: module_path!(), $crate::Level::DEBUG, { $($k = $val),* })
);
($($arg:tt)+ ) => (
drop(event!(target: 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_info = Connection { port: 40, speed: 3.20 };
///
/// info!({ port = conn_info.port }, "connected to {}", addr);
/// info!(
/// target: "connection_events",
/// ip = field::display(addr),
/// port = conn_info.port,
/// speed = field::debug(conn_info.speed)
/// );
/// # }
/// ```
#[macro_export]
macro_rules! info {
(target: $target:expr, { $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => (
event!(target: $target, $crate::Level::INFO, { $($k = $val),* }, $($arg)+)
);
(target: $target:expr, { $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => (
event!(target: $target, $crate::Level::INFO, { $($k = $val),* }, $($arg)+)
);
(target: $target:expr, $( $k:ident = $val:expr ),*, ) => (
event!(target: $target, $crate::Level::INFO, { $($k = $val),* })
);
(target: $target:expr, $( $k:ident = $val:expr ),* ) => (
event!(target: $target, $crate::Level::INFO, { $($k = $val),* })
);
(target: $target:expr, $($arg:tt)+ ) => (
drop(event!(target: $target, $crate::Level::INFO, {}, $($arg)+));
);
({ $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => (
event!(target: module_path!(), $crate::Level::INFO, { $($k = $val),* }, $($arg)+)
);
({ $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => (
event!(target: module_path!(), $crate::Level::INFO, { $($k = $val),* }, $($arg)+)
);
($( $k:ident = $val:expr ),*, ) => (
event!(target: module_path!(), $crate::Level::INFO, { $($k = $val),* })
);
($( $k:ident = $val:expr ),* ) => (
event!(target: module_path!(), $crate::Level::INFO, { $($k = $val),* })
);
($($arg:tt)+ ) => (
drop(event!(target: 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]
macro_rules! warn {
(target: $target:expr, { $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => (
event!(target: $target, $crate::Level::WARN, { $($k = $val),* }, $($arg)+)
);
(target: $target:expr, { $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => (
event!(target: $target, $crate::Level::WARN, { $($k = $val),* }, $($arg)+)
);
(target: $target:expr, $( $k:ident = $val:expr ),*, ) => (
event!(target: $target, $crate::Level::WARN, { $($k = $val),* })
);
(target: $target:expr, $( $k:ident = $val:expr ),* ) => (
event!(target: $target, $crate::Level::WARN, { $($k = $val),* })
);
(target: $target:expr, $($arg:tt)+ ) => (
drop(event!(target: $target, $crate::Level::WARN, {}, $($arg)+));
);
({ $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => (
event!(target: module_path!(), $crate::Level::WARN, { $($k = $val),* }, $($arg)+)
);
({ $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => (
event!(target: module_path!(), $crate::Level::WARN, { $($k = $val),* }, $($arg)+)
);
($( $k:ident = $val:expr ),*, ) => (
event!(target: module_path!(), $crate::Level::WARN,{ $($k = $val),* })
);
($( $k:ident = $val:expr ),* ) => (
event!(target: module_path!(), $crate::Level::WARN,{ $($k = $val),* })
);
($($arg:tt)+ ) => (
drop(event!(target: 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]
macro_rules! error {
(target: $target:expr, { $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => (
event!(target: $target, $crate::Level::ERROR, { $($k = $val),* }, $($arg)+)
);
(target: $target:expr, { $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => (
event!(target: $target, $crate::Level::ERROR, { $($k = $val),* }, $($arg)+)
);
(target: $target:expr, $( $k:ident = $val:expr ),*, ) => (
event!(target: $target, $crate::Level::ERROR, { $($k = $val),* })
);
(target: $target:expr, $( $k:ident = $val:expr ),* ) => (
event!(target: $target, $crate::Level::ERROR, { $($k = $val),* })
);
(target: $target:expr, $($arg:tt)+ ) => (
drop(event!(target: $target, $crate::Level::ERROR, {}, $($arg)+));
);
({ $( $k:ident = $val:expr ),*, }, $($arg:tt)+ ) => (
event!(target: module_path!(), $crate::Level::ERROR, { $($k = $val),* }, $($arg)+)
);
({ $( $k:ident = $val:expr ),* }, $($arg:tt)+ ) => (
event!(target: module_path!(), $crate::Level::ERROR, { $($k = $val),* }, $($arg)+)
);
($( $k:ident = $val:expr ),*, ) => (
event!(target: module_path!(), $crate::Level::ERROR, { $($k = $val),* })
);
($( $k:ident = $val:expr ),* ) => (
event!(target: module_path!(), $crate::Level::ERROR, { $($k = $val),* })
);
($($arg:tt)+ ) => (
drop(event!(target: module_path!(), $crate::Level::ERROR, {}, $($arg)+));
);
}
#[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]
macro_rules! valueset {
($fields:expr, $($k:ident $( = $val:expr )* ) ,*) => {
{
let mut iter = $fields.iter();
$fields.value_set(&[
$((
&iter.next().expect("FieldSet corrupted (this is a bug)"),
valueset!(@val $k $(= $val)*)
)),*
])
}
};
(@val $k:ident = $val:expr) => {
Some(&$val as &$crate::field::Value)
};
(@val $k:ident) => { None };
}
pub mod field;
pub mod span;
pub mod subscriber;

1005
tokio-trace/src/macros.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -123,7 +123,7 @@ macro_rules! identify_callsite {
///
/// [metadata]: metadata/struct.Metadata.html
/// [`Metadata::new`]: metadata/struct.Metadata.html#method.new
#[macro_export]
#[macro_export(local_inner_macros)]
macro_rules! metadata {
(
name: $name:expr,
@ -151,9 +151,9 @@ macro_rules! metadata {
name: $name,
target: $target,
level: $level,
file: Some(file!()),
line: Some(line!()),
module_path: Some(module_path!()),
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),
@ -162,6 +162,30 @@ macro_rules! metadata {
};
}
#[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;