lambda_runtime/
diagnostic.rs1use serde::{Deserialize, Serialize};
2use std::any::type_name;
3
4use crate::{deserializer::DeserializeError, Error};
5
6#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
42#[serde(rename_all = "camelCase")]
43pub struct Diagnostic {
44 pub error_type: String,
52 pub error_message: String,
56}
57
58impl From<DeserializeError> for Diagnostic {
59 fn from(value: DeserializeError) -> Self {
60 Diagnostic {
61 error_type: type_name_of_val(&value),
62 error_message: value.to_string(),
63 }
64 }
65}
66
67impl From<Error> for Diagnostic {
68 fn from(value: Error) -> Self {
69 Diagnostic {
70 error_type: type_name_of_val(&value),
71 error_message: value.to_string(),
72 }
73 }
74}
75
76impl From<Box<dyn std::error::Error>> for Diagnostic {
77 fn from(value: Box<dyn std::error::Error>) -> Self {
78 Diagnostic {
79 error_type: type_name_of_val(&value),
80 error_message: value.to_string(),
81 }
82 }
83}
84
85impl From<std::convert::Infallible> for Diagnostic {
86 fn from(value: std::convert::Infallible) -> Self {
87 Diagnostic {
88 error_type: type_name_of_val(&value),
89 error_message: value.to_string(),
90 }
91 }
92}
93
94impl From<String> for Diagnostic {
95 fn from(value: String) -> Self {
96 Diagnostic {
97 error_type: type_name_of_val(&value),
98 error_message: value.to_string(),
99 }
100 }
101}
102
103impl From<&'static str> for Diagnostic {
104 fn from(value: &'static str) -> Self {
105 Diagnostic {
106 error_type: type_name_of_val(&value),
107 error_message: value.to_string(),
108 }
109 }
110}
111
112impl From<std::io::Error> for Diagnostic {
113 fn from(value: std::io::Error) -> Self {
114 Diagnostic {
115 error_type: type_name_of_val(&value),
116 error_message: value.to_string(),
117 }
118 }
119}
120
121#[cfg(feature = "anyhow")]
122#[cfg_attr(docsrs, doc(cfg(feature = "anyhow")))]
123impl From<anyhow::Error> for Diagnostic {
124 fn from(value: anyhow::Error) -> Diagnostic {
125 Diagnostic {
126 error_type: type_name_of_val(&value),
127 error_message: value.to_string(),
128 }
129 }
130}
131
132#[cfg(feature = "eyre")]
133#[cfg_attr(docsrs, doc(cfg(feature = "eyre")))]
134impl From<eyre::Report> for Diagnostic {
135 fn from(value: eyre::Report) -> Diagnostic {
136 Diagnostic {
137 error_type: type_name_of_val(&value),
138 error_message: value.to_string(),
139 }
140 }
141}
142
143#[cfg(feature = "miette")]
144#[cfg_attr(docsrs, doc(cfg(feature = "miette")))]
145impl From<miette::Report> for Diagnostic {
146 fn from(value: miette::Report) -> Diagnostic {
147 Diagnostic {
148 error_type: type_name_of_val(&value),
149 error_message: value.to_string(),
150 }
151 }
152}
153
154pub(crate) fn type_name_of_val<T>(_: T) -> String {
155 type_name::<T>().into()
156}
157
158#[cfg(test)]
159mod test {
160 use super::*;
161
162 #[test]
163 fn round_trip_lambda_error() {
164 use serde_json::{json, Value};
165 let expected = json!({
166 "errorType": "InvalidEventDataError",
167 "errorMessage": "Error parsing event data.",
168 });
169
170 let actual = Diagnostic {
171 error_type: "InvalidEventDataError".into(),
172 error_message: "Error parsing event data.".into(),
173 };
174 let actual: Value = serde_json::to_value(actual).expect("failed to serialize diagnostic");
175 assert_eq!(expected, actual);
176 }
177
178 #[cfg(feature = "anyhow")]
179 #[test]
180 fn test_anyhow_integration() {
181 use anyhow::Error as AnyhowError;
182 let error: AnyhowError = anyhow::anyhow!("anyhow error");
183 let diagnostic: Diagnostic = error.into();
184 assert_eq!(diagnostic.error_type, "&anyhow::Error");
185 assert_eq!(diagnostic.error_message, "anyhow error");
186 }
187
188 #[cfg(feature = "eyre")]
189 #[test]
190 fn test_eyre_integration() {
191 use eyre::Report;
192 let error: Report = eyre::eyre!("eyre error");
193 let diagnostic: Diagnostic = error.into();
194 assert_eq!(diagnostic.error_type, "&eyre::Report");
195 assert_eq!(diagnostic.error_message, "eyre error");
196 }
197
198 #[cfg(feature = "miette")]
199 #[test]
200 fn test_miette_integration() {
201 use miette::Report;
202 let error: Report = miette::miette!("miette error");
203 let diagnostic: Diagnostic = error.into();
204 assert_eq!(diagnostic.error_type, "&miette::eyreish::Report");
205 assert_eq!(diagnostic.error_message, "miette error");
206 }
207}