Skip to main content

miden_node_utils/tracing/
span_ext.rs

1use core::time::Duration;
2use std::net::IpAddr;
3
4use miden_protocol::Word;
5use miden_protocol::account::AccountId;
6use miden_protocol::batch::BatchId;
7use miden_protocol::block::BlockNumber;
8use miden_protocol::transaction::TransactionId;
9use opentelemetry::trace::Status;
10use opentelemetry::{Key, StringValue, Value};
11
12use crate::ErrorReport;
13
14/// Utility functions for converting types into [`opentelemetry::Value`].
15pub trait ToValue {
16    fn to_value(&self) -> Value;
17}
18
19impl<T: ToValue> ToValue for Vec<T> {
20    fn to_value(&self) -> Value {
21        let string_values = self.iter().map(|v| v.to_value().into()).collect::<Vec<StringValue>>();
22        Value::Array(string_values.into())
23    }
24}
25
26impl ToValue for Duration {
27    fn to_value(&self) -> Value {
28        self.as_secs_f64().into()
29    }
30}
31
32impl ToValue for Word {
33    fn to_value(&self) -> Value {
34        self.to_hex().into()
35    }
36}
37
38impl ToValue for AccountId {
39    fn to_value(&self) -> Value {
40        self.to_hex().into()
41    }
42}
43
44impl ToValue for BlockNumber {
45    fn to_value(&self) -> Value {
46        i64::from(self.as_u32()).into()
47    }
48}
49
50impl ToValue for BatchId {
51    fn to_value(&self) -> Value {
52        self.to_hex().into()
53    }
54}
55
56impl ToValue for TransactionId {
57    fn to_value(&self) -> Value {
58        self.to_hex().into()
59    }
60}
61
62impl ToValue for usize {
63    fn to_value(&self) -> Value {
64        i64::try_from(*self).unwrap_or(i64::MAX).into()
65    }
66}
67
68impl ToValue for u64 {
69    fn to_value(&self) -> Value {
70        i64::try_from(*self).unwrap_or(i64::MAX).into()
71    }
72}
73
74/// Generates `impl ToValue` blocks for types that are `ToString`.
75macro_rules! impl_to_string_to_value {
76    ($($t:ty),*) => {
77        $(
78            impl ToValue for $t {
79                fn to_value(&self) -> Value {
80                    self.to_string().into()
81                }
82            }
83        )*
84    };
85}
86impl_to_string_to_value!(IpAddr, &str);
87
88/// Generates `impl ToValue` blocks for integer types.
89macro_rules! impl_int_to_value {
90    ($($t:ty),*) => {
91        $(
92            impl ToValue for $t {
93                fn to_value(&self) -> Value {
94                    i64::from(*self).into()
95                }
96            }
97        )*
98    };
99}
100impl_int_to_value!(u16, u32);
101
102/// Generates `impl ToValue` blocks for types that are `Into<Value>`.
103macro_rules! impl_to_value {
104    ($($t:ty),*) => {
105        $(
106            impl ToValue for $t {
107                fn to_value(&self) -> Value {
108                    (*self).into()
109                }
110            }
111        )*
112    };
113}
114impl_to_value!(f64, i64);
115
116/// Utility functions based on [`tracing_opentelemetry::OpenTelemetrySpanExt`].
117///
118/// This is a sealed trait. It and cannot be implemented outside of this module.
119pub trait OpenTelemetrySpanExt: private::Sealed {
120    fn set_attribute(&self, key: impl Into<Key>, value: impl ToValue);
121    fn set_error(&self, err: &dyn std::error::Error);
122}
123
124impl<S> OpenTelemetrySpanExt for S
125where
126    S: tracing_opentelemetry::OpenTelemetrySpanExt,
127{
128    /// Sets an attribute on `Span`.
129    ///
130    /// Implementations for `ToValue` should be added to this crate (miden-node-utils).
131    fn set_attribute(&self, key: impl Into<Key>, value: impl ToValue) {
132        tracing_opentelemetry::OpenTelemetrySpanExt::set_attribute(self, key, value.to_value());
133    }
134
135    /// Sets a status on `Span` based on an error.
136    fn set_error(&self, err: &dyn std::error::Error) {
137        tracing_opentelemetry::OpenTelemetrySpanExt::set_status(
138            self,
139            Status::Error { description: err.as_report().into() },
140        );
141    }
142}
143
144mod private {
145    pub trait Sealed {}
146    impl<S> Sealed for S where S: tracing_opentelemetry::OpenTelemetrySpanExt {}
147}