miden_node_utils/tracing/
grpc.rs1macro_rules! rpc_span {
3 ($service:literal, $method:literal) => {
4 tracing::info_span!(
5 concat!($service, "/", $method),
6 rpc.service = $service,
7 rpc.method = $method
8 )
9 };
10}
11
12pub fn block_producer_trace_fn<T>(request: &http::Request<T>) -> tracing::Span {
19 let span = if let Some("SubmitProvenTransaction") = request.uri().path().rsplit('/').next() {
20 rpc_span!("block-producer.rpc", "SubmitProvenTransaction")
21 } else {
22 rpc_span!("block-producer.rpc", "Unknown")
23 };
24
25 add_otel_span_attributes(span, request)
26}
27
28pub fn store_trace_fn<T>(request: &http::Request<T>) -> tracing::Span {
35 let span = match request.uri().path().rsplit('/').next() {
36 Some("ApplyBlock") => rpc_span!("store.rpc", "ApplyBlock"),
37 Some("CheckNullifiers") => rpc_span!("store.rpc", "CheckNullifiers"),
38 Some("CheckNullifiersByPrefix") => rpc_span!("store.rpc", "CheckNullifiersByPrefix"),
39 Some("GetAccountDetails") => rpc_span!("store.rpc", "GetAccountDetails"),
40 Some("GetAccountProofs") => rpc_span!("store.rpc", "GetAccountProofs"),
41 Some("GetAccountStateDelta") => rpc_span!("store.rpc", "GetAccountStateDelta"),
42 Some("GetBlockByNumber") => rpc_span!("store.rpc", "GetBlockByNumber"),
43 Some("GetBlockHeaderByNumber") => rpc_span!("store.rpc", "GetBlockHeaderByNumber"),
44 Some("GetBlockInputs") => rpc_span!("store.rpc", "GetBlockInputs"),
45 Some("GetBatchInputs") => rpc_span!("store.rpc", "GetBatchInputs"),
46 Some("GetNotesById") => rpc_span!("store.rpc", "GetNotesById"),
47 Some("GetTransactionInputs") => rpc_span!("store.rpc", "GetTransactionInputs"),
48 Some("SyncNotes") => rpc_span!("store.rpc", "SyncNotes"),
49 Some("SyncState") => rpc_span!("store.rpc", "SyncState"),
50 _ => rpc_span!("store.rpc", "Unknown"),
51 };
52
53 add_otel_span_attributes(span, request)
54}
55
56fn add_otel_span_attributes<T>(span: tracing::Span, request: &http::Request<T>) -> tracing::Span {
60 use super::OpenTelemetrySpanExt;
61 let otel_ctx = opentelemetry::global::get_text_map_propagator(|propagator| {
67 propagator.extract(&MetadataExtractor(&tonic::metadata::MetadataMap::from_headers(
68 request.headers().clone(),
69 )))
70 });
71 tracing_opentelemetry::OpenTelemetrySpanExt::set_parent(&span, otel_ctx);
72
73 span.set_attribute("rpc.system", "grpc");
76 if let Some(host) = request.uri().host() {
77 span.set_attribute("server.address", host);
78 }
79 if let Some(host_port) = request.uri().port() {
80 span.set_attribute("server.port", host_port.as_u16());
81 }
82 let remote_addr = request
83 .extensions()
84 .get::<tonic::transport::server::TcpConnectInfo>()
85 .and_then(tonic::transport::server::TcpConnectInfo::remote_addr);
86 if let Some(addr) = remote_addr {
87 span.set_attribute("client.address", addr.ip());
88 span.set_attribute("client.port", addr.port());
89 span.set_attribute("network.peer.address", addr.ip());
90 span.set_attribute("network.peer.port", addr.port());
91 span.set_attribute("network.transport", "tcp");
92 match addr.ip() {
93 std::net::IpAddr::V4(_) => span.set_attribute("network.type", "ipv4"),
94 std::net::IpAddr::V6(_) => span.set_attribute("network.type", "ipv6"),
95 }
96 }
97
98 span
99}
100
101#[derive(Copy, Clone)]
103pub struct OtelInterceptor;
104
105impl tonic::service::Interceptor for OtelInterceptor {
106 fn call(
107 &mut self,
108 mut request: tonic::Request<()>,
109 ) -> Result<tonic::Request<()>, tonic::Status> {
110 use tracing_opentelemetry::OpenTelemetrySpanExt;
111 let ctx = tracing::Span::current().context();
112 opentelemetry::global::get_text_map_propagator(|propagator| {
113 propagator.inject_context(&ctx, &mut MetadataInjector(request.metadata_mut()));
114 });
115
116 Ok(request)
117 }
118}
119
120struct MetadataExtractor<'a>(&'a tonic::metadata::MetadataMap);
121impl opentelemetry::propagation::Extractor for MetadataExtractor<'_> {
122 fn get(&self, key: &str) -> Option<&str> {
125 self.0.get(key).and_then(|metadata| metadata.to_str().ok())
126 }
127
128 fn keys(&self) -> Vec<&str> {
130 self.0
131 .keys()
132 .map(|key| match key {
133 tonic::metadata::KeyRef::Ascii(v) => v.as_str(),
134 tonic::metadata::KeyRef::Binary(v) => v.as_str(),
135 })
136 .collect::<Vec<_>>()
137 }
138}
139
140struct MetadataInjector<'a>(&'a mut tonic::metadata::MetadataMap);
141impl opentelemetry::propagation::Injector for MetadataInjector<'_> {
142 fn set(&mut self, key: &str, value: String) {
145 if let Ok(key) = tonic::metadata::MetadataKey::from_bytes(key.as_bytes()) {
146 if let Ok(val) = tonic::metadata::MetadataValue::try_from(&value) {
147 self.0.insert(key, val);
148 }
149 }
150 }
151}