Skip to main content

stylus_trace_core/diff/
schema.rs

1//! Schema definitions for diff reports.
2//!
3//! Defines the structures that represent differences between two profiles.
4
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8/// Complete diff report comparing baseline and target profiles
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct DiffReport {
11    /// Schema version for the diff format
12    pub diff_version: String,
13
14    /// Timestamp when diff was generated
15    pub generated_at: String,
16
17    /// Metadata from baseline profile
18    pub baseline: ProfileMetadata,
19
20    /// Metadata from target profile
21    pub target: ProfileMetadata,
22
23    /// Calculated deltas between profiles
24    pub deltas: Deltas,
25
26    /// List of threshold violations (if any)
27    pub threshold_violations: Vec<ThresholdViolation>,
28
29    /// Analysis insights (Option 4: Heuristics)
30    #[serde(default, skip_serializing_if = "Vec::is_empty")]
31    pub insights: Vec<AnalysisInsight>,
32
33    /// Summary of diff results
34    pub summary: DiffSummary,
35}
36
37/// Metadata extracted from a profile for comparison
38#[derive(Debug, Clone, Serialize, Deserialize, Default)]
39pub struct ProfileMetadata {
40    /// Transaction hash
41    pub transaction_hash: String,
42
43    /// Total gas used
44    pub total_gas: u64,
45
46    /// When the profile was generated
47    pub generated_at: String,
48}
49
50/// All calculated deltas
51#[derive(Debug, Clone, Serialize, Deserialize, Default)]
52pub struct Deltas {
53    /// Gas usage changes
54    pub gas: GasDelta,
55
56    /// HostIO changes
57    pub hostio: HostIoDelta,
58
59    /// Hot path changes
60    pub hot_paths: HotPathsDelta,
61}
62
63/// Gas usage delta
64#[derive(Debug, Clone, Serialize, Deserialize, Default)]
65pub struct GasDelta {
66    /// Baseline gas
67    pub baseline: u64,
68
69    /// Target gas
70    pub target: u64,
71
72    /// Absolute change (can be negative)
73    pub absolute_change: i64,
74
75    /// Percentage change (can be negative)
76    pub percent_change: f64,
77}
78
79/// HostIO statistics delta
80#[derive(Debug, Clone, Serialize, Deserialize, Default)]
81pub struct HostIoDelta {
82    /// Baseline total calls
83    pub baseline_total_calls: u64,
84
85    /// Target total calls
86    pub target_total_calls: u64,
87
88    /// Change in total calls
89    pub total_calls_change: i64,
90
91    /// Percentage change in total calls
92    pub total_calls_percent_change: f64,
93
94    /// Changes by HostIO type
95    pub by_type_changes: HashMap<String, HostIOTypeChange>,
96
97    /// Baseline total HostIO gas
98    pub baseline_total_gas: u64,
99
100    /// Target total HostIO gas
101    pub target_total_gas: u64,
102
103    /// Change in HostIO gas
104    pub gas_change: i64,
105
106    /// Percentage change in HostIO gas
107    pub gas_percent_change: f64,
108}
109
110/// Change in a specific HostIO type
111#[derive(Debug, Clone, Serialize, Deserialize, Default)]
112pub struct HostIOTypeChange {
113    /// Count in baseline
114    pub baseline: u64,
115
116    /// Count in target
117    pub target: u64,
118
119    /// Delta (target - baseline)
120    pub delta: i64,
121}
122
123/// Hot paths comparison
124#[derive(Debug, Clone, Serialize, Deserialize, Default)]
125pub struct HotPathsDelta {
126    /// Paths present in both profiles
127    pub common_paths: Vec<HotPathComparison>,
128
129    /// Paths only in baseline (disappeared)
130    pub baseline_only: Vec<crate::parser::schema::HotPath>,
131
132    /// Paths only in target (new)
133    pub target_only: Vec<crate::parser::schema::HotPath>,
134}
135
136/// Comparison of a single hot path present in both profiles
137#[derive(Debug, Clone, Serialize, Deserialize, Default)]
138pub struct HotPathComparison {
139    /// Stack trace identifier
140    pub stack: String,
141
142    /// Gas in baseline
143    pub baseline_gas: u64,
144
145    /// Gas in target
146    pub target_gas: u64,
147
148    /// Change in gas
149    pub gas_change: i64,
150
151    /// Percentage change
152    pub percent_change: f64,
153}
154
155/// A single threshold violation
156#[derive(Debug, Clone, Serialize, Deserialize, Default)]
157pub struct ThresholdViolation {
158    /// Name of the metric that violated threshold
159    pub metric: String,
160
161    /// Threshold value
162    pub threshold: f64,
163
164    /// Actual value
165    pub actual: f64,
166
167    /// Severity: "error" or "warning"
168    pub severity: String,
169}
170
171/// Summary of diff results
172#[derive(Debug, Clone, Serialize, Deserialize)]
173pub struct DiffSummary {
174    /// Whether there are any regressions
175    pub has_regressions: bool,
176
177    /// Number of threshold violations
178    pub violation_count: usize,
179
180    /// Overall status: "PASSED", "FAILED", "WARNING"
181    pub status: String,
182
183    /// Optional warning message
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub warning: Option<String>,
186}
187
188/// A qualitative insight from the trace analysis
189#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct AnalysisInsight {
191    /// Category of the insight (e.g., "Storage", "HostIO")
192    pub category: String,
193
194    /// Human-readable description
195    pub description: String,
196
197    /// Severity of the insight
198    pub severity: InsightSeverity,
199
200    /// Optional tag for grouping
201    pub tag: Option<String>,
202}
203
204/// Severity level for analysis insights
205#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
206#[serde(rename_all = "lowercase")]
207pub enum InsightSeverity {
208    /// Purely informational
209    Info,
210    /// Suggests a possible optimization
211    Low,
212    /// Significant optimization opportunity or suspicious pattern
213    Medium,
214    /// Urgent performance issue
215    High,
216}