miden_node_utils/tracing/
span_ext.rs

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