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 rpc_trace_fn<T>(request: &http::Request<T>) -> tracing::Span {
19 let span = match request.uri().path().rsplit('/').next() {
20 Some("CheckNullifiers") => rpc_span!("rpc.rpc", "CheckNullifiers"),
21 Some("CheckNullifiersByPrefix") => rpc_span!("rpc.rpc", "CheckNullifiersByPrefix"),
22 Some("GetBlockHeaderByNumber") => rpc_span!("rpc.rpc", "GetBlockHeaderByNumber"),
23 Some("SyncState") => rpc_span!("rpc.rpc", "SyncState"),
24 Some("SyncNotes") => rpc_span!("rpc.rpc", "SyncNotes"),
25 Some("GetNotesById") => rpc_span!("rpc.rpc", "GetNotesById"),
26 Some("SubmitProvenTransaction") => rpc_span!("rpc.rpc", "SubmitProvenTransaction"),
27 Some("GetAccountDetails") => rpc_span!("rpc.rpc", "GetAccountDetails"),
28 Some("GetBlockByNumber") => rpc_span!("rpc.rpc", "GetBlockByNumber"),
29 Some("GetAccountStateDelta") => rpc_span!("rpc.rpc", "GetAccountStateDelta"),
30 Some("GetAccountProofs") => rpc_span!("rpc.rpc", "GetAccountProofs"),
31 Some("Status") => rpc_span!("rpc.rpc", "Status"),
32 _ => rpc_span!("rpc.rpc", "Unknown"),
33 };
34 add_network_attributes(span, request)
35}
36
37pub fn block_producer_trace_fn<T>(request: &http::Request<T>) -> tracing::Span {
44 let span = match request.uri().path().rsplit('/').next() {
45 Some("SubmitProvenTransaction") => {
46 rpc_span!("block-producer.rpc", "SubmitProvenTransaction")
47 },
48 Some("Status") => rpc_span!("block-producer.rpc", "Status"),
49 _ => {
50 rpc_span!("block-producer.rpc", "Unknown")
51 },
52 };
53
54 let span = add_otel_span_attributes(span, request);
55 add_network_attributes(span, request)
56}
57
58pub fn store_trace_fn<T>(request: &http::Request<T>) -> tracing::Span {
65 let span = match request.uri().path().rsplit('/').next() {
66 Some("ApplyBlock") => rpc_span!("store.rpc", "ApplyBlock"),
67 Some("CheckNullifiers") => rpc_span!("store.rpc", "CheckNullifiers"),
68 Some("CheckNullifiersByPrefix") => rpc_span!("store.rpc", "CheckNullifiersByPrefix"),
69 Some("GetAccountDetails") => rpc_span!("store.rpc", "GetAccountDetails"),
70 Some("GetAccountProofs") => rpc_span!("store.rpc", "GetAccountProofs"),
71 Some("GetAccountStateDelta") => rpc_span!("store.rpc", "GetAccountStateDelta"),
72 Some("GetBlockByNumber") => rpc_span!("store.rpc", "GetBlockByNumber"),
73 Some("GetBlockHeaderByNumber") => rpc_span!("store.rpc", "GetBlockHeaderByNumber"),
74 Some("GetBlockInputs") => rpc_span!("store.rpc", "GetBlockInputs"),
75 Some("GetBatchInputs") => rpc_span!("store.rpc", "GetBatchInputs"),
76 Some("GetNotesById") => rpc_span!("store.rpc", "GetNotesById"),
77 Some("GetTransactionInputs") => rpc_span!("store.rpc", "GetTransactionInputs"),
78 Some("SyncNotes") => rpc_span!("store.rpc", "SyncNotes"),
79 Some("SyncState") => rpc_span!("store.rpc", "SyncState"),
80 Some("Status") => rpc_span!("store.rpc", "Status"),
81 _ => rpc_span!("store.rpc", "Unknown"),
82 };
83
84 let span = add_otel_span_attributes(span, request);
85 add_network_attributes(span, request)
86}
87
88fn add_otel_span_attributes<T>(span: tracing::Span, request: &http::Request<T>) -> tracing::Span {
92 let otel_ctx = opentelemetry::global::get_text_map_propagator(|propagator| {
98 propagator.extract(&MetadataExtractor(&tonic::metadata::MetadataMap::from_headers(
99 request.headers().clone(),
100 )))
101 });
102 tracing_opentelemetry::OpenTelemetrySpanExt::set_parent(&span, otel_ctx);
103
104 span
105}
106
107fn add_network_attributes<T>(span: tracing::Span, request: &http::Request<T>) -> tracing::Span {
111 use super::OpenTelemetrySpanExt;
112 span.set_attribute("rpc.system", "grpc");
114 if let Some(host) = request.uri().host() {
115 span.set_attribute("server.address", host);
116 }
117 if let Some(host_port) = request.uri().port() {
118 span.set_attribute("server.port", host_port.as_u16());
119 }
120 let remote_addr = request
121 .extensions()
122 .get::<tonic::transport::server::TcpConnectInfo>()
123 .and_then(tonic::transport::server::TcpConnectInfo::remote_addr);
124 if let Some(addr) = remote_addr {
125 span.set_attribute("client.address", addr.ip());
126 span.set_attribute("client.port", addr.port());
127 span.set_attribute("network.peer.address", addr.ip());
128 span.set_attribute("network.peer.port", addr.port());
129 span.set_attribute("network.transport", "tcp");
130 match addr.ip() {
131 std::net::IpAddr::V4(_) => span.set_attribute("network.type", "ipv4"),
132 std::net::IpAddr::V6(_) => span.set_attribute("network.type", "ipv6"),
133 }
134 }
135
136 span
137}
138
139#[derive(Copy, Clone)]
141pub struct OtelInterceptor;
142
143impl tonic::service::Interceptor for OtelInterceptor {
144 fn call(
145 &mut self,
146 mut request: tonic::Request<()>,
147 ) -> Result<tonic::Request<()>, tonic::Status> {
148 use tracing_opentelemetry::OpenTelemetrySpanExt;
149 let ctx = tracing::Span::current().context();
150 opentelemetry::global::get_text_map_propagator(|propagator| {
151 propagator.inject_context(&ctx, &mut MetadataInjector(request.metadata_mut()));
152 });
153
154 Ok(request)
155 }
156}
157
158struct MetadataExtractor<'a>(&'a tonic::metadata::MetadataMap);
159impl opentelemetry::propagation::Extractor for MetadataExtractor<'_> {
160 fn get(&self, key: &str) -> Option<&str> {
163 self.0.get(key).and_then(|metadata| metadata.to_str().ok())
164 }
165
166 fn keys(&self) -> Vec<&str> {
168 self.0
169 .keys()
170 .map(|key| match key {
171 tonic::metadata::KeyRef::Ascii(v) => v.as_str(),
172 tonic::metadata::KeyRef::Binary(v) => v.as_str(),
173 })
174 .collect::<Vec<_>>()
175 }
176}
177
178struct MetadataInjector<'a>(&'a mut tonic::metadata::MetadataMap);
179impl opentelemetry::propagation::Injector for MetadataInjector<'_> {
180 fn set(&mut self, key: &str, value: String) {
183 if let Ok(key) = tonic::metadata::MetadataKey::from_bytes(key.as_bytes()) {
184 if let Ok(val) = tonic::metadata::MetadataValue::try_from(&value) {
185 self.0.insert(key, val);
186 }
187 }
188 }
189}