fuchsia_triage/plugins/
crashes.rs
1use super::Plugin;
6use crate::act::Action;
7use crate::metrics::fetch::FileDataFetcher;
8use regex::Regex;
9
10pub struct CrashesPlugin();
11
12impl Plugin for CrashesPlugin {
13 fn name(&self) -> &'static str {
14 "crashes"
15 }
16
17 fn display_name(&self) -> &'static str {
18 "Process Crashes"
19 }
20
21 fn run_structured(&self, inputs: &FileDataFetcher<'_>) -> Vec<Action> {
22 let mut results = Vec::new();
23
24 let re = Regex::new(r"\[(\d+)\.(\d+)\].*(?:CRASH:|fatal :)\s*([\w\-_\s\.]+)")
25 .expect("regex compilation");
26 for line in inputs.klog.lines.iter().chain(inputs.syslog.lines.iter()) {
27 if let Some(captures) = re.captures(line) {
28 let s = captures.get(1).unwrap().as_str().parse::<i32>().unwrap_or_default();
29 let ms = captures.get(2).unwrap().as_str().parse::<i32>().unwrap_or_default();
30
31 let formatted_time = format!("{}h{}m{}.{}s", s / 3600, s % 3600 / 60, s % 60, ms);
32
33 results.push(Action::new_synthetic_error(
34 format!(
35 "[ERROR]: {} crashed at {} [{}.{}]",
36 captures.get(3).unwrap().as_str(),
37 formatted_time,
38 s,
39 ms,
40 ),
41 "DeveloperExperience>Forensics>CrashReporting".to_string(),
42 ));
43 }
44 }
45 results
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52 use crate::metrics::fetch::TextFetcher;
53
54 #[fuchsia::test]
55 fn test_crashes() {
56 let expected_errors: Vec<String> = vec![
57 "[ERROR]: my_component crashed at 1h1m1.123s [3661.123]",
58 "[ERROR]: my_component crashed at 1h2m2.345s [3722.345]",
59 ]
60 .into_iter()
61 .map(|s| s.to_string())
62 .collect::<Vec<_>>();
63 let fetcher: TextFetcher = r#"
64[3661.123] fatal : my_component[333]
65[3722.345] CRASH: my_component[334]
66"#
67 .into();
68
69 let empty_diagnostics_vec = Vec::new();
70
71 let mut inputs = FileDataFetcher::new(&empty_diagnostics_vec);
72 inputs.klog = &fetcher;
73 assert_eq!(CrashesPlugin {}.run(&inputs).errors, expected_errors);
74
75 let mut inputs = FileDataFetcher::new(&empty_diagnostics_vec);
76 inputs.syslog = &fetcher;
77 assert_eq!(CrashesPlugin {}.run(&inputs).errors, expected_errors);
78 }
79}