miden_node_utils/tracing/
span_ext.rs

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