reddb_server/telemetry/span.rs
1//! Span helpers that pull connection / transaction / tenant / auth
2//! context out of the runtime thread-locals and attach them to a
3//! `tracing::Span`. Any log emitted while the span is entered picks
4//! up these fields automatically — the caller never has to pass
5//! `conn_id` / `xid` / `tenant` as parameters down through the call
6//! graph.
7//!
8//! Usage:
9//! ```ignore
10//! use reddb::telemetry::span;
11//! let _g = span::query_span(query).entered();
12//! // subsequent tracing::info!/warn!/error! carry conn_id+xid+tenant
13//! ```
14
15use tracing::Span;
16
17use crate::runtime::mvcc::{current_connection_id, current_tenant};
18
19/// Span wrapping a single `execute_query` call. Stamps the current
20/// connection id, transaction xid (0 when autocommit), tenant, and
21/// authenticated user so every downstream event (filter eval, scan,
22/// CDC emit, error) inherits correlation context.
23///
24/// Keep the string cheap — we only store the length, not the query
25/// body, to avoid PII leakage into logs.
26pub fn query_span(query: &str) -> Span {
27 tracing::info_span!(
28 "query",
29 conn_id = current_connection_id(),
30 tenant = current_tenant().unwrap_or_default(),
31 query_len = query.len(),
32 )
33}
34
35/// Span for a new wire/gRPC/HTTP connection. Call at accept time so
36/// every log inside that connection's lifetime carries the remote
37/// peer and transport kind.
38pub fn connection_span(transport: &'static str, peer: impl std::fmt::Display) -> Span {
39 tracing::info_span!(
40 "conn",
41 transport = transport,
42 peer = %peer,
43 )
44}
45
46/// Span for a listener bind — emits once at startup to mark the
47/// transport as ready.
48pub fn listener_span(transport: &'static str, bind: impl std::fmt::Display) -> Span {
49 tracing::info_span!(
50 "listener",
51 transport = transport,
52 bind = %bind,
53 )
54}