1use std::fmt;
4use std::str::FromStr;
5
6use relay_protocol::{Annotated, Empty, Error, FromValue, IntoValue, SkipSerialization, Value};
7use serde::Serialize;
8
9#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
17#[serde(rename_all = "snake_case")]
18#[repr(u8)] pub enum SpanStatus {
20 Ok = 0,
24
25 Cancelled = 1,
27
28 Unknown = 2,
32
33 InvalidArgument = 3,
38
39 DeadlineExceeded = 4,
46
47 NotFound = 5,
49
50 AlreadyExists = 6,
54
55 PermissionDenied = 7,
59
60 ResourceExhausted = 8,
65
66 FailedPrecondition = 9,
69
70 Aborted = 10,
72
73 OutOfRange = 11,
75
76 Unimplemented = 12,
80
81 InternalError = 13,
83
84 Unavailable = 14,
86
87 DataLoss = 15,
89
90 Unauthenticated = 16,
94
95 Error = 17,
101}
102
103impl SpanStatus {
104 pub fn as_str(&self) -> &'static str {
106 match *self {
107 SpanStatus::Ok => "ok",
108 SpanStatus::DeadlineExceeded => "deadline_exceeded",
109 SpanStatus::Unauthenticated => "unauthenticated",
110 SpanStatus::PermissionDenied => "permission_denied",
111 SpanStatus::NotFound => "not_found",
112 SpanStatus::ResourceExhausted => "resource_exhausted",
113 SpanStatus::InvalidArgument => "invalid_argument",
114 SpanStatus::Unimplemented => "unimplemented",
115 SpanStatus::Unavailable => "unavailable",
116 SpanStatus::InternalError => "internal_error",
117 SpanStatus::Unknown => "unknown",
118 SpanStatus::Cancelled => "cancelled",
119 SpanStatus::AlreadyExists => "already_exists",
120 SpanStatus::FailedPrecondition => "failed_precondition",
121 SpanStatus::Aborted => "aborted",
122 SpanStatus::OutOfRange => "out_of_range",
123 SpanStatus::DataLoss => "data_loss",
124 SpanStatus::Error => "error",
125 }
126 }
127}
128
129impl AsRef<str> for SpanStatus {
130 fn as_ref(&self) -> &str {
131 self.as_str()
132 }
133}
134
135#[derive(Clone, Copy, Debug)]
137pub struct ParseSpanStatusError;
138
139impl fmt::Display for ParseSpanStatusError {
140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141 write!(f, "invalid span status")
142 }
143}
144
145impl std::error::Error for ParseSpanStatusError {}
146
147impl FromStr for SpanStatus {
148 type Err = ParseSpanStatusError;
149
150 fn from_str(string: &str) -> Result<SpanStatus, Self::Err> {
151 Ok(match string {
152 "ok" => SpanStatus::Ok,
153 "success" => SpanStatus::Ok, "deadline_exceeded" => SpanStatus::DeadlineExceeded,
155 "unauthenticated" => SpanStatus::Unauthenticated,
156 "permission_denied" => SpanStatus::PermissionDenied,
157 "not_found" => SpanStatus::NotFound,
158 "resource_exhausted" => SpanStatus::ResourceExhausted,
159 "invalid_argument" => SpanStatus::InvalidArgument,
160 "unimplemented" => SpanStatus::Unimplemented,
161 "unavailable" => SpanStatus::Unavailable,
162 "internal_error" | "unknown_error" => SpanStatus::InternalError,
163 "failure" => SpanStatus::InternalError, "unknown" => SpanStatus::Unknown,
165 "cancelled" => SpanStatus::Cancelled,
166 "already_exists" => SpanStatus::AlreadyExists,
167 "failed_precondition" => SpanStatus::FailedPrecondition,
168 "aborted" => SpanStatus::Aborted,
169 "out_of_range" => SpanStatus::OutOfRange,
170 "data_loss" => SpanStatus::DataLoss,
171 "error" => SpanStatus::Error,
172 _ => return Err(ParseSpanStatusError),
173 })
174 }
175}
176
177impl fmt::Display for SpanStatus {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 f.write_str(self.as_str())
180 }
181}
182
183impl Empty for SpanStatus {
184 #[inline]
185 fn is_empty(&self) -> bool {
186 false
187 }
188}
189
190impl FromValue for SpanStatus {
191 fn from_value(value: Annotated<Value>) -> Annotated<Self> {
192 match value {
193 Annotated(Some(Value::String(value)), mut meta) => match value.parse() {
194 Ok(status) => Annotated(Some(status), meta),
195 Err(_) => {
196 meta.add_error(Error::expected("a trace status"));
197 meta.set_original_value(Some(value));
198 Annotated(None, meta)
199 }
200 },
201 Annotated(Some(Value::I64(value)), mut meta) => Annotated(
202 Some(match value {
203 0 => SpanStatus::Ok,
204 1 => SpanStatus::Cancelled,
205 2 => SpanStatus::Unknown,
206 3 => SpanStatus::InvalidArgument,
207 4 => SpanStatus::DeadlineExceeded,
208 5 => SpanStatus::NotFound,
209 6 => SpanStatus::AlreadyExists,
210 7 => SpanStatus::PermissionDenied,
211 8 => SpanStatus::ResourceExhausted,
212 9 => SpanStatus::FailedPrecondition,
213 10 => SpanStatus::Aborted,
214 11 => SpanStatus::OutOfRange,
215 12 => SpanStatus::Unimplemented,
216 13 => SpanStatus::InternalError,
217 14 => SpanStatus::Unavailable,
218 15 => SpanStatus::DataLoss,
219 16 => SpanStatus::Unauthenticated,
220 17 => SpanStatus::Error,
221 _ => {
222 meta.add_error(Error::expected("a trace status"));
223 meta.set_original_value(Some(value));
224 return Annotated(None, meta);
225 }
226 }),
227 meta,
228 ),
229 Annotated(None, meta) => Annotated(None, meta),
230 Annotated(Some(value), mut meta) => {
231 meta.add_error(Error::expected("a string"));
232 meta.set_original_value(Some(value));
233 Annotated(None, meta)
234 }
235 }
236 }
237}
238
239impl IntoValue for SpanStatus {
240 fn into_value(self) -> Value {
241 Value::String(self.to_string())
242 }
243
244 fn serialize_payload<S>(&self, s: S, _behavior: SkipSerialization) -> Result<S::Ok, S::Error>
245 where
246 Self: Sized,
247 S: serde::Serializer,
248 {
249 Serialize::serialize(self.as_str(), s)
250 }
251}