Skip to main content

tuwunel_core/error/
log.rs

1use std::{convert::Infallible, error::Error as StdError, fmt, iter::successors};
2
3use tracing::Level;
4
5use super::Error;
6
7/// Flatten an error's `source()` chain into one `; caused by: ` string.
8///
9/// Storage and HTTP backends wrap transport errors several layers deep;
10/// the outer Display can show "error sending request" while the actual
11/// cause (e.g. rustls `UnknownIssuer`, hyper connect failure) is only
12/// reachable via `source()`. Logging the full chain at the failure site
13/// makes these self-diagnosing without per-crate trace logging.
14#[must_use]
15pub fn error_chain(e: &dyn StdError) -> String {
16	successors(Some(e), |&e| e.source())
17		.map(ToString::to_string)
18		.collect::<Vec<_>>()
19		.join("; caused by: ")
20}
21
22#[inline]
23pub fn else_log<T, E>(error: E) -> Result<T, Infallible>
24where
25	T: Default,
26	Error: From<E>,
27{
28	Ok(default_log(error))
29}
30
31#[inline]
32pub fn else_debug_log<T, E>(error: E) -> Result<T, Infallible>
33where
34	T: Default,
35	Error: From<E>,
36{
37	Ok(default_debug_log(error))
38}
39
40#[inline]
41pub fn default_log<T, E>(error: E) -> T
42where
43	T: Default,
44	Error: From<E>,
45{
46	let error = Error::from(error);
47	inspect_log(&error);
48	T::default()
49}
50
51#[inline]
52pub fn default_debug_log<T, E>(error: E) -> T
53where
54	T: Default,
55	Error: From<E>,
56{
57	let error = Error::from(error);
58	inspect_debug_log(&error);
59	T::default()
60}
61
62#[inline]
63pub fn map_log<E>(error: E) -> Error
64where
65	Error: From<E>,
66{
67	let error = Error::from(error);
68	inspect_log(&error);
69	error
70}
71
72#[inline]
73pub fn map_debug_log<E>(error: E) -> Error
74where
75	Error: From<E>,
76{
77	let error = Error::from(error);
78	inspect_debug_log(&error);
79	error
80}
81
82#[inline]
83pub fn inspect_log<E: fmt::Display>(error: &E) { inspect_log_level(error, Level::ERROR); }
84
85#[inline]
86pub fn inspect_debug_log<E: fmt::Debug>(error: &E) {
87	inspect_debug_log_level(error, Level::ERROR);
88}
89
90#[inline]
91pub fn inspect_log_level<E: fmt::Display>(error: &E, level: Level) {
92	use crate::{debug, error, info, trace, warn};
93
94	match level {
95		| Level::ERROR => error!("{error}"),
96		| Level::WARN => warn!("{error}"),
97		| Level::INFO => info!("{error}"),
98		| Level::DEBUG => debug!("{error}"),
99		| Level::TRACE => trace!("{error}"),
100	}
101}
102
103#[inline]
104pub fn inspect_debug_log_level<E: fmt::Debug>(error: &E, level: Level) {
105	use crate::{debug, debug_error, debug_info, debug_warn, trace};
106
107	match level {
108		| Level::ERROR => debug_error!("{error:?}"),
109		| Level::WARN => debug_warn!("{error:?}"),
110		| Level::INFO => debug_info!("{error:?}"),
111		| Level::DEBUG => debug!("{error:?}"),
112		| Level::TRACE => trace!("{error:?}"),
113	}
114}