error_support/
lib.rs
1#[cfg(not(feature = "tracing-logging"))]
7pub use log::{debug, error, info, trace, warn, Level};
8
9#[cfg(feature = "tracing-logging")]
10pub use tracing_support::{debug, error, info, trace, warn, Level};
11
12#[cfg(all(feature = "testing", not(feature = "tracing-logging")))]
13pub fn init_for_tests() {
14 let _ = env_logger::try_init();
15}
16
17#[cfg(all(feature = "testing", not(feature = "tracing-logging")))]
18pub fn init_for_tests_with_level(level: Level) {
19 let level_name = match level {
21 Level::Debug => "debug",
22 Level::Trace => "trace",
23 Level::Info => "info",
24 Level::Warn => "warn",
25 Level::Error => "error",
26 };
27 env_logger::Builder::from_env(env_logger::Env::default().default_filter_or(level_name)).init();
28}
29
30#[cfg(all(feature = "testing", feature = "tracing-logging"))]
31pub use tracing_support::init_for_tests;
32
33mod macros;
34
35#[cfg(feature = "backtrace")]
36pub use backtrace;
39
40#[cfg(not(feature = "backtrace"))]
41pub mod backtrace {
43 use std::fmt;
44
45 pub struct Backtrace;
46
47 impl Backtrace {
48 pub fn new() -> Self {
49 Backtrace
50 }
51 }
52
53 impl Default for Backtrace {
54 fn default() -> Self {
55 Self::new()
56 }
57 }
58
59 impl fmt::Debug for Backtrace {
60 #[cold]
61 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62 write!(f, "Not available")
63 }
64 }
65}
66
67mod redact;
68pub use redact::*;
69
70#[cfg(not(feature = "tracing-reporting"))]
71mod reporting;
72#[cfg(not(feature = "tracing-reporting"))]
73pub use reporting::{
74 set_application_error_reporter, unset_application_error_reporter, ApplicationErrorReporter,
75};
76
77#[cfg(feature = "tracing-reporting")]
78mod reporting {
79 pub fn report_error_to_app(type_name: String, message: String) {
80 tracing::event!(target: "app-services-error-reporter::error", tracing::Level::ERROR, message, type_name);
81 }
82
83 pub fn report_breadcrumb(message: String, module: String, line: u32, column: u32) {
84 tracing::event!(target: "app-services-error-reporter::breadcrumb", tracing::Level::INFO, message, module, line, column);
85 }
86}
87
88pub use reporting::{report_breadcrumb, report_error_to_app};
89
90pub use error_support_macros::handle_error;
91
92mod handling;
93pub use handling::{convert_log_report_error, ErrorHandling, ErrorReporting, GetErrorHandling};
94
95#[macro_export]
101macro_rules! define_error_wrapper {
102 ($Kind:ty) => {
103 pub type Result<T, E = Error> = std::result::Result<T, E>;
104 struct ErrorData {
105 kind: $Kind,
106 backtrace: Option<std::sync::Mutex<$crate::backtrace::Backtrace>>,
107 }
108
109 impl ErrorData {
110 #[cold]
111 fn new(kind: $Kind) -> Self {
112 ErrorData {
113 kind,
114 #[cfg(feature = "backtrace")]
115 backtrace: Some(std::sync::Mutex::new(
116 $crate::backtrace::Backtrace::new_unresolved(),
117 )),
118 #[cfg(not(feature = "backtrace"))]
119 backtrace: None,
120 }
121 }
122
123 #[cfg(feature = "backtrace")]
124 #[cold]
125 fn get_backtrace(&self) -> Option<&std::sync::Mutex<$crate::backtrace::Backtrace>> {
126 self.backtrace.as_ref().map(|mutex| {
127 mutex.lock().unwrap().resolve();
128 mutex
129 })
130 }
131
132 #[cfg(not(feature = "backtrace"))]
133 #[cold]
134 fn get_backtrace(&self) -> Option<&std::sync::Mutex<$crate::backtrace::Backtrace>> {
135 None
136 }
137 }
138
139 impl std::fmt::Debug for ErrorData {
140 #[cfg(feature = "backtrace")]
141 #[cold]
142 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
143 let mut bt = self.backtrace.as_ref().unwrap().lock().unwrap();
144 bt.resolve();
145 write!(f, "{:?}\n\n{}", bt, self.kind)
146 }
147
148 #[cfg(not(feature = "backtrace"))]
149 #[cold]
150 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
151 write!(f, "{}", self.kind)
152 }
153 }
154
155 #[derive(Debug, thiserror::Error)]
156 pub struct Error(Box<ErrorData>);
157 impl Error {
158 #[cold]
159 pub fn kind(&self) -> &$Kind {
160 &self.0.kind
161 }
162
163 #[cold]
164 pub fn backtrace(&self) -> Option<&std::sync::Mutex<$crate::backtrace::Backtrace>> {
165 self.0.get_backtrace()
166 }
167 }
168
169 impl std::fmt::Display for Error {
170 #[cold]
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 std::fmt::Display::fmt(self.kind(), f)
173 }
174 }
175
176 impl From<$Kind> for Error {
177 #[cold]
179 fn from(ctx: $Kind) -> Error {
180 Error(Box::new(ErrorData::new(ctx)))
181 }
182 }
183 };
184}
185
186#[macro_export]
190macro_rules! define_error_conversions {
191 ($Kind:ident { $(($variant:ident, $type:ty)),* $(,)? }) => ($(
192 impl From<$type> for Error {
193 #[cold]
195 fn from(e: $type) -> Self {
196 Error::from($Kind::$variant(e))
197 }
198 }
199 )*);
200}
201
202#[macro_export]
205macro_rules! define_error {
206 ($Kind:ident { $(($variant:ident, $type:ty)),* $(,)? }) => {
207 $crate::define_error_wrapper!($Kind);
208 $crate::define_error_conversions! {
209 $Kind {
210 $(($variant, $type)),*
211 }
212 }
213 };
214}
215
216uniffi::setup_scaffolding!("errorsupport");