1use crate::payload::{Payload, PayloadRaw};
8use std::sync::Arc;
9use uuid::Uuid;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
14pub struct TraceContext {
15 pub correlation_id: Uuid,
16 pub span_id: u64,
17 pub parent_id: Option<u64>,
18}
19
20impl TraceContext {
21 pub fn new() -> Self {
23 let correlation_id = Uuid::now_v7();
24 let span_id = correlation_id.as_u128() as u64; Self {
26 correlation_id,
27 span_id,
28 parent_id: None,
29 }
30 }
31
32 pub fn new_child(&self) -> Self {
34 Self {
35 correlation_id: self.correlation_id,
36 span_id: Uuid::now_v7().as_u128() as u64, parent_id: Some(self.span_id),
38 }
39 }
40
41 pub fn from_parts(correlation_id: Uuid, span_id: u64, parent_id: Option<u64>) -> Self {
43 Self {
44 correlation_id,
45 span_id,
46 parent_id,
47 }
48 }
49}
50
51impl Default for TraceContext {
52 fn default() -> Self {
53 Self::new()
54 }
55}
56
57pub trait LogTrace {
59 fn correlation_id(&self) -> Uuid;
60 fn span_id(&self) -> u64;
61 fn parent_id(&self) -> Option<u64>;
62 fn neuron_name(&self) -> String;
63
64 fn trace_context(&self) -> TraceContext {
66 TraceContext::from_parts(self.correlation_id(), self.span_id(), self.parent_id())
67 }
68
69 fn span_info(&self, name: &'static str) -> tracing::Span {
71 let correlation_id = self.correlation_id().to_string();
72 let span_id = self.span_id().to_string();
73 let parent_id = self
74 .parent_id()
75 .map(|id| id.to_string())
76 .unwrap_or_default();
77 let neuron = self.neuron_name();
78
79 tracing::info_span!(
80 target: "plexor::trace",
81 "plexor",
82 log_name = name,
83 correlation_id = %correlation_id,
84 span_id = %span_id,
85 parent_id = %parent_id,
86 neuron = %neuron
87 )
88 }
89
90 fn span_debug(&self, name: &'static str) -> tracing::Span {
92 let correlation_id = self.correlation_id().to_string();
93 let span_id = self.span_id().to_string();
94 let parent_id = self
95 .parent_id()
96 .map(|id| id.to_string())
97 .unwrap_or_default();
98 let neuron = self.neuron_name();
99
100 tracing::debug_span!(
101 target: "plexor::trace",
102 "plexor",
103 log_name = name,
104 correlation_id = %correlation_id,
105 span_id = %span_id,
106 parent_id = %parent_id,
107 neuron = %neuron
108 )
109 }
110}
111
112impl LogTrace for TraceContext {
113 fn correlation_id(&self) -> Uuid {
114 self.correlation_id
115 }
116 fn span_id(&self) -> u64 {
117 self.span_id
118 }
119 fn parent_id(&self) -> Option<u64> {
120 self.parent_id
121 }
122 fn neuron_name(&self) -> String {
123 "app".to_string()
124 }
125 fn trace_context(&self) -> TraceContext {
126 *self
127 }
128}
129
130impl LogTrace for Uuid {
131 fn correlation_id(&self) -> Uuid {
132 Uuid::nil()
133 }
134 fn span_id(&self) -> u64 {
135 0
136 }
137 fn parent_id(&self) -> Option<u64> {
138 None
139 }
140 fn neuron_name(&self) -> String {
141 "none".to_string()
142 }
143
144 fn span_info(&self, name: &'static str) -> tracing::Span {
145 tracing::info_span!(
146 target: "plexor::trace",
147 "plexor",
148 log_name = name,
149 ganglion_id = %self
150 )
151 }
152
153 fn span_debug(&self, name: &'static str) -> tracing::Span {
154 tracing::debug_span!(
155 target: "plexor::trace",
156 "plexor",
157 log_name = name,
158 ganglion_id = %self
159 )
160 }
161}
162
163impl<T, C> LogTrace for Payload<T, C>
164where
165 T: Send + Sync + 'static,
166 C: crate::codec::Codec<T> + crate::codec::CodecName + Send + Sync + 'static,
167{
168 fn correlation_id(&self) -> Uuid {
169 self.trace.correlation_id
170 }
171 fn span_id(&self) -> u64 {
172 self.trace.span_id
173 }
174 fn parent_id(&self) -> Option<u64> {
175 self.trace.parent_id
176 }
177 fn neuron_name(&self) -> String {
178 self.neuron.name()
179 }
180 fn trace_context(&self) -> TraceContext {
181 self.trace
182 }
183}
184
185impl<T, C> LogTrace for PayloadRaw<T, C>
186where
187 T: Send + Sync + 'static,
188 C: crate::codec::Codec<T> + crate::codec::CodecName + Send + Sync + 'static,
189{
190 fn correlation_id(&self) -> Uuid {
191 self.trace.correlation_id
192 }
193 fn span_id(&self) -> u64 {
194 self.trace.span_id
195 }
196 fn parent_id(&self) -> Option<u64> {
197 self.trace.parent_id
198 }
199 fn neuron_name(&self) -> String {
200 self.neuron
201 .as_ref()
202 .map(|n| n.name())
203 .unwrap_or_else(|| "unknown".to_string())
204 }
205 fn trace_context(&self) -> TraceContext {
206 self.trace
207 }
208}
209
210impl LogTrace for crate::erasure::payload::SimplePayloadRawErased {
211 fn correlation_id(&self) -> Uuid {
212 self.trace.correlation_id
213 }
214 fn span_id(&self) -> u64 {
215 self.trace.span_id
216 }
217 fn parent_id(&self) -> Option<u64> {
218 self.trace.parent_id
219 }
220 fn neuron_name(&self) -> String {
221 self.neuron_name.clone()
222 }
223 fn trace_context(&self) -> TraceContext {
224 self.trace
225 }
226}
227
228impl<T, C> LogTrace for crate::erasure::payload::PayloadErasedWrapper<T, C>
229where
230 T: Send + Sync + 'static,
231 C: crate::codec::Codec<T> + crate::codec::CodecName + Send + Sync + 'static,
232{
233 fn correlation_id(&self) -> Uuid {
234 self.get_typed_payload().trace.correlation_id
235 }
236 fn span_id(&self) -> u64 {
237 self.get_typed_payload().trace.span_id
238 }
239 fn parent_id(&self) -> Option<u64> {
240 self.get_typed_payload().trace.parent_id
241 }
242 fn neuron_name(&self) -> String {
243 self.get_typed_payload().neuron.name()
244 }
245 fn trace_context(&self) -> TraceContext {
246 self.get_typed_payload().trace
247 }
248}
249
250impl<T, C> LogTrace for crate::erasure::payload::PayloadRawErasedWrapper<T, C>
251where
252 T: Send + Sync + 'static,
253 C: crate::codec::Codec<T> + crate::codec::CodecName + Send + Sync + 'static,
254{
255 fn correlation_id(&self) -> Uuid {
256 self.get_payload_raw().trace.correlation_id
257 }
258 fn span_id(&self) -> u64 {
259 self.get_payload_raw().trace.span_id
260 }
261 fn parent_id(&self) -> Option<u64> {
262 self.get_payload_raw().trace.parent_id
263 }
264 fn neuron_name(&self) -> String {
265 self.get_payload_raw()
266 .neuron
267 .as_ref()
268 .map(|n| n.name())
269 .unwrap_or_else(|| "unknown".to_string())
270 }
271 fn trace_context(&self) -> TraceContext {
272 self.get_payload_raw().trace
273 }
274}
275
276impl<P: LogTrace + ?Sized> LogTrace for Arc<P> {
277 fn correlation_id(&self) -> Uuid {
278 (**self).correlation_id()
279 }
280 fn span_id(&self) -> u64 {
281 (**self).span_id()
282 }
283 fn parent_id(&self) -> Option<u64> {
284 (**self).parent_id()
285 }
286 fn neuron_name(&self) -> String {
287 (**self).neuron_name()
288 }
289}