use crate::ErrorKind;
#[doc(hidden)]
pub use static_assertions;
#[doc(hidden)]
pub use tracing::{Level, event};
use paste::paste;
impl ErrorKind {
pub fn is_always_a_warning(&self) -> bool {
matches!(self, ErrorKind::Internal | ErrorKind::BadApiUsage)
}
}
#[macro_export]
macro_rules! event_report {
($level:expr, $err:expr) => {
$crate::event_report!($level, $err,)
};
($level:expr, $err:expr, $($arg:tt)*) => {
{
use $crate::{tracing as tr, HasKind as _, };
let err = $err;
if err.kind().is_always_a_warning() && tr::Level::WARN < $level {
$crate::event_report!(@raw tr::Level::WARN, err, $($arg)*);
} else {
$crate::event_report!(@raw $level, err, $($arg)*);
}
}
};
(@raw $level:expr, $err:expr) => {
$crate::event_report!(@raw $level, $err,)
};
(@raw $level:expr, $err:expr, $($arg:tt)*) => {
{
use $crate::tracing as tr;
use ::std::ops::Deref as _;
tr::event!(
$level,
error = ((&($err)).deref() as &dyn std::error::Error),
$($arg)*
)
}
}
}
macro_rules! define_report_macros { {
# $title_1:tt
LEVEL
# $title_2:tt
$D:tt
$( [$($flag:tt)*] $level:ident )*
} => { $( paste!{
# $title_1
#[doc = concat!("`", stringify!( [< $level:upper >] ), "`")]
# $title_2
#[doc = concat!("use tor_error::", stringify!($level), "_report;")]
#[doc = concat!(stringify!($level), "_report!",
r#"(err, "Cheese exhausted (ephemeral)");"#)]
#[doc = concat!(stringify!($level), "_report!",
r#"(err, "Unable to parse message {:?}", msg);"#)]
#[macro_export]
macro_rules! [< $level _report >] {
( $D err:expr ) => {
$D crate::event_report!($($flag)*
$D crate::tracing::Level::[< $level:upper >],
$D err)
};
( $D err:expr, $D ($D rest:tt)* ) => {
$D crate::event_report!($($flag)*
$D crate::tracing::Level::[< $level:upper >],
$D err, $D ($D rest)*)
}
}
} )* } }
define_report_macros! {
LEVEL
$ [] trace
[] debug
[] info
}
define_report_macros! {
LEVEL
$ [@raw] warn
[@raw] error
}
#[cfg(test)]
mod test {
#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::clone_on_copy)]
#![allow(clippy::dbg_macro)]
#![allow(clippy::mixed_attributes_style)]
#![allow(clippy::print_stderr)]
#![allow(clippy::print_stdout)]
#![allow(clippy::single_char_pattern)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::unchecked_time_subtraction)]
#![allow(clippy::useless_vec)]
#![allow(clippy::needless_pass_by_value)]
use crate::internal;
use crate::report::ErrorReport;
use thiserror::Error;
use tracing_test::traced_test;
#[derive(Error, Debug)]
#[error("my error")]
struct MyError;
#[test]
#[traced_test]
#[allow(clippy::cognitive_complexity)]
fn warn_report() {
let me = MyError;
let _ = me.report();
warn_report!(me, "reporting unwrapped");
let ae = anyhow::Error::from(me).context("context");
let _ = ae.report();
warn_report!(ae, "reporting anyhow");
let ie = internal!("Foo was not initialized");
let _ = ie.report();
warn_report!(ie);
}
}