burn_train/metric/processor/
error.rs1use burn_core::tensor::TensorReadError;
2use burn_std::ExecutionError;
3
4use crate::metric::{MetricName, store::Split};
5
6#[derive(Debug)]
8pub struct MetricError {
9 pub metric: MetricName,
11 pub split: Split,
13 pub source: TensorReadError,
15}
16
17impl core::fmt::Display for MetricError {
18 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19 match &self.split {
20 Split::Test(Some(name)) => write!(f, "test/{name}/{}: {}", self.metric, self.source),
21 split => write!(f, "{split}/{}: {}", self.metric, self.source),
22 }
23 }
24}
25
26impl core::error::Error for MetricError {
27 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
28 Some(&self.source)
29 }
30}
31
32#[derive(Debug)]
34pub enum EventProcessorFailure {
35 Metric(MetricError),
37 Sync {
39 split: Split,
41 source: ExecutionError,
43 },
44}
45
46impl EventProcessorFailure {
47 pub fn is_device_poisoned(&self) -> bool {
49 match self {
50 Self::Metric(error) => {
51 matches!(&error.source, TensorReadError::Execution(err) if err.is_device_poisoned())
52 }
53 Self::Sync { source, .. } => source.is_device_poisoned(),
54 }
55 }
56}
57
58impl core::fmt::Display for EventProcessorFailure {
59 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60 match self {
61 Self::Metric(error) => write!(f, "{error}"),
62 Self::Sync {
63 split: Split::Test(Some(name)),
64 source,
65 } => write!(f, "test/{name}: the event could not be synced: {source}"),
66 Self::Sync { split, source } => {
67 write!(f, "{split}: the event could not be synced: {source}")
68 }
69 }
70 }
71}
72
73impl core::error::Error for EventProcessorFailure {
74 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
75 match self {
76 Self::Metric(error) => Some(error),
77 Self::Sync { source, .. } => Some(source),
78 }
79 }
80}
81
82impl From<MetricError> for EventProcessorFailure {
83 fn from(error: MetricError) -> Self {
84 Self::Metric(error)
85 }
86}
87
88#[derive(Debug)]
90pub struct EventProcessorError {
91 failures: Vec<EventProcessorFailure>,
92}
93
94impl EventProcessorError {
95 pub(crate) fn from_errors(errors: Vec<MetricError>) -> Result<(), Self> {
97 match errors.is_empty() {
98 true => Ok(()),
99 false => Err(Self {
100 failures: errors
101 .into_iter()
102 .map(EventProcessorFailure::Metric)
103 .collect(),
104 }),
105 }
106 }
107
108 pub(crate) fn sync(split: Split, source: ExecutionError) -> Self {
110 Self {
111 failures: vec![EventProcessorFailure::Sync { split, source }],
112 }
113 }
114
115 pub(crate) fn merge(&mut self, other: Self) {
117 self.failures.extend(other.failures);
118 }
119
120 pub fn failures(&self) -> &[EventProcessorFailure] {
122 &self.failures
123 }
124
125 pub fn into_failures(self) -> Vec<EventProcessorFailure> {
127 self.failures
128 }
129
130 pub fn is_device_poisoned(&self) -> bool {
132 self.failures
133 .iter()
134 .any(EventProcessorFailure::is_device_poisoned)
135 }
136}
137
138impl core::fmt::Display for EventProcessorError {
139 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
140 match self.failures.as_slice() {
141 [failure] => write!(f, "Event processing failed: {failure}"),
142 failures => {
143 write!(f, "Event processing failed {} times:", failures.len())?;
144 for failure in failures {
145 write!(f, "\n {failure}")?;
146 }
147 Ok(())
148 }
149 }
150 }
151}
152
153impl core::error::Error for EventProcessorError {}