use schemars::JsonSchema; use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize, JsonSchema, Debug)] struct StackTraceSymbol { name: Option, file: Option, line: Option, } #[derive(Deserialize, Serialize, JsonSchema, Debug)] struct StackTraceFrame { symbols: Vec, } impl StackTraceFrame { pub fn render(&self) -> String { let mut result = String::new(); for symbol in &self.symbols { let symbol_string = format!( "{}:{} - {} ", symbol.file.as_deref().unwrap_or_default(), symbol.line.unwrap_or_default(), symbol.name.as_deref().unwrap_or_default(), ); result.push_str(&symbol_string); } result } } #[derive(Deserialize, Serialize, JsonSchema, Debug)] pub struct ThreadStackTrace { id: u32, name: String, frames: Vec, } #[derive(Deserialize, Serialize, JsonSchema, Debug)] pub struct StackTrace { threads: Vec, } pub fn get_stack_trace() -> StackTrace { #[cfg(not(all(target_os = "linux", feature = "stacktrace")))] { StackTrace { threads: vec![] } } #[cfg(all(target_os = "linux", feature = "stacktrace"))] { let exe = std::env::current_exe().unwrap(); let trace = rstack_self::trace(std::process::Command::new(exe).arg("--stacktrace")).unwrap(); StackTrace { threads: trace .threads() .iter() .map(|thread| ThreadStackTrace { id: thread.id(), name: thread.name().to_string(), frames: thread .frames() .iter() .map(|frame| { let frame = StackTraceFrame { symbols: frame .symbols() .iter() .map(|symbol| StackTraceSymbol { name: symbol.name().map(|name| name.to_string()), file: symbol.file().map(|file| { file.to_str().unwrap_or_default().to_string() }), line: symbol.line(), }) .collect(), }; frame.render() }) .collect(), }) .collect(), } } }