Skip to main content

intel_crashlog/
analysis.rs

1// Copyright (C) 2026 Intel Corporation
2// SPDX-License-Identifier: MIT
3
4//! Analysis and interpretation of decoded Crash Log records.
5//!
6//! This module provides functionality to analyze crash log data structures,
7//! identify root causes of system failures, and extract diagnostic information.
8//! The analyzer examines various record types including reset sources, MCA
9//! (Machine Check Architecture) events, core exceptions, and PMC (Power Management
10//! Controller) data to generate comprehensive analysis reports.
11//!
12//! Current capabilities include triage analysis for prioritizing crash log findings,
13//! with additional analysis features planned for future releases.
14//!
15//! # Analysis Process
16//!
17//! 1. Queue one or more decoded crash log nodes using [`Analyzer::with_input`]
18//! 2. Call [`Analyzer::analyze`] to perform analysis across all queued nodes
19//! 3. Receive an [`AnalysisReport`] containing diagnostic findings
20
21mod agent;
22mod core;
23mod mca;
24mod reason;
25mod report;
26mod reset;
27mod tag;
28mod xq;
29
30use crate::node::{Node, NodeType};
31#[cfg(not(feature = "std"))]
32use alloc::collections::{BinaryHeap, VecDeque};
33pub use report::AnalysisReport;
34#[cfg(feature = "std")]
35use std::collections::{BinaryHeap, VecDeque};
36pub use tag::Tag;
37use tag::TriageTag;
38
39/// Analyzes decoded Crash Log records to extract diagnostic information.
40///
41/// The analyzer examines crash log data structures to identify root causes,
42/// extract diagnostic information, and generate structured reports. Results
43/// include prioritized findings and interpretation of crash log events.
44#[derive(Default)]
45pub struct Analyzer<'a> {
46    inputs: VecDeque<&'a Node>,
47    tags: BinaryHeap<TriageTag>,
48}
49
50impl<'a> Analyzer<'a> {
51    fn analyze_record(&mut self, node: &Node) {
52        match node.name.as_str().trim_end_matches(char::is_numeric) {
53            "pmc_rst" => self.analyze_pmc_rst(node),
54            "punit" | "pmc" => self.analyze_reason(node),
55            "pcore" | "ecore" => self.analyze_core(node),
56            "mca" => self.analyze_mca(node),
57            "crashlog_agent" => self.analyze_crashlog_agent(node),
58            _ => (),
59        }
60    }
61
62    fn analyze_records(&mut self, node: &Node) {
63        if let NodeType::Record = node.kind {
64            self.analyze_record(node)
65        } else {
66            for child in node.children() {
67                self.analyze_records(child);
68            }
69        }
70    }
71
72    /// Adds a crash log node to the analysis queue.
73    ///
74    /// Multiple nodes can be chained for batch analysis. The analyzer will
75    /// process all queued nodes when [`analyze`](Self::analyze) is called.
76    pub fn with_input(mut self, node: &'a Node) -> Self {
77        self.inputs.push_back(node);
78        self
79    }
80
81    /// Consumes the analyzer and performs analysis on all queued nodes.
82    ///
83    /// Traverses the crash log data structures, identifies issues, and generates
84    /// a report containing diagnostic findings and interpretations.
85    ///
86    /// # Returns
87    ///
88    /// An [`AnalysisReport`] containing analysis results.
89    pub fn analyze(mut self) -> AnalysisReport {
90        while let Some(input) = self.inputs.pop_front() {
91            self.analyze_records(input);
92        }
93
94        self.build_report()
95    }
96}