mirror of
https://github.com/tokio-rs/tokio.git
synced 2025-10-01 12:20:39 +00:00
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:
parent
e780fccce4
commit
4313d65b38
@ -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
1005
tokio-trace/src/macros.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user