From 8877f3d7c2138019b2bb1d9da27d71f092596f8d Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 2 Sep 2025 23:59:53 +1000 Subject: [PATCH] chore(telemetry): remove span name from attributes in Sentry (#10278) Before sending logs to Sentry, we perform a pass over them to make them somewhat look like the output of `tracing_subscriber::fmt`. In particular, we trim the span name from fields in order to shorten the message. In our logger config, we don't render the span name at all and just append all fields at the end of the message. Sentry supports filtering by field names but unfortunately, those cannot contain a colon (`:`). Given that we already trim the span name in the actual message, it also makes sense to remove the span name from the actual attributes. That allows us to actually filter by these attributes and has the additional advantage that fields from different spans with the same name are merged. This is especially useful because we purposely reuse names like `cid` to refer the current connection from different spans. --- rust/telemetry/src/lib.rs | 41 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/rust/telemetry/src/lib.rs b/rust/telemetry/src/lib.rs index 49c9231e9..386741e0a 100644 --- a/rust/telemetry/src/lib.rs +++ b/rust/telemetry/src/lib.rs @@ -3,7 +3,7 @@ use std::{ borrow::Cow, collections::BTreeMap, - fmt, + fmt, mem, net::{SocketAddr, ToSocketAddrs as _}, str::FromStr, sync::Arc, @@ -371,21 +371,24 @@ fn append_tracing_fields_to_message(mut log: Log) -> Option { "parent_span_id", ]; - for (key, attribute) in &log.attributes { + for (key, attribute) in mem::take(&mut log.attributes) { let LogAttribute(serde_json::Value::String(attr_string)) = &attribute else { continue; }; if IGNORED_ATTRS.iter().any(|attr| key.starts_with(attr)) { + log.attributes.insert(key, attribute); + continue; } let key = match key.rsplit_once(':') { Some((_, key)) => key, - None => key, + None => &key, }; log.body.push_str(&format!(" {key}={attr_string}")); + log.attributes.insert(key.to_owned(), attribute); } Some(log) @@ -504,6 +507,38 @@ mod tests { ) } + #[test] + fn trims_name_of_span_from_attribute() { + let log = log( + "Foobar", + &[ + ("handle_input:class", "success response"), + ("handle_input:from", "1.1.1.1:3478"), + ("handle_input:method", "binding"), + ], + ); + + let log = append_tracing_fields_to_message(log).unwrap(); + + assert_eq!( + log.attributes, + BTreeMap::from([ + ( + "class".to_owned(), + LogAttribute(serde_json::Value::String("success response".to_owned())) + ), + ( + "from".to_owned(), + LogAttribute(serde_json::Value::String("1.1.1.1:3478".to_owned())) + ), + ( + "method".to_owned(), + LogAttribute(serde_json::Value::String("binding".to_owned())) + ) + ]) + ) + } + fn event(msg: &str) -> Event<'static> { Event { message: Some(msg.to_owned()),