fuchsia_triage/plugins/
crashes.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use 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}