tracing_tunnel/types.rs
1//! Types to carry tracing events over the WASM client-host boundary.
2
3use serde::{Deserialize, Serialize};
4use tracing_core::{Level, Metadata};
5
6use core::hash::Hash;
7
8use crate::{
9 alloc::{Cow, String, Vec},
10 TracedValues,
11};
12
13/// ID of a tracing [`Metadata`] record as used in [`TracingEvent`]s.
14pub type MetadataId = u64;
15/// ID of a tracing span as used in [`TracingEvent`]s.
16pub type RawSpanId = u64;
17
18/// Tracing level defined in [`CallSiteData`].
19///
20/// This corresponds to [`Level`] from the `tracing-core` library, but is (de)serializable.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
22#[serde(rename_all = "snake_case")]
23pub enum TracingLevel {
24 /// "ERROR" level.
25 Error,
26 /// "WARN" level.
27 Warn,
28 /// "INFO" level.
29 Info,
30 /// "DEBUG" level.
31 Debug,
32 /// "TRACE" level.
33 Trace,
34}
35
36impl From<Level> for TracingLevel {
37 fn from(level: Level) -> Self {
38 match level {
39 Level::ERROR => Self::Error,
40 Level::WARN => Self::Warn,
41 Level::INFO => Self::Info,
42 Level::DEBUG => Self::Debug,
43 Level::TRACE => Self::Trace,
44 }
45 }
46}
47
48/// Kind of [`CallSiteData`] location: either a span, or an event.
49#[derive(Debug, Clone, Copy, Hash, Serialize, Deserialize)]
50#[serde(rename_all = "snake_case")]
51pub enum CallSiteKind {
52 /// Call site is a span.
53 Span,
54 /// Call site is an event.
55 Event,
56}
57
58/// Data for a single tracing call site: either a span definition, or an event definition.
59///
60/// This corresponds to [`Metadata`] from the `tracing-core` library, but is (de)serializable.
61#[derive(Debug, Clone, Hash, Serialize, Deserialize)]
62pub struct CallSiteData {
63 /// Kind of the call site.
64 pub kind: CallSiteKind,
65 /// Name of the call site.
66 pub name: Cow<'static, str>,
67 /// Tracing target.
68 pub target: Cow<'static, str>,
69 /// Tracing level.
70 pub level: TracingLevel,
71 /// Path to the module where this call site is defined.
72 #[serde(default, skip_serializing_if = "Option::is_none")]
73 pub module_path: Option<Cow<'static, str>>,
74 /// Path to the file where this call site is defined.
75 #[serde(default, skip_serializing_if = "Option::is_none")]
76 pub file: Option<Cow<'static, str>>,
77 /// Line number for this call site.
78 #[serde(default, skip_serializing_if = "Option::is_none")]
79 pub line: Option<u32>,
80 /// Fields defined by this call site.
81 pub fields: Vec<Cow<'static, str>>,
82}
83
84impl From<&Metadata<'static>> for CallSiteData {
85 fn from(metadata: &Metadata<'static>) -> Self {
86 let kind = if metadata.is_span() {
87 CallSiteKind::Span
88 } else {
89 debug_assert!(metadata.is_event());
90 CallSiteKind::Event
91 };
92 let fields = metadata
93 .fields()
94 .iter()
95 .map(|field| Cow::Borrowed(field.name()));
96
97 Self {
98 kind,
99 name: Cow::Borrowed(metadata.name()),
100 target: Cow::Borrowed(metadata.target()),
101 level: TracingLevel::from(*metadata.level()),
102 module_path: metadata.module_path().map(Cow::Borrowed),
103 file: metadata.file().map(Cow::Borrowed),
104 line: metadata.line(),
105 fields: fields.collect(),
106 }
107 }
108}
109
110/// Event produced during tracing.
111///
112/// These events are emitted by a [`TracingEventSender`] and then consumed
113/// by a [`TracingEventReceiver`] to pass tracing info across an API boundary.
114///
115/// [`TracingEventSender`]: crate::TracingEventSender
116/// [`TracingEventReceiver`]: crate::TracingEventReceiver
117#[derive(Debug, Clone, Serialize, Deserialize)]
118#[serde(rename_all = "snake_case")]
119#[non_exhaustive]
120pub enum TracingEvent {
121 /// New call site.
122 NewCallSite {
123 /// Unique ID of the call site that will be used to refer to it in the following events.
124 id: MetadataId,
125 /// Information about the call site.
126 #[serde(flatten)]
127 data: CallSiteData,
128 },
129
130 /// New tracing span.
131 NewSpan {
132 /// Unique ID of the span that will be used to refer to it in the following events.
133 id: RawSpanId,
134 /// Parent span ID. `None` means using the contextual parent (i.e., the current span).
135 #[serde(default, skip_serializing_if = "Option::is_none")]
136 parent_id: Option<RawSpanId>,
137 /// ID of the span metadata.
138 metadata_id: MetadataId,
139 /// Values associated with the span.
140 values: TracedValues<String>,
141 },
142 /// New "follows from" relation between spans.
143 FollowsFrom {
144 /// ID of the follower span.
145 id: RawSpanId,
146 /// ID of the source span.
147 follows_from: RawSpanId,
148 },
149 /// Span was entered.
150 SpanEntered {
151 /// ID of the span.
152 id: RawSpanId,
153 },
154 /// Span was exited.
155 SpanExited {
156 /// ID of the span.
157 id: RawSpanId,
158 },
159 /// Span was cloned.
160 SpanCloned {
161 /// ID of the span.
162 id: RawSpanId,
163 },
164 /// Span was dropped (aka closed).
165 SpanDropped {
166 /// ID of the span.
167 id: RawSpanId,
168 },
169 /// New values recorded for a span.
170 ValuesRecorded {
171 /// ID of the span.
172 id: RawSpanId,
173 /// Recorded values.
174 values: TracedValues<String>,
175 },
176
177 /// New event.
178 NewEvent {
179 /// ID of the event metadata.
180 metadata_id: MetadataId,
181 /// Parent span ID. `None` means using the contextual parent (i.e., the current span).
182 #[serde(default, skip_serializing_if = "Option::is_none")]
183 parent: Option<RawSpanId>,
184 /// Values associated with the event.
185 values: TracedValues<String>,
186 },
187}