openzeppelin_monitor/utils/monitor/
error.rs

1//! Monitor execution error types and handling.
2//!
3//! Provides error types for monitor execution against a specific block,
4use crate::utils::logging::error::{ErrorContext, TraceableError};
5use std::collections::HashMap;
6use thiserror::Error as ThisError;
7use uuid::Uuid;
8
9/// Represents possible errors during monitor execution
10#[derive(ThisError, Debug)]
11pub enum MonitorExecutionError {
12	/// Errors related to not found errors
13	#[error("Not found error: {0}")]
14	NotFound(ErrorContext),
15
16	/// Errors related to execution failures
17	#[error("Execution error: {0}")]
18	ExecutionError(ErrorContext),
19
20	/// Other errors that don't fit into the categories above
21	#[error(transparent)]
22	Other(#[from] anyhow::Error),
23}
24
25impl MonitorExecutionError {
26	// Not found error
27	pub fn not_found(
28		msg: impl Into<String>,
29		source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
30		metadata: Option<HashMap<String, String>>,
31	) -> Self {
32		Self::NotFound(ErrorContext::new_with_log(msg, source, metadata))
33	}
34
35	// Execution error
36	pub fn execution_error(
37		msg: impl Into<String>,
38		source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
39		metadata: Option<HashMap<String, String>>,
40	) -> Self {
41		Self::ExecutionError(ErrorContext::new_with_log(msg, source, metadata))
42	}
43}
44
45impl TraceableError for MonitorExecutionError {
46	fn trace_id(&self) -> String {
47		match self {
48			Self::NotFound(ctx) => ctx.trace_id.clone(),
49			Self::ExecutionError(ctx) => ctx.trace_id.clone(),
50			Self::Other(_) => Uuid::new_v4().to_string(),
51		}
52	}
53}
54
55#[cfg(test)]
56mod tests {
57	use super::*;
58	use std::io::{Error as IoError, ErrorKind};
59
60	#[test]
61	fn test_not_found_error_formatting() {
62		let error = MonitorExecutionError::not_found("test error", None, None);
63		assert_eq!(error.to_string(), "Not found error: test error");
64
65		let source_error = IoError::new(ErrorKind::NotFound, "test source");
66		let error = MonitorExecutionError::not_found(
67			"test error",
68			Some(Box::new(source_error)),
69			Some(HashMap::from([("key1".to_string(), "value1".to_string())])),
70		);
71		assert_eq!(
72			error.to_string(),
73			"Not found error: test error [key1=value1]"
74		);
75	}
76
77	#[test]
78	fn test_execution_error_formatting() {
79		let error = MonitorExecutionError::execution_error("test error", None, None);
80		assert_eq!(error.to_string(), "Execution error: test error");
81
82		let source_error = IoError::new(ErrorKind::NotFound, "test source");
83		let error = MonitorExecutionError::execution_error(
84			"test error",
85			Some(Box::new(source_error)),
86			Some(HashMap::from([("key1".to_string(), "value1".to_string())])),
87		);
88		assert_eq!(
89			error.to_string(),
90			"Execution error: test error [key1=value1]"
91		);
92	}
93
94	#[test]
95	fn test_from_anyhow_error() {
96		let anyhow_error = anyhow::anyhow!("test anyhow error");
97		let script_error: MonitorExecutionError = anyhow_error.into();
98		assert!(matches!(script_error, MonitorExecutionError::Other(_)));
99		assert_eq!(script_error.to_string(), "test anyhow error");
100	}
101}