scouter_error/
lib.rs

1use pyo3::create_exception;
2use pyo3::exceptions::PyException;
3use pyo3::PyErr;
4use serde::Deserialize;
5use std::fmt::Display;
6use thiserror::Error;
7use tracing::error;
8
9pub trait TracedError: Display {
10    fn trace(&self) {
11        error!("{}", self);
12    }
13}
14
15#[derive(Error, Debug, Deserialize, PartialEq)]
16pub enum TypeError {
17    #[error("Missing attribute: {0}")]
18    MissingAttribute(String),
19
20    #[error("Failed to extract data: {0}")]
21    ExtractionError(String),
22
23    #[error("Failed to construct TimeInterval {0}")]
24    TimeIntervalError(String),
25
26    #[error("{0}")]
27    DowncastError(String),
28
29    #[error("Failed to convert: {0}")]
30    ConversionError(String),
31
32    #[error("Type not supported: {0}")]
33    TypeNotSupported(String),
34}
35
36impl From<TypeError> for PyErr {
37    fn from(err: TypeError) -> PyErr {
38        PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(err.to_string())
39    }
40}
41
42// add tracing trait to ScouterError
43
44#[derive(Error, Debug, Deserialize, PartialEq)]
45pub enum UtilError {
46    #[error("Failed to parse cron expression: {0}")]
47    ParseCronError(String),
48
49    #[error("Failed to serialize: {0}")]
50    SerializeError(String),
51
52    #[error("Failed to deserialize: {0}")]
53    DeSerializeError(String),
54
55    #[error("Failed to decode base64-encoded string: {0}")]
56    DecodeBase64Error(String),
57
58    #[error("Failed to convert string to Utf-8: {0}")]
59    ConvertUtf8Error(String),
60
61    #[error("Failed to set log level: {0}")]
62    SetLogLevelError(String),
63
64    #[error("Failed to get parent path")]
65    GetParentPathError,
66
67    #[error("Failed to create directory")]
68    CreateDirectoryError,
69
70    #[error("Failed to write to file")]
71    WriteError,
72
73    #[error("Failed to read to file")]
74    ReadError,
75}
76
77impl TracedError for UtilError {}
78
79impl UtilError {
80    pub fn traced_parse_cron_error(err: impl Display) -> Self {
81        let error = Self::ParseCronError(err.to_string());
82        error.trace();
83        error
84    }
85
86    pub fn traced_serialize_error(err: impl Display) -> Self {
87        let error = Self::SerializeError(err.to_string());
88        error.trace();
89        error
90    }
91
92    pub fn traced_deserialize_error(err: impl Display) -> Self {
93        let error = Self::DeSerializeError(err.to_string());
94        error.trace();
95        error
96    }
97
98    pub fn traced_set_log_level_error(err: impl Display) -> Self {
99        let error = Self::SetLogLevelError(err.to_string());
100        error.trace();
101        error
102    }
103
104    pub fn traced_decode_base64_error(err: impl Display) -> Self {
105        let error = Self::DecodeBase64Error(err.to_string());
106        error.trace();
107        error
108    }
109
110    pub fn traced_convert_utf8_error(err: impl Display) -> Self {
111        let error = Self::ConvertUtf8Error(err.to_string());
112        error.trace();
113        error
114    }
115}
116
117#[derive(Error, Debug, Deserialize, PartialEq)]
118pub enum StorageError {
119    #[error("Failed to create object store: {0}")]
120    ObjectStoreError(String),
121
122    #[error("Failed to create storage: {0}")]
123    StorageError(String),
124
125    #[error("Failed to create file system: {0}")]
126    FileSystemError(String),
127
128    #[error("Failed to create file: {0}")]
129    FileError(String),
130
131    #[error("Failed to create directory: {0}")]
132    DirectoryError(String),
133
134    #[error("Failed to write to file: {0}")]
135    WriteError(String),
136
137    #[error("Failed to read from file: {0}")]
138    ReadError(String),
139
140    #[error(transparent)]
141    UtilError(#[from] UtilError),
142}
143
144#[derive(Error, Debug)]
145pub enum ProfilerError {
146    #[error("Quantile error: {0}")]
147    QuantileError(String),
148
149    #[error("Error calculating mean")]
150    MeanError,
151
152    #[error("Compute error: {0}")]
153    ComputeError(String),
154
155    #[error("Failed to compute string statistics: {0}")]
156    StringStatsError(String),
157
158    #[error("Failed to create feature map: {0}")]
159    FeatureMapError(String),
160
161    #[error("Failed to convert: {0}")]
162    ConversionError(String),
163
164    #[error("Failed to create string profile: {0}")]
165    StringProfileError(String),
166
167    // array concatenation error
168    #[error("Failed to concatenate arrays: {0}")]
169    ConcatenateError(String),
170}
171
172impl TracedError for ProfilerError {}
173
174impl ProfilerError {
175    pub fn traced_string_stats_error(err: impl Display) -> Self {
176        let error = Self::StringStatsError(err.to_string());
177        error.trace();
178        error
179    }
180
181    pub fn traced_concatenate_error(err: impl Display) -> Self {
182        let error = Self::ConcatenateError(err.to_string());
183        error.trace();
184        error
185    }
186}
187
188#[derive(Error, Debug, Deserialize, PartialEq)]
189pub enum FeatureQueueError {
190    #[error("{0}")]
191    InvalidFormatError(String),
192
193    #[error("Failed to create drift record: {0}")]
194    DriftRecordError(String),
195
196    #[error("Failed to create alert record: {0}")]
197    AlertRecordError(String),
198
199    #[error("Failed to get feature")]
200    GetFeatureError,
201
202    #[error("Missing feature map")]
203    MissingFeatureMapError,
204
205    #[error("invalid data type detected for feature: {0}")]
206    InvalidFeatureTypeError(String),
207
208    #[error("invalid value detected for feature: {0}, error: {1}")]
209    InvalidValueError(String, String),
210
211    #[error("Failed to get bin given bin id")]
212    GetBinError,
213}
214
215// impl From for PyErr
216
217impl From<FeatureQueueError> for PyErr {
218    fn from(err: FeatureQueueError) -> PyErr {
219        PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(err.to_string())
220    }
221}
222
223#[derive(Error, Debug, PartialEq)]
224pub enum SqlError {
225    #[error("Failed to run sql migrations: {0}")]
226    MigrationError(String),
227
228    #[error("Failed to run sql query: {0}")]
229    QueryError(String),
230
231    #[error("Failed to parse version: {0}")]
232    VersionError(String),
233
234    #[error("File error: {0}")]
235    FileError(String),
236
237    #[error("Failed to connect to the database - {0}")]
238    ConnectionError(String),
239
240    #[error("Failed to update drift profile: {0}")]
241    UpdateDriftProfileError(String),
242
243    #[error("Failed to get bin proportions: {0}")]
244    GetBinProportionsError(String),
245
246    #[error("Failed to get custom metrics: {0}")]
247    GetCustomMetricsError(String),
248
249    #[error("Failed to get insert metrics: {0}")]
250    InsertCustomMetricsError(String),
251
252    #[error("Invalid record type: {0}")]
253    InvalidRecordTypeError(String),
254
255    #[error("Failed to get entities: {0}")]
256    GetEntitiesError(String),
257
258    #[error("Failed to get entity data: {0}")]
259    GetEntityDataError(String),
260
261    #[error("Failed to get features: {0}")]
262    GetFeaturesError(String),
263
264    #[error("Failed to get next run: {0}")]
265    GetNextRunError(String),
266
267    #[error("Failed to get drift task: {0}")]
268    GetDriftTaskError(String),
269
270    #[error(transparent)]
271    UtilError(#[from] UtilError),
272
273    #[error(transparent)]
274    DataFrameError(#[from] DataFrameError),
275
276    #[error("Failed to extract value {0} {1}")]
277    FailedToExtractError(String, String),
278
279    #[error("Invalid date range: {0}")]
280    InvalidDateRangeError(String),
281
282    #[error("Failed to convert dataframe: {0}")]
283    FailedToConvertDataFrameError(String),
284}
285
286impl TracedError for SqlError {}
287
288impl SqlError {
289    pub fn traced_query_error(err: impl Display) -> Self {
290        let error = Self::QueryError(err.to_string());
291        error.trace();
292        error
293    }
294
295    pub fn traced_update_drift_profile_error(err: impl Display) -> Self {
296        let error = Self::UpdateDriftProfileError(err.to_string());
297        error.trace();
298        error
299    }
300
301    pub fn traced_get_bin_proportions_error(err: impl Display) -> Self {
302        let error = Self::GetBinProportionsError(err.to_string());
303        error.trace();
304        error
305    }
306
307    pub fn traced_get_custom_metrics_error(err: impl Display) -> Self {
308        let error = Self::GetCustomMetricsError(err.to_string());
309        error.trace();
310        error
311    }
312
313    pub fn traced_insert_custom_metrics_error(err: impl Display) -> Self {
314        let error = Self::InsertCustomMetricsError(err.to_string());
315        error.trace();
316        error
317    }
318
319    pub fn traced_invalid_record_type_error(err: impl Display) -> Self {
320        let error = Self::InvalidRecordTypeError(err.to_string());
321        error.trace();
322        error
323    }
324
325    pub fn traced_get_entities_error(err: impl Display) -> Self {
326        let error = Self::GetEntitiesError(err.to_string());
327        error.trace();
328        error
329    }
330
331    pub fn traced_get_entity_data_error(err: impl Display) -> Self {
332        let error = Self::GetEntityDataError(err.to_string());
333        error.trace();
334        error
335    }
336
337    pub fn traced_get_features_error(err: impl Display) -> Self {
338        let error = Self::GetFeaturesError(err.to_string());
339        error.trace();
340        error
341    }
342
343    pub fn traced_get_next_run_error(err: impl Display) -> Self {
344        let error = Self::GetNextRunError(err.to_string());
345        error.trace();
346        error
347    }
348
349    pub fn traced_get_drift_task_error(err: impl Display) -> Self {
350        let error = Self::GetDriftTaskError(err.to_string());
351        error.trace();
352        error
353    }
354
355    pub fn traced_failed_to_extract_error(err: impl Display, field: impl Display) -> Self {
356        let error = Self::FailedToExtractError(field.to_string(), err.to_string());
357        error.trace();
358        error
359    }
360
361    pub fn traced_connection_error(err: impl Display) -> Self {
362        let error = Self::ConnectionError(err.to_string());
363        error.trace();
364        error
365    }
366
367    pub fn traced_failed_to_convert_dataframe_error(err: impl Display) -> Self {
368        let error = Self::FailedToConvertDataFrameError(err.to_string());
369        error.trace();
370        error
371    }
372}
373
374#[derive(Error, Debug, Deserialize)]
375pub enum AlertError {
376    #[error("Error: {0}")]
377    GeneralError(String),
378
379    #[error("Failed to create alert: {0}")]
380    CreateError(String),
381
382    #[error("{0}")]
383    DriftError(String),
384}
385
386#[derive(Error, Debug, PartialEq)]
387pub enum DataFrameError {
388    #[error("Failed to read batch: {0}")]
389    ReadBatchError(String),
390
391    #[error("Failed to create batch: {0}")]
392    CreateBatchError(String),
393
394    #[error(transparent)]
395    StorageError(#[from] StorageError),
396
397    #[error(transparent)]
398    DriftError(#[from] DriftError),
399
400    #[error("Failed to add year column: {0}")]
401    AddYearColumnError(String),
402
403    #[error("Failed to add month column: {0}")]
404    AddMonthColumnError(String),
405
406    #[error("Failed to add day column: {0}")]
407    AddDayColumnError(String),
408
409    #[error("Failed to add hour column: {0}")]
410    AddHourColumnError(String),
411
412    #[error("Failed to write to parquet: {0}")]
413    WriteParquetError(String),
414
415    #[error("Failed to parse table path: {0}")]
416    ParseTablePathError(String),
417
418    #[error("Failed to infer schema: {0}")]
419    InferSchemaError(String),
420
421    #[error("Failed to create listing table: {0}")]
422    CreateListingTableError(String),
423
424    #[error("Failed to register table: {0}")]
425    RegisterTableError(String),
426
427    #[error("Invalid record type: {0}")]
428    InvalidRecordTypeError(String),
429
430    #[error("Downcast error: {0}")]
431    DowncastError(String),
432
433    #[error("Failed to get column: {0}")]
434    GetColumnError(String),
435
436    #[error("Missing field: {0}")]
437    MissingFieldError(String),
438}
439
440impl TracedError for DataFrameError {}
441
442impl DataFrameError {
443    pub fn traced_read_batch_error(err: impl Display) -> Self {
444        let error = Self::ReadBatchError(err.to_string());
445        error.trace();
446        error
447    }
448
449    pub fn traced_create_batch_error(err: impl Display) -> Self {
450        let error = Self::CreateBatchError(err.to_string());
451        error.trace();
452        error
453    }
454
455    pub fn traced_add_year_column_error(err: impl Display) -> Self {
456        let error = Self::AddYearColumnError(err.to_string());
457        error.trace();
458        error
459    }
460    pub fn traced_add_month_column_error(err: impl Display) -> Self {
461        let error = Self::AddMonthColumnError(err.to_string());
462        error.trace();
463        error
464    }
465    pub fn traced_add_day_column_error(err: impl Display) -> Self {
466        let error = Self::AddDayColumnError(err.to_string());
467        error.trace();
468        error
469    }
470    pub fn traced_add_hour_column_error(err: impl Display) -> Self {
471        let error = Self::AddHourColumnError(err.to_string());
472        error.trace();
473        error
474    }
475
476    pub fn traced_write_parquet_error(err: impl Display) -> Self {
477        let error = Self::WriteParquetError(err.to_string());
478        error.trace();
479        error
480    }
481
482    pub fn traced_parse_table_path_error(err: impl Display) -> Self {
483        let error = Self::ParseTablePathError(err.to_string());
484        error.trace();
485        error
486    }
487    pub fn traced_infer_schema_error(err: impl Display) -> Self {
488        let error = Self::InferSchemaError(err.to_string());
489        error.trace();
490        error
491    }
492
493    pub fn traced_create_listing_table_error(err: impl Display) -> Self {
494        let error = Self::CreateListingTableError(err.to_string());
495        error.trace();
496        error
497    }
498    pub fn traced_register_table_error(err: impl Display) -> Self {
499        let error = Self::RegisterTableError(err.to_string());
500        error.trace();
501        error
502    }
503
504    pub fn traced_invalid_record_type_error(err: impl Display) -> Self {
505        let error = Self::InvalidRecordTypeError(err.to_string());
506        error.trace();
507        error
508    }
509
510    pub fn traced_downcast_error(err: impl Display) -> Self {
511        let error = Self::DowncastError(err.to_string());
512        error.trace();
513        error
514    }
515
516    pub fn traced_get_column_error(err: impl Display) -> Self {
517        let error = Self::GetColumnError(err.to_string());
518        error.trace();
519        error
520    }
521}
522
523#[derive(Error, Debug, PartialEq)]
524pub enum DriftError {
525    #[error("Error: {0}")]
526    Error(String),
527
528    #[error("Failed to create rule. Rule must be of length 8")]
529    RuleLengthError,
530
531    #[error(transparent)]
532    ParseIntError(#[from] std::num::ParseIntError),
533
534    #[error("Failed to compute - {0}")]
535    ComputeError(String),
536
537    #[error("Failed to shape array: {0}")]
538    ShapeError(String),
539
540    #[error("Missing feature {0}")]
541    MissingFeatureError(String),
542
543    #[error("Features missing from feature map")]
544    MissingFeaturesError,
545
546    #[error("Failed to sample data {0}")]
547    SampleDataError(String),
548
549    #[error("Failed to set control value: {0}")]
550    SetControlValueError(String),
551
552    #[error("Features and array are not the same length")]
553    FeatureArrayLengthError,
554
555    #[error("Failed to create bins - {0}")]
556    CreateBinsError(String),
557
558    #[error(
559        "Feature mismatch, feature '{0}' not found. Available features in the drift profile: {1}"
560    )]
561    FeatureMismatchError(String, String),
562
563    // array concantenation error
564    #[error("Failed to concatenate arrays: {0}")]
565    ConcatenateError(String),
566
567    // invalid config
568    #[error("Invalid config: {0}")]
569    InvalidConfigError(String),
570
571    // invalid drift type
572    #[error("Invalid drift type")]
573    InvalidDriftTypeError,
574}
575
576impl TracedError for DriftError {}
577
578impl DriftError {
579    pub fn raise<T>(self) -> Result<T, Self> {
580        self.trace();
581        Err(self)
582    }
583
584    pub fn traced_rule_length_error() -> Self {
585        let error = Self::RuleLengthError;
586        error.trace();
587        error
588    }
589
590    pub fn traced_compute_error(err: impl Display) -> Self {
591        let error = Self::ComputeError(err.to_string());
592        error.trace();
593        error
594    }
595
596    pub fn traced_shape_error(err: impl Display) -> Self {
597        let error = Self::ShapeError(err.to_string());
598        error.trace();
599        error
600    }
601
602    pub fn traced_missing_feature_error(err: impl Display) -> Self {
603        let error = Self::MissingFeatureError(err.to_string());
604        error.trace();
605        error
606    }
607
608    pub fn traced_sample_data_error(err: impl Display) -> Self {
609        let error = Self::SampleDataError(err.to_string());
610        error.trace();
611        error
612    }
613
614    pub fn traced_set_control_value_error(err: impl Display) -> Self {
615        let error = Self::SetControlValueError(err.to_string());
616        error.trace();
617        error
618    }
619
620    pub fn traced_feature_length_error() -> Self {
621        let error = Self::FeatureArrayLengthError;
622        error.trace();
623        error
624    }
625
626    pub fn traced_missing_features_error() -> Self {
627        let error = Self::MissingFeaturesError;
628        error.trace();
629        error
630    }
631
632    pub fn traced_create_bins_error(err: impl Display) -> Self {
633        let error = Self::CreateBinsError(err.to_string());
634        error.trace();
635        error
636    }
637
638    pub fn traced_feature_mismatch_error(feature: impl Display, available: impl Display) -> Self {
639        let error = Self::FeatureMismatchError(feature.to_string(), available.to_string());
640        error.trace();
641        error
642    }
643}
644
645#[derive(Error, Debug, PartialEq)]
646pub enum ClientError {
647    #[error("Failed to get JWT token: {0}")]
648    FailedToGetJwtToken(String),
649
650    #[error("Failed to parse JWT token: {0}")]
651    FailedToParseJwtToken(String),
652
653    #[error("Failed to send request: {0}")]
654    FailedToSendRequest(String),
655
656    #[error("Failed to get response: {0}")]
657    FailedToGetResponse(String),
658
659    #[error("Failed to serialize: {0}")]
660    FailedToSerialize(String),
661
662    #[error("Failed to deserialize: {0}")]
663    FailedToDeserialize(String),
664
665    #[error("Failed to create header: {0}")]
666    FailedToCreateHeader(String),
667
668    #[error("Failed to create client: {0}")]
669    FailedToCreateClient(String),
670
671    #[error("Unauthorized")]
672    Unauthorized,
673
674    #[error(transparent)]
675    SqlError(#[from] SqlError),
676}
677
678impl TracedError for ClientError {}
679
680impl ClientError {
681    pub fn traced_jwt_error(err: impl Display) -> Self {
682        let error = ClientError::FailedToGetJwtToken(err.to_string());
683        error.trace();
684        error
685    }
686
687    pub fn traced_parse_jwt_error(err: impl Display) -> Self {
688        let error = ClientError::FailedToParseJwtToken(err.to_string());
689        error.trace();
690        error
691    }
692
693    pub fn traced_request_error(err: impl Display) -> Self {
694        let error = ClientError::FailedToSendRequest(err.to_string());
695        error.trace();
696        error
697    }
698
699    pub fn traced_unauthorized_error() -> Self {
700        let error = ClientError::Unauthorized;
701        error.trace();
702        error
703    }
704
705    pub fn traced_serialize_error(err: impl Display) -> Self {
706        let error = Self::FailedToSerialize(err.to_string());
707        error.trace();
708        error
709    }
710
711    pub fn traced_deserialize_error(err: impl Display) -> Self {
712        let error = Self::FailedToDeserialize(err.to_string());
713        error.trace();
714        error
715    }
716
717    pub fn traced_create_header_error(err: impl Display) -> Self {
718        let error = Self::FailedToCreateHeader(err.to_string());
719        error.trace();
720        error
721    }
722
723    pub fn traced_create_client_error(err: impl Display) -> Self {
724        let error = Self::FailedToCreateClient(err.to_string());
725        error.trace();
726        error
727    }
728}
729
730#[derive(Error, Debug, PartialEq)]
731pub enum EventError {
732    #[error("Failed to connect: {0}")]
733    ConnectionError(String),
734
735    #[error("Failed to create channel: {0}")]
736    ChannelError(String),
737
738    #[error("Failed to setup queue: {0}")]
739    DeclareQueueError(String),
740
741    #[error("Failed to publish message: {0}")]
742    PublishError(String),
743
744    #[error("Failed to consume message: {0}")]
745    ConsumeError(String),
746
747    #[error("Failed to flush message: {0}")]
748    FlushError(String),
749
750    #[error("Failed to send message: {0}")]
751    SendError(String),
752
753    #[error(transparent)]
754    UtilError(#[from] UtilError),
755
756    #[error(transparent)]
757    ClientError(#[from] ClientError),
758
759    #[error(transparent)]
760    SqlError(#[from] SqlError),
761
762    #[error(transparent)]
763    FeatureQueueError(#[from] FeatureQueueError),
764
765    #[error(transparent)]
766    TypeError(#[from] TypeError),
767
768    #[error("Invalid compression type")]
769    InvalidCompressionTypeError,
770
771    #[error("Subscribe error: {0}")]
772    SubscribeError(String),
773
774    #[error("Failed to setup qos: {0}")]
775    SetupQosError(String),
776
777    #[error("Failed to setup consumer: {0}")]
778    SetupConsumerError(String),
779
780    #[error("Failed to setup runtime: {0}")]
781    SetupRuntimeError(String),
782
783    #[error("Failed to insert record: {0}")]
784    InsertRecordError(String),
785
786    #[error("Queue is full, failed to push item")]
787    QueueFullError,
788
789    #[error("Failed to create send entity to consumer: {0}")]
790    SendEntityError(String),
791}
792
793impl TracedError for EventError {}
794
795impl EventError {
796    pub fn queue_push_error<T>(_item: T) -> Self {
797        // If you need the item, store it in the error variant
798        // Otherwise just return the error type
799        EventError::QueueFullError
800    }
801
802    pub fn traced_connection_error(err: impl Display) -> Self {
803        let error = Self::ConnectionError(err.to_string());
804        error.trace();
805        error
806    }
807
808    pub fn traced_channel_error(err: impl Display) -> Self {
809        let error = Self::ChannelError(err.to_string());
810        error.trace();
811        error
812    }
813
814    pub fn traced_declare_queue_error(err: impl Display) -> Self {
815        let error = Self::DeclareQueueError(err.to_string());
816        error.trace();
817        error
818    }
819
820    pub fn traced_publish_error(err: impl Display) -> Self {
821        let error = Self::PublishError(err.to_string());
822        error.trace();
823        error
824    }
825    pub fn traced_consume_error(err: impl Display) -> Self {
826        let error = Self::ConsumeError(err.to_string());
827        error.trace();
828        error
829    }
830    pub fn traced_flush_error(err: impl Display) -> Self {
831        let error = Self::FlushError(err.to_string());
832        error.trace();
833        error
834    }
835
836    pub fn traced_send_error(err: impl Display) -> Self {
837        let error = Self::SendError(err.to_string());
838        error.trace();
839        error
840    }
841
842    pub fn traced_subscribe_error(err: impl Display) -> Self {
843        let error = Self::SubscribeError(err.to_string());
844        error.trace();
845        error
846    }
847
848    pub fn traced_setup_qos_error(err: impl Display) -> Self {
849        let error = Self::SetupQosError(err.to_string());
850        error.trace();
851        error
852    }
853
854    pub fn traced_setup_runtime_error(err: impl Display) -> Self {
855        let error = Self::SetupConsumerError(err.to_string());
856        error.trace();
857        error
858    }
859
860    pub fn traced_insert_record_error(err: impl Display) -> Self {
861        let error = Self::InsertRecordError(err.to_string());
862        error.trace();
863        error
864    }
865}
866
867/// THis should be the top-level error that all other errors are converted to
868#[derive(Error, Debug)]
869pub enum ScouterError {
870    #[error("Failed to serialize string")]
871    SerializeError,
872
873    #[error("Failed to deserialize string")]
874    DeSerializeError,
875
876    #[error("Failed to create path")]
877    CreatePathError,
878
879    #[error("Missing feature map")]
880    MissingFeatureMapError,
881
882    #[error("Failed to create string profile: {0}")]
883    StringProfileError(String),
884
885    #[error("Invalid drift type: {0}")]
886    InvalidDriftTypeError(String),
887
888    #[error("Shape mismatch: {0}")]
889    ShapeMismatchError(String),
890
891    #[error("{0}")]
892    FeatureError(String),
893
894    #[error("{0}")]
895    Error(String),
896
897    #[error(transparent)]
898    AlertError(#[from] AlertError),
899
900    #[error(transparent)]
901    CustomError(#[from] CustomMetricError),
902
903    #[error(transparent)]
904    FeatureQueueError(#[from] FeatureQueueError),
905
906    #[error(transparent)]
907    SqlError(#[from] SqlError),
908
909    #[error(transparent)]
910    DriftError(#[from] DriftError),
911
912    #[error(transparent)]
913    StorageError(#[from] StorageError),
914
915    #[error(transparent)]
916    ClientError(#[from] ClientError),
917
918    #[error(transparent)]
919    ProfileError(#[from] ProfilerError),
920
921    #[error(transparent)]
922    DataFrameError(#[from] DataFrameError),
923
924    #[error(transparent)]
925    EventError(#[from] EventError),
926
927    #[error(transparent)]
928    UtilError(#[from] UtilError),
929
930    #[error(transparent)]
931    TypeError(#[from] TypeError),
932
933    #[error("Missing value in map")]
934    MissingValue,
935
936    #[error("Empty ServerRecordsError")]
937    EmptyServerRecordsError,
938
939    // rabbitmq
940
941    // downcast error
942    #[error("Failed to downcast: {0}")]
943    FailedToDowncast(String),
944
945    // unsupported data type
946    #[error("Unsupported data type: {0}")]
947    UnsupportedDataType(String),
948
949    // data is not numpy
950    #[error("Data is not a numpy array")]
951    DataNotNumpy,
952
953    // column names must be strings
954    #[error("Column names must be string type")]
955    ColumnNamesMustBeStrings,
956
957    #[error("Failed to get queue for alias. Check that it exists: {0}")]
958    MissingQueueError(String),
959
960    #[error("Failed to bind queue to python: {0}")]
961    BindError(String),
962
963    #[error("Failed to create queue: {0}")]
964    QueueCreateError(String),
965
966    #[error("Failed to shutdown queue: {0}")]
967    QueueShutdownError(String),
968}
969
970impl TracedError for ScouterError {}
971
972// add a raise method so that each error is traced before being returned
973impl ScouterError {
974    pub fn raise<T>(self) -> Result<T, Self> {
975        self.trace();
976        Err(self)
977    }
978
979    pub fn traced_downcast_error(err: impl Display) -> Self {
980        let error = Self::FailedToDowncast(err.to_string());
981        error.trace();
982        error
983    }
984
985    pub fn traced_unsupported_data_type_error(err: impl Display) -> Self {
986        let error = Self::UnsupportedDataType(err.to_string());
987        error.trace();
988        error
989    }
990
991    pub fn traced_data_not_numpy_error() -> Self {
992        let error = Self::DataNotNumpy;
993        error.trace();
994        error
995    }
996}
997
998// impl From for PyErr
999
1000impl From<std::io::Error> for ScouterError {
1001    fn from(err: std::io::Error) -> ScouterError {
1002        ScouterError::Error(err.to_string())
1003    }
1004}
1005
1006impl From<PyErr> for ScouterError {
1007    fn from(err: PyErr) -> ScouterError {
1008        ScouterError::Error(err.to_string())
1009    }
1010}
1011
1012impl From<ScouterError> for PyErr {
1013    fn from(err: ScouterError) -> PyErr {
1014        PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(err.to_string())
1015    }
1016}
1017
1018#[derive(Error, Debug)]
1019pub enum DispatchError {
1020    #[error("{0}")]
1021    OpsGenieError(String),
1022
1023    #[error("{0}")]
1024    SlackError(String),
1025
1026    #[error("{0}")]
1027    HttpError(String),
1028
1029    #[error("Error processing alerts: {0}")]
1030    AlertProcessError(String),
1031
1032    #[error("Error setting alerter: {0}")]
1033    AlerterError(String),
1034}
1035
1036#[derive(Error, Debug, Deserialize)]
1037pub enum ObserverError {
1038    #[error("Route not found {0}")]
1039    RouteNotFound(String),
1040
1041    #[error("Failed to update route metrics: {0}")]
1042    UpdateMetricsError(String),
1043
1044    #[error("Failed to compute quantiles: {0}")]
1045    QuantileError(String),
1046
1047    #[error("Failed to collect metrics: {0}")]
1048    CollectMetricsError(String),
1049}
1050
1051impl From<ObserverError> for PyErr {
1052    fn from(err: ObserverError) -> PyErr {
1053        PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(err.to_string())
1054    }
1055}
1056
1057#[derive(Error, Debug, Deserialize)]
1058pub enum CustomMetricError {
1059    #[error("Cannot create metric profile, no metrics were provided")]
1060    NoMetricsError,
1061
1062    #[error("{0}")]
1063    Error(String),
1064}
1065
1066impl From<CustomMetricError> for PyErr {
1067    fn from(err: CustomMetricError) -> PyErr {
1068        PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(err.to_string())
1069    }
1070}
1071
1072#[derive(Error, Debug, Deserialize)]
1073pub enum ConfigError {
1074    #[error("{0}")]
1075    Error(String),
1076}
1077
1078#[derive(Error, Debug, Deserialize)]
1079pub enum LoggingError {
1080    #[error("{0}")]
1081    Error(String),
1082}
1083
1084#[derive(Error, Debug)]
1085pub enum AuthError {
1086    #[error("Invalid username provided")]
1087    InvalidUser,
1088
1089    #[error("Invalid password provided")]
1090    InvalidPassword,
1091
1092    #[error("Session timeout for user occured")]
1093    SessionTimeout,
1094
1095    #[error("JWT token provided is invalid")]
1096    InvalidJwtToken,
1097
1098    #[error("Refresh token is invalid")]
1099    InvalidRefreshToken,
1100}
1101
1102create_exception!(scouter, PyScouterError, PyException);