console_api/
common.rs

1use std::fmt;
2
3pub use generated::*;
4
5mod generated {
6    #![allow(warnings)]
7    include!("generated/rs.tokio.console.common.rs");
8}
9
10impl From<tracing_core::Level> for metadata::Level {
11    fn from(level: tracing_core::Level) -> Self {
12        match level {
13            tracing_core::Level::ERROR => metadata::Level::Error,
14            tracing_core::Level::WARN => metadata::Level::Warn,
15            tracing_core::Level::INFO => metadata::Level::Info,
16            tracing_core::Level::DEBUG => metadata::Level::Debug,
17            tracing_core::Level::TRACE => metadata::Level::Trace,
18        }
19    }
20}
21
22impl From<tracing_core::metadata::Kind> for metadata::Kind {
23    fn from(kind: tracing_core::metadata::Kind) -> Self {
24        // /!\ Note that this is intentionally *not* implemented using match.
25        // The `metadata::Kind` struct in `tracing_core` was written not
26        // intending to allow exhaustive matches, but accidentally did.
27        //
28        // Therefore, we shouldn't be able to write a match against both
29        // variants without a wildcard arm. However, on versions of
30        // `tracing_core` where the type was exhaustively matchable, a wildcard
31        // arm will result in a warning. Thus we must write this rather
32        // tortured-looking `if` statement to get non-exhaustive matching
33        // behavior.
34        if kind == tracing_core::metadata::Kind::SPAN {
35            metadata::Kind::Span
36        } else {
37            metadata::Kind::Event
38        }
39    }
40}
41
42impl<'a> From<&'a tracing_core::Metadata<'a>> for Metadata {
43    fn from(meta: &'a tracing_core::Metadata<'a>) -> Self {
44        let kind = if meta.is_span() {
45            metadata::Kind::Span
46        } else {
47            debug_assert!(meta.is_event());
48            metadata::Kind::Event
49        };
50
51        let field_names = meta.fields().iter().map(|f| f.name().to_string()).collect();
52        Metadata {
53            name: meta.name().to_string(),
54            target: meta.target().to_string(),
55            location: Some(meta.into()),
56            kind: kind as i32,
57            level: metadata::Level::from(*meta.level()) as i32,
58            field_names,
59            ..Default::default()
60        }
61    }
62}
63
64impl<'a> From<&'a tracing_core::Metadata<'a>> for Location {
65    fn from(meta: &'a tracing_core::Metadata<'a>) -> Self {
66        Location {
67            file: meta.file().map(String::from),
68            module_path: meta.module_path().map(String::from),
69            line: meta.line(),
70            column: None, // tracing doesn't support columns yet
71        }
72    }
73}
74
75impl<'a> From<&'a std::panic::Location<'a>> for Location {
76    fn from(loc: &'a std::panic::Location<'a>) -> Self {
77        Location {
78            file: Some(loc.file().to_string()),
79            line: Some(loc.line()),
80            column: Some(loc.column()),
81            ..Default::default()
82        }
83    }
84}
85
86impl fmt::Display for field::Value {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        match self {
89            field::Value::BoolVal(v) => fmt::Display::fmt(v, f)?,
90            field::Value::StrVal(v) => fmt::Display::fmt(v, f)?,
91            field::Value::U64Val(v) => fmt::Display::fmt(v, f)?,
92            field::Value::DebugVal(v) => fmt::Display::fmt(v, f)?,
93            field::Value::I64Val(v) => fmt::Display::fmt(v, f)?,
94        }
95
96        Ok(())
97    }
98}
99
100impl fmt::Display for Field {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        let name_val = (self.name.as_ref(), self.value.as_ref());
103        if let (Some(field::Name::StrName(name)), Some(val)) = name_val {
104            write!(f, "{}={}", name, val)?;
105        }
106
107        Ok(())
108    }
109}
110
111impl fmt::Display for Location {
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113        match (self.module_path.as_ref(), self.file.as_ref()) {
114            // Module paths take precedence because they're shorter...
115            (Some(module), _) => f.write_str(module.as_ref())?,
116            (None, Some(file)) => f.write_str(file.as_ref())?,
117            // If there's no file or module path, then printing the line and
118            // column makes no sense...
119            (None, None) => return f.write_str("<unknown location>"),
120        };
121
122        if let Some(line) = self.line {
123            write!(f, ":{}", line)?;
124
125            // Printing the column only makes sense if there's a line...
126            if let Some(column) = self.column {
127                write!(f, ":{}", column)?;
128            }
129        }
130
131        Ok(())
132    }
133}
134
135// === IDs ===
136
137impl From<&'static tracing_core::Metadata<'static>> for MetaId {
138    fn from(meta: &'static tracing_core::Metadata) -> Self {
139        MetaId {
140            id: meta as *const _ as u64,
141        }
142    }
143}
144
145impl From<tracing_core::span::Id> for SpanId {
146    fn from(id: tracing_core::span::Id) -> Self {
147        SpanId { id: id.into_u64() }
148    }
149}
150
151impl From<SpanId> for tracing_core::span::Id {
152    fn from(span_id: SpanId) -> Self {
153        tracing_core::span::Id::from_u64(span_id.id)
154    }
155}
156
157impl From<u64> for SpanId {
158    fn from(id: u64) -> Self {
159        SpanId { id }
160    }
161}
162
163impl From<&'static tracing_core::Metadata<'static>> for register_metadata::NewMetadata {
164    fn from(meta: &'static tracing_core::Metadata) -> Self {
165        register_metadata::NewMetadata {
166            id: Some(meta.into()),
167            metadata: Some(meta.into()),
168        }
169    }
170}
171
172impl From<i64> for field::Value {
173    fn from(val: i64) -> Self {
174        field::Value::I64Val(val)
175    }
176}
177
178impl From<u64> for field::Value {
179    fn from(val: u64) -> Self {
180        field::Value::U64Val(val)
181    }
182}
183
184impl From<bool> for field::Value {
185    fn from(val: bool) -> Self {
186        field::Value::BoolVal(val)
187    }
188}
189
190impl From<&str> for field::Value {
191    fn from(val: &str) -> Self {
192        field::Value::StrVal(val.into())
193    }
194}
195
196impl From<&str> for field::Name {
197    fn from(val: &str) -> Self {
198        field::Name::StrName(val.into())
199    }
200}
201
202impl From<&dyn std::fmt::Debug> for field::Value {
203    fn from(val: &dyn std::fmt::Debug) -> Self {
204        field::Value::DebugVal(format!("{:?}", val))
205    }
206}
207
208// === IDs ===
209
210impl From<u64> for Id {
211    fn from(id: u64) -> Self {
212        Id { id }
213    }
214}
215
216impl From<Id> for u64 {
217    fn from(id: Id) -> Self {
218        id.id
219    }
220}
221
222impl From<tracing_core::span::Id> for Id {
223    fn from(id: tracing_core::span::Id) -> Self {
224        Id { id: id.into_u64() }
225    }
226}