miden_node_utils/tracing/
span_ext.rs1use core::time::Duration;
2use std::net::IpAddr;
3
4use miden_objects::{Digest, batch::BatchId, block::BlockNumber};
5use opentelemetry::{Key, Value, trace::Status};
6
7pub trait ToValue {
9 fn to_value(&self) -> Value;
10}
11
12impl ToValue for Duration {
13 fn to_value(&self) -> Value {
14 self.as_secs_f64().into()
15 }
16}
17
18impl ToValue for Digest {
19 fn to_value(&self) -> Value {
20 self.to_hex().into()
21 }
22}
23
24impl ToValue for BlockNumber {
25 fn to_value(&self) -> Value {
26 i64::from(self.as_u32()).into()
27 }
28}
29
30impl ToValue for BatchId {
31 fn to_value(&self) -> Value {
32 self.to_hex().into()
33 }
34}
35
36impl ToValue for usize {
37 fn to_value(&self) -> Value {
38 i64::try_from(*self).unwrap_or(i64::MAX).into()
39 }
40}
41
42macro_rules! impl_to_string_to_value {
44 ($($t:ty),*) => {
45 $(
46 impl ToValue for $t {
47 fn to_value(&self) -> Value {
48 self.to_string().into()
49 }
50 }
51 )*
52 };
53}
54impl_to_string_to_value!(IpAddr, &str);
55
56macro_rules! impl_int_to_value {
58 ($($t:ty),*) => {
59 $(
60 impl ToValue for $t {
61 fn to_value(&self) -> Value {
62 i64::from(*self).into()
63 }
64 }
65 )*
66 };
67}
68impl_int_to_value!(u16, u32);
69
70macro_rules! impl_to_value {
72 ($($t:ty),*) => {
73 $(
74 impl ToValue for $t {
75 fn to_value(&self) -> Value {
76 (*self).into()
77 }
78 }
79 )*
80 };
81}
82impl_to_value!(f64, i64);
83
84pub trait OpenTelemetrySpanExt: private::Sealed {
88 fn set_attribute(&self, key: impl Into<Key>, value: impl ToValue);
89 fn set_error(&self, err: &dyn std::error::Error);
90}
91
92impl<S> OpenTelemetrySpanExt for S
93where
94 S: tracing_opentelemetry::OpenTelemetrySpanExt,
95{
96 fn set_attribute(&self, key: impl Into<Key>, value: impl ToValue) {
100 tracing_opentelemetry::OpenTelemetrySpanExt::set_attribute(self, key, value.to_value());
101 }
102
103 fn set_error(&self, err: &dyn std::error::Error) {
105 let mut report = err.to_string();
107
108 std::iter::successors(err.source(), |child| child.source())
109 .for_each(|source| report.push_str(&format!("\nCaused by: {source}")));
110
111 tracing_opentelemetry::OpenTelemetrySpanExt::set_status(
112 self,
113 Status::Error { description: report.into() },
114 );
115 }
116}
117
118mod private {
119 pub trait Sealed {}
120 impl<S> Sealed for S where S: tracing_opentelemetry::OpenTelemetrySpanExt {}
121}