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