aingle_observability/open/context_wrap.rs
1use super::*;
2
3/// Wrap a channel message in a span context.
4/// The context is automatically propagated to
5/// the current span by calling `msg_wrap.inner()`.
6/// The context is automatically propagated from
7/// the current span by calling `t.into()`.
8/// If you wish to avoid either of these propagations
9/// you can use `msg_wrap.without_context()` and
10/// `MsgWrap::from_no_context(t)` respectively.
11pub struct MsgWrap<T> {
12 t: T,
13 context: Option<Context>,
14}
15
16impl<T> MsgWrap<T> {
17 /// Create a T wrapped in a Context.
18 /// If you just need the current context use
19 /// `t.into()`.
20 pub fn new(t: T, context: Context) -> Self {
21 Self {
22 t,
23 context: Some(context),
24 }
25 }
26 /// Get the inner type and propagate the context to
27 /// the current span.
28 pub fn inner(self) -> T {
29 if let Some(context) = self.context {
30 tracing::Span::set_current_context(context);
31 }
32 self.t
33 }
34 /// Get the inner type without propagating the context.
35 pub fn without_context(self) -> T {
36 self.t
37 }
38
39 /// Create a wrapped T with no Context.
40 pub fn from_no_context(t: T) -> Self {
41 Self { t, context: None }
42 }
43
44 /// Unwrap the wrapped T into a T and Context.
45 /// If you just need to propagate the context to
46 /// the current span use `msg_wrap.inner()`
47 pub fn into_parts(self) -> (T, Context) {
48 (self.t, self.context.unwrap_or_default())
49 }
50}
51
52impl<T> From<T> for MsgWrap<T> {
53 /// Create a wrapped T with the context from
54 /// the current span.
55 fn from(t: T) -> Self {
56 let span = tracing::Span::current();
57 let context = if span.is_disabled() {
58 None
59 } else {
60 Some(span.get_context())
61 };
62
63 Self { t, context }
64 }
65}
66
67impl<T> std::fmt::Debug for MsgWrap<T>
68where
69 T: std::fmt::Debug,
70{
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 f.write_fmt(format_args!("{:?}", self.t))
73 }
74}