1use std::error::Error as StdError;
11use std::ops::Deref;
12
13use futures::future::SharedError;
14
15use super::Compat;
16use super::Error;
17
18pub struct SlogKVError(pub Error);
20
21impl slog::KV for SlogKVError {
22 fn serialize(
23 &self,
24 _record: &slog::Record<'_>,
25 serializer: &mut dyn slog::Serializer,
26 ) -> slog::Result {
27 let err = &self.0;
28
29 serializer.emit_str(Error.into_str(), &format!("{err}"))?;
30 serializer.emit_str(ErrorDebug.into_str(), &format!("{err:#?}"))?;
31
32 #[cfg(fbcode_build)]
33 {
34 let backtrace = err.backtrace();
35 if let std::backtrace::BacktraceStatus::Captured = backtrace.status() {
36 serializer.emit_str(Backtrace.into_str(), &backtrace.to_string())?;
37 }
38 }
39
40 let mut err = err.deref() as &dyn StdError;
41 while let Some(cause) = cause_workaround(err) {
42 serializer.emit_str(Cause.into_str(), &format!("{cause}"))?;
43 err = cause;
44 }
45 serializer.emit_str(RootCause.into_str(), &format!("{err}"))?;
46
47 Ok(())
48 }
49}
50
51impl slog::KV for SlogKVErrorWithoutBackTrace {
52 fn serialize(
53 &self,
54 _record: &slog::Record<'_>,
55 serializer: &mut dyn slog::Serializer,
56 ) -> slog::Result {
57 let error = &self.0;
58 serializer.emit_str(Error.into_str(), &format!("{error}"))?;
59 serializer.emit_str(ErrorDebug.into_str(), &format!("{error:#?}"))?;
60
61 let mut error = error.deref() as &dyn StdError;
62 while let Some(cause) = cause_workaround(error) {
63 serializer.emit_str(Cause.into_str(), &format!("{cause}"))?;
64 error = cause;
65 }
66 serializer.emit_str(RootCause.into_str(), &format!("{error}"))?;
67
68 Ok(())
69 }
70}
71
72pub struct SlogKVErrorWithoutBackTrace(pub Error);
74
75#[derive(Debug, Clone, Eq, PartialEq)]
77pub enum SlogKVErrorKey {
78 Error,
80 RootCause,
82 Backtrace,
84 Cause,
86 ErrorDebug,
88}
89use crate::SlogKVErrorKey::*;
90
91impl SlogKVErrorKey {
92 pub fn into_str(self) -> &'static str {
94 match self {
95 Error => "error",
96 RootCause => "root_cause",
97 Backtrace => "backtrace",
98 Cause => "cause",
99 ErrorDebug => "error_debug",
100 }
101 }
102}
103
104impl ::std::str::FromStr for SlogKVErrorKey {
105 type Err = ();
106
107 fn from_str(s: &str) -> Result<Self, Self::Err> {
108 match s {
109 "error" => Ok(Error),
110 "root_cause" => Ok(RootCause),
111 "backtrace" => Ok(Backtrace),
112 "cause" => Ok(Cause),
113 "error_debug" => Ok(ErrorDebug),
114 _ => Err(()),
115 }
116 }
117}
118
119pub fn cause_workaround(fail: &dyn StdError) -> Option<&dyn StdError> {
122 let mut cause = fail.source()?;
123 if let Some(shared) = cause.downcast_ref::<SharedError<Compat<Error>>>() {
124 cause = shared.0.deref();
125 }
126 Some(cause)
127}