scouter_types/
error.rs

1use pyo3::exceptions::PyRuntimeError;
2use pyo3::PyErr;
3use thiserror::Error;
4
5#[derive(Error, Debug)]
6pub enum UtilError {
7    #[error("Failed to get parent path")]
8    GetParentPathError,
9
10    #[error("Failed to create directory")]
11    CreateDirectoryError,
12
13    #[error("Failed to read to create path")]
14    CreatePathError,
15
16    #[error(transparent)]
17    IoError(#[from] std::io::Error),
18
19    #[error(transparent)]
20    SerdeJsonError(#[from] serde_json::Error),
21}
22
23impl From<UtilError> for PyErr {
24    fn from(err: UtilError) -> PyErr {
25        let msg = err.to_string();
26        PyRuntimeError::new_err(msg)
27    }
28}
29
30#[derive(Error, Debug)]
31pub enum TypeError {
32    #[error("Start time must be before end time")]
33    StartTimeError,
34
35    #[error("Invalid schedule")]
36    InvalidScheduleError,
37
38    #[error("Invalid PSI threshold configuration")]
39    InvalidPsiThresholdError,
40
41    #[error("Invalid alert dispatch configuration")]
42    InvalidDispatchConfigError,
43
44    #[error("Missing space argument")]
45    MissingSpaceError,
46
47    #[error("Missing name argument")]
48    MissingNameError,
49
50    #[error("Missing version argument")]
51    MissingVersionError,
52
53    #[error("Missing alert_config argument")]
54    MissingAlertConfigError,
55
56    #[error("No metrics found")]
57    NoMetricsError,
58
59    #[error(transparent)]
60    SerdeJsonError(#[from] serde_json::Error),
61
62    #[error("Invalid number")]
63    InvalidNumberError,
64
65    #[error("Root must be an object")]
66    RootMustBeObject,
67
68    #[error("Unsupported type: {0}")]
69    UnsupportedTypeError(String),
70
71    #[error("Failed to downcast Python object: {0}")]
72    DowncastError(String),
73
74    #[error("Invalid data type")]
75    InvalidDataType,
76
77    #[error("Missing value for string feature")]
78    MissingStringValueError,
79
80    #[error("{0}")]
81    PyError(String),
82}
83
84impl<'a> From<pyo3::DowncastError<'a, 'a>> for TypeError {
85    fn from(err: pyo3::DowncastError) -> Self {
86        TypeError::DowncastError(err.to_string())
87    }
88}
89
90impl From<TypeError> for PyErr {
91    fn from(err: TypeError) -> PyErr {
92        let msg = err.to_string();
93        PyRuntimeError::new_err(msg)
94    }
95}
96
97impl From<PyErr> for TypeError {
98    fn from(err: PyErr) -> TypeError {
99        TypeError::PyError(err.to_string())
100    }
101}
102
103#[derive(Error, Debug)]
104pub enum ContractError {
105    #[error(transparent)]
106    TypeError(#[from] TypeError),
107
108    #[error("{0}")]
109    PyError(String),
110}
111
112impl From<ContractError> for PyErr {
113    fn from(err: ContractError) -> PyErr {
114        let msg = err.to_string();
115        PyRuntimeError::new_err(msg)
116    }
117}
118
119impl From<PyErr> for ContractError {
120    fn from(err: PyErr) -> ContractError {
121        ContractError::PyError(err.to_string())
122    }
123}
124
125#[derive(Error, Debug)]
126pub enum RecordError {
127    #[error("Unable to extract record into any known ServerRecord variant")]
128    ExtractionError,
129
130    #[error("No server records found")]
131    EmptyServerRecordsError,
132
133    #[error(transparent)]
134    SerdeJsonError(#[from] serde_json::Error),
135
136    #[error("Unexpected record type")]
137    InvalidDriftTypeError,
138
139    #[error("{0}")]
140    PyError(String),
141}
142
143impl From<RecordError> for PyErr {
144    fn from(err: RecordError) -> PyErr {
145        let msg = err.to_string();
146        PyRuntimeError::new_err(msg)
147    }
148}
149
150impl From<PyErr> for RecordError {
151    fn from(err: PyErr) -> RecordError {
152        RecordError::PyError(err.to_string())
153    }
154}
155
156#[derive(Error, Debug)]
157pub enum ProfileError {
158    #[error(transparent)]
159    SerdeJsonError(#[from] serde_json::Error),
160
161    #[error("Features and array are not the same length")]
162    FeatureArrayLengthError,
163
164    #[error("Unexpected record type")]
165    InvalidDriftTypeError,
166
167    #[error(transparent)]
168    UtilError(#[from] UtilError),
169
170    #[error(transparent)]
171    TypeError(#[from] TypeError),
172
173    #[error(transparent)]
174    IoError(#[from] std::io::Error),
175
176    #[error("Missing sample argument")]
177    MissingSampleError,
178
179    #[error("Missing sample size argument")]
180    MissingSampleSizeError,
181
182    #[error("Custom alert thresholds have not been set")]
183    CustomThresholdNotSetError,
184
185    #[error("Custom alert threshold not found")]
186    CustomAlertThresholdNotFound,
187
188    #[error("{0}")]
189    PyError(String),
190}
191
192impl From<ProfileError> for PyErr {
193    fn from(err: ProfileError) -> PyErr {
194        let msg = err.to_string();
195        PyRuntimeError::new_err(msg)
196    }
197}
198
199impl From<PyErr> for ProfileError {
200    fn from(err: PyErr) -> ProfileError {
201        ProfileError::PyError(err.to_string())
202    }
203}