support field values in err! macro
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
5b1642f641
commit
5add9a8c34
4 changed files with 127 additions and 31 deletions
|
@ -14,7 +14,7 @@ pub use crate::utils::debug::*;
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! debug_event {
|
macro_rules! debug_event {
|
||||||
( $level:expr, $($x:tt)+ ) => {
|
( $level:expr, $($x:tt)+ ) => {
|
||||||
if cfg!(debug_assertions) && cfg!(not(feature = "dev_release_log_level")) {
|
if $crate::debug::logging() {
|
||||||
::tracing::event!( $level, $($x)+ )
|
::tracing::event!( $level, $($x)+ )
|
||||||
} else {
|
} else {
|
||||||
::tracing::debug!( $($x)+ )
|
::tracing::debug!( $($x)+ )
|
||||||
|
@ -88,3 +88,7 @@ pub fn panic_str(p: &Box<dyn Any + Send>) -> &'static str { p.downcast_ref::<&st
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn type_name<T>(_: &T) -> &'static str { std::any::type_name::<T>() }
|
pub fn type_name<T>(_: &T) -> &'static str { std::any::type_name::<T>() }
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
pub const fn logging() -> bool { cfg!(debug_assertions) && cfg!(not(feature = "dev_release_log_level")) }
|
||||||
|
|
|
@ -41,60 +41,149 @@ macro_rules! Err {
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! err {
|
macro_rules! err {
|
||||||
(Config($item:literal, $($args:expr),*)) => {{
|
(Request(Forbidden($level:ident!($($args:tt)+)))) => {{
|
||||||
$crate::error!(config = %$item, $($args),*);
|
let mut buf = String::new();
|
||||||
$crate::error::Error::Config($item, $crate::format_maybe!($($args),*))
|
|
||||||
}};
|
|
||||||
|
|
||||||
(Request(Forbidden($level:ident!($($args:expr),*)))) => {{
|
|
||||||
$crate::$level!($($args),*);
|
|
||||||
$crate::error::Error::Request(
|
$crate::error::Error::Request(
|
||||||
::ruma::api::client::error::ErrorKind::forbidden(),
|
::ruma::api::client::error::ErrorKind::forbidden(),
|
||||||
$crate::format_maybe!($($args),*),
|
$crate::err_log!(buf, $level, $($args)+),
|
||||||
::http::StatusCode::BAD_REQUEST
|
::http::StatusCode::BAD_REQUEST
|
||||||
)
|
)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
(Request(Forbidden($($args:expr),*))) => {
|
(Request(Forbidden($($args:tt)+))) => {
|
||||||
$crate::error::Error::Request(
|
$crate::error::Error::Request(
|
||||||
::ruma::api::client::error::ErrorKind::forbidden(),
|
::ruma::api::client::error::ErrorKind::forbidden(),
|
||||||
$crate::format_maybe!($($args),*),
|
$crate::format_maybe!($($args)+),
|
||||||
::http::StatusCode::BAD_REQUEST
|
::http::StatusCode::BAD_REQUEST
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
(Request($variant:ident($level:ident!($($args:expr),*)))) => {{
|
(Request($variant:ident($level:ident!($($args:tt)+)))) => {{
|
||||||
$crate::$level!($($args),*);
|
let mut buf = String::new();
|
||||||
$crate::error::Error::Request(
|
$crate::error::Error::Request(
|
||||||
::ruma::api::client::error::ErrorKind::$variant,
|
::ruma::api::client::error::ErrorKind::$variant,
|
||||||
$crate::format_maybe!($($args),*),
|
$crate::err_log!(buf, $level, $($args)+),
|
||||||
::http::StatusCode::BAD_REQUEST
|
::http::StatusCode::BAD_REQUEST
|
||||||
)
|
)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
(Request($variant:ident($($args:expr),*))) => {
|
(Request($variant:ident($($args:tt)+))) => {
|
||||||
$crate::error::Error::Request(
|
$crate::error::Error::Request(
|
||||||
::ruma::api::client::error::ErrorKind::$variant,
|
::ruma::api::client::error::ErrorKind::$variant,
|
||||||
$crate::format_maybe!($($args),*),
|
$crate::format_maybe!($($args)+),
|
||||||
::http::StatusCode::BAD_REQUEST
|
::http::StatusCode::BAD_REQUEST
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
($variant:ident($level:ident!($($args:expr),*))) => {{
|
(Config($item:literal, $($args:tt)+)) => {{
|
||||||
$crate::$level!($($args),*);
|
let mut buf = String::new();
|
||||||
$crate::error::Error::$variant($crate::format_maybe!($($args),*))
|
$crate::error::Error::Config($item, $crate::err_log!(buf, error, config = %$item, $($args)+))
|
||||||
}};
|
}};
|
||||||
|
|
||||||
($variant:ident($($args:expr),*)) => {
|
($variant:ident($level:ident!($($args:tt)+))) => {{
|
||||||
$crate::error::Error::$variant($crate::format_maybe!($($args),*))
|
let mut buf = String::new();
|
||||||
|
$crate::error::Error::$variant($crate::err_log!(buf, $level, $($args)+))
|
||||||
|
}};
|
||||||
|
|
||||||
|
($variant:ident($($args:tt)+)) => {
|
||||||
|
$crate::error::Error::$variant($crate::format_maybe!($($args)+))
|
||||||
};
|
};
|
||||||
|
|
||||||
($level:ident!($($args:expr),*)) => {{
|
($level:ident!($($args:tt)+)) => {{
|
||||||
$crate::$level!($($args),*);
|
let mut buf = String::new();
|
||||||
$crate::error::Error::Err($crate::format_maybe!($($args),*))
|
$crate::error::Error::Err($crate::err_log!(buf, $level, $($args)+))
|
||||||
}};
|
}};
|
||||||
|
|
||||||
($($args:expr),*) => {
|
($($args:tt)+) => {
|
||||||
$crate::error::Error::Err($crate::format_maybe!($($args),*))
|
$crate::error::Error::Err($crate::format_maybe!($($args)+))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trinity of integration between tracing, logging, and Error. This is a
|
||||||
|
/// customization of tracing::event! with the primary purpose of sharing the
|
||||||
|
/// error string, fieldset parsing and formatting. An added benefit is that we
|
||||||
|
/// can share the same callsite metadata for the source of our Error and the
|
||||||
|
/// associated logging and tracing event dispatches.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! err_log {
|
||||||
|
($out:ident, $level:ident, $($fields:tt)+) => {{
|
||||||
|
use std::{fmt, fmt::Write};
|
||||||
|
|
||||||
|
use ::tracing::{
|
||||||
|
callsite, callsite2, level_enabled, metadata, valueset, Callsite, Event, __macro_support,
|
||||||
|
__tracing_log,
|
||||||
|
field::{Field, ValueSet, Visit},
|
||||||
|
Level,
|
||||||
|
};
|
||||||
|
|
||||||
|
const LEVEL: Level = $crate::err_lev!($level);
|
||||||
|
static __CALLSITE: callsite::DefaultCallsite = callsite2! {
|
||||||
|
name: std::concat! {
|
||||||
|
"event ",
|
||||||
|
std::file!(),
|
||||||
|
":",
|
||||||
|
std::line!(),
|
||||||
|
},
|
||||||
|
kind: metadata::Kind::EVENT,
|
||||||
|
target: std::module_path!(),
|
||||||
|
level: LEVEL,
|
||||||
|
fields: $($fields)+,
|
||||||
|
};
|
||||||
|
|
||||||
|
let visit = &mut |vs: ValueSet<'_>| {
|
||||||
|
struct Visitor<'a>(&'a mut String);
|
||||||
|
impl Visit for Visitor<'_> {
|
||||||
|
fn record_debug(&mut self, field: &Field, val: &dyn fmt::Debug) {
|
||||||
|
if field.name() == "message" {
|
||||||
|
write!(self.0, "{:?}", val).expect("stream error");
|
||||||
|
} else {
|
||||||
|
write!(self.0, " {}={:?}", field.name(), val).expect("stream error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let meta = __CALLSITE.metadata();
|
||||||
|
let enabled = level_enabled!(LEVEL) && {
|
||||||
|
let interest = __CALLSITE.interest();
|
||||||
|
!interest.is_never() && __macro_support::__is_enabled(meta, interest)
|
||||||
|
};
|
||||||
|
|
||||||
|
if enabled {
|
||||||
|
Event::dispatch(meta, &vs);
|
||||||
|
}
|
||||||
|
|
||||||
|
__tracing_log!(LEVEL, __CALLSITE, &vs);
|
||||||
|
vs.record(&mut Visitor(&mut $out));
|
||||||
|
};
|
||||||
|
|
||||||
|
(visit)(valueset!(__CALLSITE.metadata().fields(), $($fields)+));
|
||||||
|
($out).into()
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! err_lev {
|
||||||
|
(debug_warn) => {
|
||||||
|
if $crate::debug::logging() {
|
||||||
|
::tracing::Level::WARN
|
||||||
|
} else {
|
||||||
|
::tracing::Level::DEBUG
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(debug_error) => {
|
||||||
|
if $crate::debug::logging() {
|
||||||
|
::tracing::Level::ERROR
|
||||||
|
} else {
|
||||||
|
::tracing::Level::DEBUG
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(warn) => {
|
||||||
|
::tracing::Level::WARN
|
||||||
|
};
|
||||||
|
|
||||||
|
(error) => {
|
||||||
|
::tracing::Level::ERROR
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@ mod response;
|
||||||
|
|
||||||
use std::{any::Any, borrow::Cow, convert::Infallible, fmt};
|
use std::{any::Any, borrow::Cow, convert::Infallible, fmt};
|
||||||
|
|
||||||
pub use log::*;
|
pub use self::log::*;
|
||||||
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
|
|
||||||
#[derive(thiserror::Error)]
|
#[derive(thiserror::Error)]
|
||||||
|
|
|
@ -8,12 +8,12 @@ pub const EMPTY: &str = "";
|
||||||
/// arguments are provided the first is assumed to be a format string.
|
/// arguments are provided the first is assumed to be a format string.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! format_maybe {
|
macro_rules! format_maybe {
|
||||||
($s:literal) => {
|
($s:literal $(,)?) => {
|
||||||
if $crate::is_format!($s) { std::format!($s).into() } else { $s.into() }
|
if $crate::is_format!($s) { std::format!($s).into() } else { $s.into() }
|
||||||
};
|
};
|
||||||
|
|
||||||
($($args:expr),*) => {
|
($s:literal, $($args:tt)+) => {
|
||||||
std::format!($($args),*).into()
|
std::format!($s, $($args)+).into()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,10 @@ macro_rules! is_format {
|
||||||
($s:literal) => {
|
($s:literal) => {
|
||||||
::const_str::contains!($s, "{") && ::const_str::contains!($s, "}")
|
::const_str::contains!($s, "{") && ::const_str::contains!($s, "}")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
($($s:tt)+) => {
|
||||||
|
false
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Add table
Reference in a new issue