Skip to content

Commit d3e2ca0

Browse files
authored
Implement record of tagged span data in tracing integration (#696)
1 parent a1481d4 commit d3e2ca0

File tree

4 files changed

+82
-7
lines changed

4 files changed

+82
-7
lines changed

sentry-core/src/performance.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::borrow::Cow;
12
use std::collections::BTreeMap;
23
use std::ops::{Deref, DerefMut};
34
use std::sync::{Arc, Mutex, MutexGuard};
@@ -433,6 +434,20 @@ impl<'a> TransactionData<'a> {
433434
Box::new(std::iter::empty())
434435
}
435436
}
437+
438+
/// Set some extra information to be sent with this Transaction.
439+
pub fn set_data(&mut self, key: Cow<'a, str>, value: protocol::Value) {
440+
if let Some(transaction) = self.0.transaction.as_mut() {
441+
transaction.extra.insert(key.into(), value);
442+
}
443+
}
444+
445+
/// Set some extra information to be sent with this Transaction.
446+
pub fn set_tag(&mut self, key: Cow<'_, str>, value: String) {
447+
if let Some(transaction) = self.0.transaction.as_mut() {
448+
transaction.tags.insert(key.into(), value);
449+
}
450+
}
436451
}
437452

438453
impl Transaction {
@@ -627,6 +642,18 @@ impl Transaction {
627642
/// A smart pointer to a span's [`data` field](protocol::Span::data).
628643
pub struct Data<'a>(MutexGuard<'a, protocol::Span>);
629644

645+
impl<'a> Data<'a> {
646+
/// Set some extra information to be sent with this Span.
647+
pub fn set_data(&mut self, key: String, value: protocol::Value) {
648+
self.0.data.insert(key, value);
649+
}
650+
651+
/// Set some tag to be sent with this Span.
652+
pub fn set_tag(&mut self, key: String, value: String) {
653+
self.0.tags.insert(key, value);
654+
}
655+
}
656+
630657
impl<'a> Deref for Data<'a> {
631658
type Target = BTreeMap<String, protocol::Value>;
632659

sentry-tracing/src/converters.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use tracing_subscriber::layer::Context;
99
use tracing_subscriber::registry::LookupSpan;
1010

1111
use super::layer::SentrySpanData;
12+
use crate::TAGS_PREFIX;
1213

1314
/// Converts a [`tracing_core::Level`] to a Sentry [`Level`]
1415
fn convert_tracing_level(level: &tracing_core::Level) -> Level {
@@ -156,7 +157,7 @@ fn tags_from_event(fields: &mut BTreeMap<String, Value>) -> BTreeMap<String, Str
156157
let mut tags = BTreeMap::new();
157158

158159
fields.retain(|key, value| {
159-
let Some(key) = key.strip_prefix("tags.") else {
160+
let Some(key) = key.strip_prefix(TAGS_PREFIX) else {
160161
return true;
161162
};
162163
let string = match value {

sentry-tracing/src/layer.rs

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::borrow::Cow;
12
use std::cell::RefCell;
23
use std::collections::BTreeMap;
34

@@ -9,6 +10,7 @@ use tracing_subscriber::layer::{Context, Layer};
910
use tracing_subscriber::registry::LookupSpan;
1011

1112
use crate::converters::*;
13+
use crate::TAGS_PREFIX;
1214

1315
/// The action that Sentry should perform for a [`Metadata`]
1416
#[derive(Debug, Clone, Copy)]
@@ -142,6 +144,53 @@ where
142144
}
143145
}
144146

147+
#[inline(always)]
148+
fn record_fields<'a, K: AsRef<str> + Into<Cow<'a, str>>>(
149+
span: &TransactionOrSpan,
150+
data: BTreeMap<K, Value>,
151+
) {
152+
match span {
153+
TransactionOrSpan::Span(span) => {
154+
let mut span = span.data();
155+
for (key, value) in data {
156+
if let Some(stripped_key) = key.as_ref().strip_prefix(TAGS_PREFIX) {
157+
match value {
158+
Value::Bool(value) => {
159+
span.set_tag(stripped_key.to_owned(), value.to_string())
160+
}
161+
Value::Number(value) => {
162+
span.set_tag(stripped_key.to_owned(), value.to_string())
163+
}
164+
Value::String(value) => span.set_tag(stripped_key.to_owned(), value),
165+
_ => span.set_data(key.into().into_owned(), value),
166+
}
167+
} else {
168+
span.set_data(key.into().into_owned(), value);
169+
}
170+
}
171+
}
172+
TransactionOrSpan::Transaction(transaction) => {
173+
let mut transaction = transaction.data();
174+
for (key, value) in data {
175+
if let Some(stripped_key) = key.as_ref().strip_prefix(TAGS_PREFIX) {
176+
match value {
177+
Value::Bool(value) => {
178+
transaction.set_tag(stripped_key.into(), value.to_string())
179+
}
180+
Value::Number(value) => {
181+
transaction.set_tag(stripped_key.into(), value.to_string())
182+
}
183+
Value::String(value) => transaction.set_tag(stripped_key.into(), value),
184+
_ => transaction.set_data(key.into(), value),
185+
}
186+
} else {
187+
transaction.set_data(key.into(), value);
188+
}
189+
}
190+
}
191+
}
192+
}
193+
145194
/// Data that is attached to the tracing Spans `extensions`, in order to
146195
/// `finish` the corresponding sentry span `on_close`, and re-set its parent as
147196
/// the *current* span.
@@ -217,9 +266,7 @@ where
217266
};
218267
// Add the data from the original span to the sentry span.
219268
// This comes from typically the `fields` in `tracing::instrument`.
220-
for (key, value) in data {
221-
sentry_span.set_data(key, value);
222-
}
269+
record_fields(&sentry_span, data);
223270

224271
sentry_core::configure_scope(|scope| scope.set_span(Some(sentry_span.clone())));
225272

@@ -267,9 +314,7 @@ where
267314
let mut data = FieldVisitor::default();
268315
values.record(&mut data);
269316

270-
for (key, value) in data.json_values {
271-
span.set_data(&key, value);
272-
}
317+
record_fields(span, data.json_values);
273318
}
274319
}
275320

sentry-tracing/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,5 @@ mod layer;
145145

146146
pub use converters::*;
147147
pub use layer::*;
148+
149+
const TAGS_PREFIX: &str = "tags.";

0 commit comments

Comments
 (0)