ruva_core/
backtrace.rs

1#[cfg(feature = "backtrace")]
2#[inline]
3pub fn get_caller_data() -> Option<String> {
4	let stack_trace = backtrace::Backtrace::new();
5	let caller = stack_trace
6		.frames()
7		.iter()
8		.filter(|x| x.symbols().first().and_then(|x| x.name()).and_then(|x| x.as_str()).is_some())
9		.filter(|x| {
10			static BLACKLIST: [&str; 7] = ["backtrace::", "ruva_core::", "tokio::", "core::", "std::", "test::", "futures::"];
11			let name = x.symbols().first().and_then(|x| x.name()).and_then(|x| x.as_str()).unwrap();
12			if BLACKLIST.iter().any(|y| name.starts_with(y)) {
13				return false;
14			}
15			true
16		})
17		.map(|x| x.symbols().first().unwrap())
18		.next()
19		.cloned()?;
20
21	let module_path = caller.name().expect("caller에서 name을 기준으로 비교했기 때문에 현재는 값이 반드시 존재함");
22	let filename = caller.filename();
23	let line = caller.lineno();
24
25	let mut result = String::new();
26	result.push_str(module_path.as_str().unwrap());
27	if let Some(file_path) = filename {
28		if let Some(file_path) = file_path.to_str() {
29			result.push(' ');
30			result.push_str(file_path);
31		}
32	}
33
34	if let Some(line_no) = line {
35		result.push(':');
36		result.push_str(line_no.to_string().as_str());
37	}
38	Some(result)
39}
40
41#[macro_export]
42macro_rules! backtrace_error {
43    ($($arg:tt)*) => {
44        #[cfg(feature = "backtrace")]
45        {
46            let caller = $crate::backtrace::get_caller_data();
47            if caller.is_some() {
48                let caller = caller.unwrap();
49                tracing::error!(?caller, $($arg)*);
50            } else {
51                tracing::error!($($arg)*);
52            }
53        }
54        #[cfg(not(feature = "backtrace"))]
55        {
56            tracing::error!($($arg)*);
57        }
58    };
59}