use crate::{
device_info::{MobileDeviceInfo, ThermalState},
mobile_performance_profiler::{MobileMetricsSnapshot, PerformanceBottleneck},
model_debugger::{ModelAnomaly, TensorDebugInfo},
scirs2_compat::random::legacy,
};
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, VecDeque};
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex, RwLock};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use trustformers_core::errors::{runtime_error, Result};
extern crate libc;
#[cfg(target_os = "ios")]
use std::ffi::{CStr, CString};
#[cfg(target_os = "android")]
use std::ffi::{CStr, CString};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashReporterConfig {
pub enabled: bool,
pub privacy_config: CrashPrivacyConfig,
pub storage_config: CrashStorageConfig,
pub analysis_config: CrashAnalysisConfig,
pub reporting_config: CrashReportingConfig,
pub recovery_config: CrashRecoveryConfig,
pub platform_config: PlatformCrashConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashPrivacyConfig {
pub auto_report: bool,
pub require_consent: bool,
pub include_user_data: bool,
pub include_system_info: bool,
pub include_stack_traces: bool,
pub include_memory_dumps: bool,
pub anonymize_data: bool,
pub retention_days: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashStorageConfig {
pub storage_directory: PathBuf,
pub max_local_reports: usize,
pub max_storage_size_mb: usize,
pub compress_reports: bool,
pub encrypt_reports: bool,
pub encryption_key_source: EncryptionKeySource,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashAnalysisConfig {
pub auto_analyze: bool,
pub pattern_detection: bool,
pub similarity_analysis: bool,
pub recovery_suggestions: bool,
pub analysis_timeout_secs: u64,
pub ml_analysis: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashReportingConfig {
pub remote_reporting: bool,
pub remote_endpoint: Option<String>,
pub auth_config: Option<ReportingAuthConfig>,
pub retry_config: RetryConfig,
pub batch_reporting: bool,
pub batch_size: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashRecoveryConfig {
pub auto_recovery: bool,
pub recovery_strategies: Vec<RecoveryStrategy>,
pub recovery_timeout_secs: u64,
pub state_restoration: bool,
pub safe_mode_config: SafeModeConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct PlatformCrashConfig {
#[cfg(target_os = "ios")]
pub ios_config: IOSCrashConfig,
#[cfg(target_os = "android")]
pub android_config: AndroidCrashConfig,
pub signal_config: SignalHandlingConfig,
}
#[cfg(target_os = "ios")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IOSCrashConfig {
pub mach_exceptions: bool,
pub bsd_signals: bool,
pub cpp_exceptions: bool,
pub app_store_compliance: bool,
pub privacy_manifest: bool,
}
#[cfg(target_os = "android")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AndroidCrashConfig {
pub native_crashes: bool,
pub java_crashes: bool,
pub anr_detection: bool,
pub play_store_compliance: bool,
pub tombstone_integration: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SignalHandlingConfig {
pub handled_signals: Vec<i32>,
pub stack_trace_depth: usize,
pub handler_timeout_ms: u64,
pub async_safe: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum EncryptionKeySource {
Hardware,
Keychain,
Generated,
None,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReportingAuthConfig {
pub auth_type: AuthType,
pub api_key: Option<String>,
pub bearer_token: Option<String>,
pub custom_headers: HashMap<String, String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum AuthType {
ApiKey,
BearerToken,
Custom,
None,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RetryConfig {
pub max_attempts: usize,
pub base_delay_ms: u64,
pub max_delay_ms: u64,
pub backoff_multiplier: f64,
pub jitter_factor: f64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum RecoveryStrategy {
RestartApp,
ResetModel,
ClearCache,
SafeMode,
ReducedFunctionality,
ManualIntervention,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SafeModeConfig {
pub enabled: bool,
pub disable_gpu: bool,
pub reduce_memory: bool,
pub disable_advanced_features: bool,
pub timeout_secs: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashReport {
pub report_id: String,
pub timestamp: u64,
pub crash_type: CrashType,
pub severity: CrashSeverity,
pub system_info: SystemCrashInfo,
pub app_info: AppCrashInfo,
pub stack_trace: Option<StackTrace>,
pub memory_dump: Option<MemoryDump>,
pub context: CrashContext,
pub analysis: Option<CrashAnalysis>,
pub recovery_suggestions: Vec<RecoverySuggestion>,
pub is_privacy_compliant: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum CrashType {
SegmentationFault,
OutOfMemory,
StackOverflow,
AssertionFailure,
UncaughtException,
Signal(i32),
ApplicationHang,
GPUCrash,
ModelCrash,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum CrashSeverity {
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemCrashInfo {
pub device_info: MobileDeviceInfo,
pub performance_metrics: Option<MobileMetricsSnapshot>,
pub memory_usage: MemoryUsageInfo,
pub cpu_info: CpuCrashInfo,
pub gpu_info: Option<GpuCrashInfo>,
pub thermal_state: Option<ThermalState>,
pub battery_info: Option<BatteryCrashInfo>,
pub network_info: Option<NetworkCrashInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppCrashInfo {
pub app_version: String,
pub build_number: String,
pub framework_version: String,
pub app_state: AppState,
pub foreground_status: ForegroundStatus,
pub session_duration: Duration,
pub model_info: Option<ModelCrashInfo>,
pub recent_operations: Vec<RecentOperation>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StackTrace {
pub crashed_thread: ThreadInfo,
pub all_threads: Vec<ThreadInfo>,
pub exception_info: Option<ExceptionInfo>,
pub signal_info: Option<SignalInfo>,
pub frames: Vec<StackFrame>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryDump {
pub memory_regions: Vec<MemoryRegion>,
pub heap_info: HeapInfo,
pub stack_info: StackInfo,
pub registers: HashMap<String, u64>,
pub binary_data: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashContext {
pub current_operation: Option<String>,
pub user_actions: Vec<UserAction>,
pub system_events: Vec<SystemEvent>,
pub model_anomalies: Vec<ModelAnomaly>,
pub performance_bottlenecks: Vec<PerformanceBottleneck>,
pub error_logs: Vec<ErrorLogEntry>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashAnalysis {
pub root_cause: Option<String>,
pub contributing_factors: Vec<String>,
pub similar_crashes: Vec<SimilarCrash>,
pub patterns: Vec<CrashPattern>,
pub risk_assessment: RiskAssessment,
pub confidence_score: f32,
pub analysis_timestamp: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RecoverySuggestion {
pub suggestion_type: RecoveryStrategy,
pub description: String,
pub steps: Vec<String>,
pub success_probability: f32,
pub risk_level: RiskLevel,
pub impact: RecoveryImpact,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryUsageInfo {
pub total_mb: f32,
pub used_mb: f32,
pub available_mb: f32,
pub heap_mb: f32,
pub stack_mb: f32,
pub gpu_mb: Option<f32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CpuCrashInfo {
pub usage_percent: f32,
pub frequency_mhz: u32,
pub temperature_c: Option<f32>,
pub throttling: bool,
pub active_cores: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GpuCrashInfo {
pub usage_percent: f32,
pub memory_usage_mb: f32,
pub temperature_c: Option<f32>,
pub frequency_mhz: Option<u32>,
pub vendor: String,
pub model: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BatteryCrashInfo {
pub level_percent: f32,
pub charging: bool,
pub temperature_c: Option<f32>,
pub power_usage_mw: Option<f32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkCrashInfo {
pub connection_type: NetworkConnectionType,
pub signal_strength: Option<f32>,
pub bandwidth_mbps: Option<f32>,
pub latency_ms: Option<f32>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum AppState {
Launching,
Active,
Background,
Suspended,
Terminating,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ForegroundStatus {
Foreground,
Background,
Unknown,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelCrashInfo {
pub model_id: String,
pub model_type: String,
pub current_operation: Option<String>,
pub input_tensors: Vec<TensorDebugInfo>,
pub performance_metrics: Option<ModelPerformanceMetrics>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RecentOperation {
pub operation: String,
pub timestamp: u64,
pub duration: Duration,
pub success: bool,
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadInfo {
pub thread_id: u64,
pub thread_name: Option<String>,
pub thread_state: ThreadState,
pub stack_frames: Vec<StackFrame>,
pub registers: HashMap<String, u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExceptionInfo {
pub exception_type: String,
pub message: String,
pub code: Option<i32>,
pub additional_info: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SignalInfo {
pub signal: i32,
pub signal_name: String,
pub signal_code: Option<i32>,
pub fault_address: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StackFrame {
pub frame_index: usize,
pub instruction_pointer: u64,
pub function_name: Option<String>,
pub file_name: Option<String>,
pub line_number: Option<u32>,
pub module_name: Option<String>,
pub symbol_offset: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryRegion {
pub start_address: u64,
pub end_address: u64,
pub size: usize,
pub region_type: MemoryRegionType,
pub permissions: MemoryPermissions,
pub protection: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HeapInfo {
pub total_size: usize,
pub used_size: usize,
pub free_size: usize,
pub largest_free_block: usize,
pub fragmentation_ratio: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StackInfo {
pub base_address: u64,
pub size: usize,
pub usage: usize,
pub overflow_detected: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserAction {
pub action_type: String,
pub timestamp: u64,
pub details: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemEvent {
pub event_type: String,
pub timestamp: u64,
pub data: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ErrorLogEntry {
pub level: LogLevel,
pub message: String,
pub timestamp: u64,
pub source: Option<String>,
pub line: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimilarCrash {
pub report_id: String,
pub similarity_score: f32,
pub matching_patterns: Vec<String>,
pub resolution_status: ResolutionStatus,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashPattern {
pub pattern_type: PatternType,
pub description: String,
pub frequency: usize,
pub confidence: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RiskAssessment {
pub risk_level: RiskLevel,
pub recurrence_likelihood: f32,
pub impact_assessment: ImpactAssessment,
pub mitigation_urgency: UrgencyLevel,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RecoveryImpact {
pub user_experience: ImpactLevel,
pub performance: ImpactLevel,
pub data_loss_risk: RiskLevel,
pub recovery_time_estimate: Duration,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelPerformanceMetrics {
pub inference_time: Duration,
pub memory_usage: usize,
pub gpu_utilization: Option<f32>,
pub throughput: f32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ThreadState {
Running,
Blocked,
Waiting,
Terminated,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum MemoryRegionType {
Code,
Data,
Heap,
Stack,
Shared,
Unknown,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryPermissions {
pub read: bool,
pub write: bool,
pub execute: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum NetworkConnectionType {
WiFi,
Cellular,
Ethernet,
Bluetooth,
None,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum LogLevel {
Error,
Warning,
Info,
Debug,
Trace,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ResolutionStatus {
Unresolved,
InProgress,
Resolved,
WontFix,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PatternType {
MemoryLeak,
StackOverflow,
DeadLock,
RaceCondition,
ResourceExhaustion,
InvalidState,
ConfigurationError,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum RiskLevel {
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ImpactAssessment {
pub user_impact: ImpactLevel,
pub business_impact: ImpactLevel,
pub technical_impact: ImpactLevel,
pub security_impact: ImpactLevel,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ImpactLevel {
Minimal,
Low,
Medium,
High,
Severe,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum UrgencyLevel {
Low,
Medium,
High,
Critical,
Emergency,
}
pub struct MobileCrashReporter {
config: CrashReporterConfig,
crash_history: Arc<RwLock<VecDeque<CrashReport>>>,
analysis_engine: Arc<Mutex<CrashAnalysisEngine>>,
storage_manager: Arc<Mutex<CrashStorageManager>>,
recovery_manager: Arc<Mutex<CrashRecoveryManager>>,
signal_handler: Option<SignalHandler>,
is_initialized: Arc<Mutex<bool>>,
}
struct CrashAnalysisEngine {
pattern_database: HashMap<String, CrashPattern>,
similarity_threshold: f32,
analysis_cache: HashMap<String, CrashAnalysis>,
ml_analyzer: Option<MLCrashAnalyzer>,
}
struct CrashStorageManager {
storage_path: PathBuf,
encryption_enabled: bool,
compression_enabled: bool,
max_reports: usize,
current_size: usize,
max_size: usize,
}
struct CrashRecoveryManager {
recovery_strategies: Vec<RecoveryStrategy>,
safe_mode_active: bool,
recovery_history: VecDeque<RecoveryAttempt>,
auto_recovery_enabled: bool,
}
struct SignalHandler {
handled_signals: Vec<i32>,
crash_reporter: Arc<Mutex<Option<Arc<MobileCrashReporter>>>>,
}
struct MLCrashAnalyzer {
model_path: PathBuf,
confidence_threshold: f32,
analysis_enabled: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct RecoveryAttempt {
strategy: RecoveryStrategy,
timestamp: u64,
success: bool,
duration: Duration,
error: Option<String>,
}
impl Default for CrashReporterConfig {
fn default() -> Self {
Self {
enabled: true,
privacy_config: CrashPrivacyConfig::default(),
storage_config: CrashStorageConfig::default(),
analysis_config: CrashAnalysisConfig::default(),
reporting_config: CrashReportingConfig::default(),
recovery_config: CrashRecoveryConfig::default(),
platform_config: PlatformCrashConfig::default(),
}
}
}
impl Default for CrashPrivacyConfig {
fn default() -> Self {
Self {
auto_report: false, require_consent: true,
include_user_data: false,
include_system_info: true,
include_stack_traces: true,
include_memory_dumps: false, anonymize_data: true,
retention_days: 30,
}
}
}
impl Default for CrashStorageConfig {
fn default() -> Self {
Self {
storage_directory: PathBuf::from("crash_reports"),
max_local_reports: 100,
max_storage_size_mb: 50,
compress_reports: true,
encrypt_reports: true,
encryption_key_source: EncryptionKeySource::Keychain,
}
}
}
impl Default for CrashAnalysisConfig {
fn default() -> Self {
Self {
auto_analyze: true,
pattern_detection: true,
similarity_analysis: true,
recovery_suggestions: true,
analysis_timeout_secs: 30,
ml_analysis: false, }
}
}
impl Default for CrashReportingConfig {
fn default() -> Self {
Self {
remote_reporting: false, remote_endpoint: None,
auth_config: None,
retry_config: RetryConfig::default(),
batch_reporting: true,
batch_size: 10,
}
}
}
impl Default for CrashRecoveryConfig {
fn default() -> Self {
Self {
auto_recovery: true,
recovery_strategies: vec![
RecoveryStrategy::ClearCache,
RecoveryStrategy::ResetModel,
RecoveryStrategy::SafeMode,
],
recovery_timeout_secs: 60,
state_restoration: true,
safe_mode_config: SafeModeConfig::default(),
}
}
}
#[cfg(target_os = "ios")]
impl Default for IOSCrashConfig {
fn default() -> Self {
Self {
mach_exceptions: true,
bsd_signals: true,
cpp_exceptions: true,
app_store_compliance: true,
privacy_manifest: true,
}
}
}
#[cfg(target_os = "android")]
impl Default for AndroidCrashConfig {
fn default() -> Self {
Self {
native_crashes: true,
java_crashes: true,
anr_detection: true,
play_store_compliance: true,
tombstone_integration: true,
}
}
}
impl Default for SignalHandlingConfig {
fn default() -> Self {
Self {
handled_signals: vec![
libc::SIGSEGV, libc::SIGABRT, libc::SIGBUS, libc::SIGFPE, libc::SIGILL, libc::SIGPIPE, ],
stack_trace_depth: 50,
handler_timeout_ms: 5000,
async_safe: true,
}
}
}
impl Default for RetryConfig {
fn default() -> Self {
Self {
max_attempts: 3,
base_delay_ms: 1000,
max_delay_ms: 30000,
backoff_multiplier: 2.0,
jitter_factor: 0.1,
}
}
}
impl Default for SafeModeConfig {
fn default() -> Self {
Self {
enabled: true,
disable_gpu: true,
reduce_memory: true,
disable_advanced_features: true,
timeout_secs: 300, }
}
}
impl MobileCrashReporter {
pub fn new(config: CrashReporterConfig) -> Result<Self> {
let analysis_engine = CrashAnalysisEngine::new(&config.analysis_config)?;
let storage_manager = CrashStorageManager::new(&config.storage_config)?;
let recovery_manager = CrashRecoveryManager::new(&config.recovery_config)?;
Ok(Self {
config,
crash_history: Arc::new(RwLock::new(VecDeque::new())),
analysis_engine: Arc::new(Mutex::new(analysis_engine)),
storage_manager: Arc::new(Mutex::new(storage_manager)),
recovery_manager: Arc::new(Mutex::new(recovery_manager)),
signal_handler: None,
is_initialized: Arc::new(Mutex::new(false)),
})
}
pub fn initialize(&mut self) -> Result<()> {
{
let mut initialized = self
.is_initialized
.lock()
.map_err(|_| runtime_error("Failed to acquire lock"))?;
if *initialized {
return Ok(());
}
if !self.config.enabled {
return Ok(());
}
*initialized = true;
}
self.setup_signal_handlers()?;
self.storage_manager
.lock()
.map_err(|_| runtime_error("Failed to acquire lock"))?
.initialize()?;
self.load_crash_history()?;
Ok(())
}
pub fn report_crash(&self, crash_info: CrashInfo) -> Result<String> {
if !self.config.enabled {
return Err(runtime_error("Crash reporter not enabled"));
}
let report_id = self.generate_report_id();
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs();
let system_info = self.collect_system_info()?;
let app_info = self.collect_app_info()?;
let is_privacy_compliant = self.is_privacy_compliant(&crash_info);
let mut crash_report = CrashReport {
report_id: report_id.clone(),
timestamp,
crash_type: crash_info.crash_type,
severity: self.assess_crash_severity(&crash_info),
system_info,
app_info,
stack_trace: crash_info.stack_trace,
memory_dump: crash_info.memory_dump,
context: crash_info.context,
analysis: None,
recovery_suggestions: Vec::new(),
is_privacy_compliant,
};
if self.config.analysis_config.auto_analyze {
if let Ok(analysis) = self.analyze_crash(&crash_report) {
crash_report.analysis = Some(analysis);
}
}
crash_report.recovery_suggestions = self.generate_recovery_suggestions(&crash_report)?;
self.store_crash_report(&crash_report)?;
let mut history = self
.crash_history
.write()
.map_err(|_| runtime_error("Failed to acquire write lock"))?;
history.push_back(crash_report.clone());
while history.len() > 1000 {
history.pop_front();
}
if self.config.recovery_config.auto_recovery {
self.attempt_recovery(&crash_report)?;
}
if self.config.reporting_config.remote_reporting && self.has_user_consent() {
self.report_remote(&crash_report)?;
}
Ok(report_id)
}
pub fn get_crash_report(&self, report_id: &str) -> Result<Option<CrashReport>> {
let history = self
.crash_history
.read()
.map_err(|_| runtime_error("Failed to acquire read lock"))?;
Ok(history.iter().find(|report| report.report_id == report_id).cloned())
}
pub fn get_recent_crashes(&self, limit: Option<usize>) -> Result<Vec<CrashReport>> {
let history = self
.crash_history
.read()
.map_err(|_| runtime_error("Failed to acquire read lock"))?;
let reports: Vec<CrashReport> =
history.iter().rev().take(limit.unwrap_or(50)).cloned().collect();
Ok(reports)
}
pub fn get_crash_statistics(&self) -> Result<CrashStatistics> {
let history = self
.crash_history
.read()
.map_err(|_| runtime_error("Failed to acquire read lock"))?;
let total_crashes = history.len();
let mut crash_types = HashMap::new();
let mut severity_counts = HashMap::new();
for report in history.iter() {
*crash_types.entry(report.crash_type).or_insert(0) += 1;
*severity_counts.entry(report.severity).or_insert(0) += 1;
}
Ok(CrashStatistics {
total_crashes,
crash_types,
severity_counts,
crash_free_sessions: 0, mean_time_between_crashes: Duration::from_secs(0), })
}
pub fn clear_crash_history(&self) -> Result<()> {
let mut history = self
.crash_history
.write()
.map_err(|_| runtime_error("Failed to acquire write lock"))?;
history.clear();
self.storage_manager
.lock()
.map_err(|_| runtime_error("Failed to acquire lock"))?
.clear_all()?;
Ok(())
}
pub fn export_crash_reports(&self, format: ExportFormat, output_path: &Path) -> Result<()> {
let history = self
.crash_history
.read()
.map_err(|_| runtime_error("Failed to acquire read lock"))?;
match format {
ExportFormat::Json => {
let json = serde_json::to_string_pretty(&*history)
.map_err(|e| runtime_error(format!("Serialization error: {}", e)))?;
fs::write(output_path, json)
.map_err(|e| runtime_error(format!("IO error: {}", e)))?;
},
ExportFormat::Csv => {
let data: Vec<CrashReport> = history.iter().cloned().collect();
self.export_csv(&data, output_path)?;
},
ExportFormat::Html => {
let data: Vec<CrashReport> = history.iter().cloned().collect();
self.export_html(&data, output_path)?;
},
}
Ok(())
}
fn setup_signal_handlers(&mut self) -> Result<()> {
if !self.config.platform_config.signal_config.async_safe {
return Ok(()); }
Ok(())
}
fn load_crash_history(&self) -> Result<()> {
let storage_manager = self
.storage_manager
.lock()
.map_err(|_| runtime_error("Failed to acquire lock"))?;
let reports = storage_manager.load_all_reports()?;
let mut history = self
.crash_history
.write()
.map_err(|_| runtime_error("Failed to acquire write lock"))?;
for report in reports {
history.push_back(report);
}
Ok(())
}
fn generate_report_id(&self) -> String {
format!(
"crash_{}_{}",
SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_nanos(),
(legacy::f64() * u32::MAX as f64) as u32
)
}
fn collect_system_info(&self) -> Result<SystemCrashInfo> {
Ok(SystemCrashInfo {
device_info: crate::device_info::MobileDeviceDetector::detect()?,
performance_metrics: None, memory_usage: self.collect_memory_usage()?,
cpu_info: self.collect_cpu_info()?,
gpu_info: self.collect_gpu_info(),
thermal_state: None, battery_info: self.collect_battery_info(),
network_info: self.collect_network_info(),
})
}
fn collect_app_info(&self) -> Result<AppCrashInfo> {
Ok(AppCrashInfo {
app_version: env!("CARGO_PKG_VERSION").to_string(),
build_number: "1".to_string(), framework_version: env!("CARGO_PKG_VERSION").to_string(),
app_state: AppState::Active, foreground_status: ForegroundStatus::Foreground,
session_duration: Duration::from_secs(0), model_info: None, recent_operations: Vec::new(), })
}
fn collect_memory_usage(&self) -> Result<MemoryUsageInfo> {
Ok(MemoryUsageInfo {
total_mb: 0.0,
used_mb: 0.0,
available_mb: 0.0,
heap_mb: 0.0,
stack_mb: 0.0,
gpu_mb: None,
})
}
fn collect_cpu_info(&self) -> Result<CpuCrashInfo> {
Ok(CpuCrashInfo {
usage_percent: 0.0,
frequency_mhz: 0,
temperature_c: None,
throttling: false,
active_cores: 1,
})
}
fn collect_gpu_info(&self) -> Option<GpuCrashInfo> {
None }
fn collect_battery_info(&self) -> Option<BatteryCrashInfo> {
None }
fn collect_network_info(&self) -> Option<NetworkCrashInfo> {
None }
fn assess_crash_severity(&self, crash_info: &CrashInfo) -> CrashSeverity {
match crash_info.crash_type {
CrashType::SegmentationFault | CrashType::StackOverflow => CrashSeverity::Critical,
CrashType::OutOfMemory => CrashSeverity::High,
CrashType::UncaughtException => CrashSeverity::Medium,
CrashType::ApplicationHang => CrashSeverity::Medium,
_ => CrashSeverity::Low,
}
}
fn is_privacy_compliant(&self, _crash_info: &CrashInfo) -> bool {
!self.config.privacy_config.include_user_data || self.config.privacy_config.anonymize_data
}
fn analyze_crash(&self, report: &CrashReport) -> Result<CrashAnalysis> {
let analysis_engine = self
.analysis_engine
.lock()
.map_err(|_| runtime_error("Failed to acquire lock"))?;
analysis_engine.analyze_crash(report)
}
fn generate_recovery_suggestions(
&self,
report: &CrashReport,
) -> Result<Vec<RecoverySuggestion>> {
let mut suggestions = Vec::new();
match report.crash_type {
CrashType::OutOfMemory => {
suggestions.push(RecoverySuggestion {
suggestion_type: RecoveryStrategy::ClearCache,
description: "Clear application cache to free memory".to_string(),
steps: vec![
"Clear model cache".to_string(),
"Clear temporary files".to_string(),
"Restart inference engine".to_string(),
],
success_probability: 0.8,
risk_level: RiskLevel::Low,
impact: RecoveryImpact {
user_experience: ImpactLevel::Low,
performance: ImpactLevel::Low,
data_loss_risk: RiskLevel::Low,
recovery_time_estimate: Duration::from_secs(30),
},
});
},
CrashType::SegmentationFault => {
suggestions.push(RecoverySuggestion {
suggestion_type: RecoveryStrategy::SafeMode,
description: "Enable safe mode with reduced functionality".to_string(),
steps: vec![
"Disable GPU acceleration".to_string(),
"Reduce memory usage".to_string(),
"Disable advanced features".to_string(),
],
success_probability: 0.9,
risk_level: RiskLevel::Low,
impact: RecoveryImpact {
user_experience: ImpactLevel::Medium,
performance: ImpactLevel::High,
data_loss_risk: RiskLevel::Low,
recovery_time_estimate: Duration::from_secs(60),
},
});
},
_ => {
suggestions.push(RecoverySuggestion {
suggestion_type: RecoveryStrategy::RestartApp,
description: "Restart application to clear problematic state".to_string(),
steps: vec!["Restart application".to_string()],
success_probability: 0.7,
risk_level: RiskLevel::Medium,
impact: RecoveryImpact {
user_experience: ImpactLevel::High,
performance: ImpactLevel::Low,
data_loss_risk: RiskLevel::Medium,
recovery_time_estimate: Duration::from_secs(10),
},
});
},
}
Ok(suggestions)
}
fn store_crash_report(&self, report: &CrashReport) -> Result<()> {
let storage_manager = self
.storage_manager
.lock()
.map_err(|_| runtime_error("Failed to acquire lock"))?;
storage_manager.store_report(report)
}
fn attempt_recovery(&self, report: &CrashReport) -> Result<()> {
let mut recovery_manager = self
.recovery_manager
.lock()
.map_err(|_| runtime_error("Failed to acquire lock"))?;
recovery_manager.attempt_recovery(report)
}
fn has_user_consent(&self) -> bool {
if !self.config.privacy_config.require_consent {
return true;
}
false
}
fn report_remote(&self, _report: &CrashReport) -> Result<()> {
Ok(())
}
fn export_csv(&self, reports: &[CrashReport], output_path: &Path) -> Result<()> {
let mut csv_content = String::new();
csv_content.push_str("Report ID,Timestamp,Crash Type,Severity,App Version\n");
for report in reports {
csv_content.push_str(&format!(
"{},{},{:?},{:?},{}\n",
report.report_id,
report.timestamp,
report.crash_type,
report.severity,
report.app_info.app_version
));
}
fs::write(output_path, csv_content)
.map_err(|e| runtime_error(format!("IO error: {}", e)))?;
Ok(())
}
fn export_html(&self, reports: &[CrashReport], output_path: &Path) -> Result<()> {
let mut html = String::new();
html.push_str("<!DOCTYPE html><html><head><title>Crash Reports</title></head><body>");
html.push_str("<h1>Crash Reports</h1>");
html.push_str("<table border='1'>");
html.push_str(
"<tr><th>Report ID</th><th>Timestamp</th><th>Type</th><th>Severity</th></tr>",
);
for report in reports {
html.push_str(&format!(
"<tr><td>{}</td><td>{}</td><td>{:?}</td><td>{:?}</td></tr>",
report.report_id, report.timestamp, report.crash_type, report.severity
));
}
html.push_str("</table></body></html>");
fs::write(output_path, html).map_err(|e| runtime_error(format!("IO error: {}", e)))?;
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct CrashInfo {
pub crash_type: CrashType,
pub stack_trace: Option<StackTrace>,
pub memory_dump: Option<MemoryDump>,
pub context: CrashContext,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashStatistics {
pub total_crashes: usize,
pub crash_types: HashMap<CrashType, usize>,
pub severity_counts: HashMap<CrashSeverity, usize>,
pub crash_free_sessions: usize,
pub mean_time_between_crashes: Duration,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExportFormat {
Json,
Csv,
Html,
}
impl CrashAnalysisEngine {
fn new(_config: &CrashAnalysisConfig) -> Result<Self> {
Ok(Self {
pattern_database: HashMap::new(),
similarity_threshold: 0.7,
analysis_cache: HashMap::new(),
ml_analyzer: None,
})
}
fn analyze_crash(&self, _report: &CrashReport) -> Result<CrashAnalysis> {
Ok(CrashAnalysis {
root_cause: Some("Memory access violation".to_string()),
contributing_factors: vec!["High memory usage".to_string()],
similar_crashes: Vec::new(),
patterns: Vec::new(),
risk_assessment: RiskAssessment {
risk_level: RiskLevel::High,
recurrence_likelihood: 0.6,
impact_assessment: ImpactAssessment {
user_impact: ImpactLevel::High,
business_impact: ImpactLevel::Medium,
technical_impact: ImpactLevel::High,
security_impact: ImpactLevel::Low,
},
mitigation_urgency: UrgencyLevel::High,
},
confidence_score: 0.8,
analysis_timestamp: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
})
}
}
impl CrashStorageManager {
fn new(config: &CrashStorageConfig) -> Result<Self> {
Ok(Self {
storage_path: config.storage_directory.clone(),
encryption_enabled: config.encrypt_reports,
compression_enabled: config.compress_reports,
max_reports: config.max_local_reports,
current_size: 0,
max_size: config.max_storage_size_mb * 1024 * 1024,
})
}
fn initialize(&mut self) -> Result<()> {
if !self.storage_path.exists() {
fs::create_dir_all(&self.storage_path)
.map_err(|e| runtime_error(format!("IO error: {}", e)))?;
}
Ok(())
}
fn store_report(&self, report: &CrashReport) -> Result<()> {
let file_path = self.storage_path.join(format!("{}.json", report.report_id));
let json = serde_json::to_string(report)
.map_err(|e| runtime_error(format!("Serialization error: {}", e)))?;
fs::write(file_path, json).map_err(|e| runtime_error(format!("IO error: {}", e)))?;
Ok(())
}
fn load_all_reports(&self) -> Result<Vec<CrashReport>> {
let mut reports = Vec::new();
if !self.storage_path.exists() {
return Ok(reports);
}
let entries = fs::read_dir(&self.storage_path)
.map_err(|e| runtime_error(format!("IO error: {}", e)))?;
for entry in entries {
let entry = entry.map_err(|e| runtime_error(format!("IO error: {}", e)))?;
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some("json") {
if let Ok(content) = fs::read_to_string(&path) {
if let Ok(report) = serde_json::from_str::<CrashReport>(&content) {
reports.push(report);
}
}
}
}
Ok(reports)
}
fn clear_all(&self) -> Result<()> {
if self.storage_path.exists() {
fs::remove_dir_all(&self.storage_path)
.map_err(|e| runtime_error(format!("IO error: {}", e)))?;
fs::create_dir_all(&self.storage_path)
.map_err(|e| runtime_error(format!("IO error: {}", e)))?;
}
Ok(())
}
}
impl CrashRecoveryManager {
fn new(config: &CrashRecoveryConfig) -> Result<Self> {
Ok(Self {
recovery_strategies: config.recovery_strategies.clone(),
safe_mode_active: false,
recovery_history: VecDeque::new(),
auto_recovery_enabled: config.auto_recovery,
})
}
fn attempt_recovery(&mut self, _report: &CrashReport) -> Result<()> {
if !self.auto_recovery_enabled {
return Ok(());
}
let strategies = self.recovery_strategies.clone();
for strategy in &strategies {
let start_time = Instant::now();
let success = self.execute_recovery_strategy(*strategy)?;
let duration = start_time.elapsed();
let attempt = RecoveryAttempt {
strategy: *strategy,
timestamp: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
success,
duration,
error: None,
};
self.recovery_history.push_back(attempt);
if success {
break;
}
}
Ok(())
}
fn execute_recovery_strategy(&mut self, strategy: RecoveryStrategy) -> Result<bool> {
match strategy {
RecoveryStrategy::ClearCache => {
Ok(true)
},
RecoveryStrategy::ResetModel => {
Ok(true)
},
RecoveryStrategy::SafeMode => {
self.safe_mode_active = true;
Ok(true)
},
_ => Ok(false),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_crash_reporter_creation() {
let config = CrashReporterConfig::default();
let reporter = MobileCrashReporter::new(config);
assert!(reporter.is_ok());
}
#[test]
fn test_crash_severity_assessment() {
let config = CrashReporterConfig::default();
let reporter = MobileCrashReporter::new(config).expect("Operation failed");
let crash_info = CrashInfo {
crash_type: CrashType::SegmentationFault,
stack_trace: None,
memory_dump: None,
context: CrashContext {
current_operation: None,
user_actions: Vec::new(),
system_events: Vec::new(),
model_anomalies: Vec::new(),
performance_bottlenecks: Vec::new(),
error_logs: Vec::new(),
},
};
let severity = reporter.assess_crash_severity(&crash_info);
assert_eq!(severity, CrashSeverity::Critical);
}
#[test]
fn test_privacy_compliance() {
let mut config = CrashReporterConfig::default();
config.privacy_config.include_user_data = false;
config.privacy_config.anonymize_data = true;
let reporter = MobileCrashReporter::new(config).expect("Operation failed");
let crash_info = CrashInfo {
crash_type: CrashType::OutOfMemory,
stack_trace: None,
memory_dump: None,
context: CrashContext {
current_operation: None,
user_actions: Vec::new(),
system_events: Vec::new(),
model_anomalies: Vec::new(),
performance_bottlenecks: Vec::new(),
error_logs: Vec::new(),
},
};
assert!(reporter.is_privacy_compliant(&crash_info));
}
#[test]
fn test_recovery_suggestions() {
let config = CrashReporterConfig::default();
let reporter = MobileCrashReporter::new(config).expect("Operation failed");
let crash_report = CrashReport {
report_id: "test".to_string(),
timestamp: 0,
crash_type: CrashType::OutOfMemory,
severity: CrashSeverity::High,
system_info: SystemCrashInfo {
device_info: crate::device_info::MobileDeviceDetector::detect()
.expect("Operation failed"),
performance_metrics: None,
memory_usage: MemoryUsageInfo {
total_mb: 1024.0,
used_mb: 1000.0,
available_mb: 24.0,
heap_mb: 800.0,
stack_mb: 50.0,
gpu_mb: None,
},
cpu_info: CpuCrashInfo {
usage_percent: 90.0,
frequency_mhz: 2000,
temperature_c: Some(80.0),
throttling: true,
active_cores: 4,
},
gpu_info: None,
thermal_state: None,
battery_info: None,
network_info: None,
},
app_info: AppCrashInfo {
app_version: "1.0.0".to_string(),
build_number: "1".to_string(),
framework_version: "1.0.0".to_string(),
app_state: AppState::Active,
foreground_status: ForegroundStatus::Foreground,
session_duration: Duration::from_secs(300),
model_info: None,
recent_operations: Vec::new(),
},
stack_trace: None,
memory_dump: None,
context: CrashContext {
current_operation: None,
user_actions: Vec::new(),
system_events: Vec::new(),
model_anomalies: Vec::new(),
performance_bottlenecks: Vec::new(),
error_logs: Vec::new(),
},
analysis: None,
recovery_suggestions: Vec::new(),
is_privacy_compliant: true,
};
let suggestions =
reporter.generate_recovery_suggestions(&crash_report).expect("Operation failed");
assert!(!suggestions.is_empty());
assert_eq!(suggestions[0].suggestion_type, RecoveryStrategy::ClearCache);
}
}