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}