Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(profiles): Extract thread ID and name in spans #3771

Merged
merged 10 commits into from
Jul 3, 2024
105 changes: 105 additions & 0 deletions relay-event-normalization/src/normalize/span/tag_extraction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ pub enum SpanTagKey {
TraceStatus,
MessagingDestinationName,
MessagingMessageId,
ThreadName,
ThreadId,
}

impl SpanTagKey {
Expand Down Expand Up @@ -132,6 +134,8 @@ impl SpanTagKey {
SpanTagKey::TraceStatus => "trace.status",
SpanTagKey::MessagingDestinationName => "messaging.destination.name",
SpanTagKey::MessagingMessageId => "messaging.message.id",
SpanTagKey::ThreadName => "thread.name",
SpanTagKey::ThreadId => "thread.id",
}
}
}
Expand Down Expand Up @@ -404,6 +408,16 @@ fn extract_segment_tags(event: &Event) -> BTreeMap<SpanTagKey, String> {
}
}
}

if let Some(data) = trace_context.data.value() {
if let Some(thread_id) = data.thread_id.value() {
tags.insert(SpanTagKey::ThreadId, thread_id.to_string());
}

if let Some(thread_name) = data.thread_name.value() {
tags.insert(SpanTagKey::ThreadName, thread_name.to_string());
}
}
}

tags
Expand Down Expand Up @@ -752,6 +766,16 @@ pub fn extract_tags(
span_tags.insert(SpanTagKey::BrowserName, browser_name.clone());
}

if let Some(data) = span.data.value() {
if let Some(thread_id) = data.thread_id.value() {
span_tags.insert(SpanTagKey::ThreadId, thread_id.to_string());
}

if let Some(thread_name) = data.thread_name.value().and_then(|name| name.as_str()) {
span_tags.insert(SpanTagKey::ThreadName, thread_name.into());
}
}

span_tags
}

Expand Down Expand Up @@ -2430,4 +2454,85 @@ LIMIT 1
"[email protected]"
);
}

#[test]
fn extract_thread_id_name_from_span_data_into_sentry_tags() {
let json = r#"
{
"type": "transaction",
"platform": "javascript",
"start_timestamp": "2021-04-26T07:59:01+0100",
"timestamp": "2021-04-26T08:00:00+0100",
"transaction": "foo",
"contexts": {
"trace": {
"trace_id": "ff62a8b040f340bda5d830223def1d81",
"span_id": "bd429c44b67a3eb4"
}
},
"spans": [
{
"op": "before_first_display",
"span_id": "bd429c44b67a3eb1",
"start_timestamp": 1597976300.0000000,
"timestamp": 1597976302.0000000,
"trace_id": "ff62a8b040f340bda5d830223def1d81",
"data": {
"thread.name": "main",
"thread.id": 42
}
}
]
}
"#;

let mut event = Annotated::<Event>::from_json(json).unwrap();

normalize_event(
&mut event,
&NormalizationConfig {
enrich_spans: true,
..Default::default()
},
);

let spans = get_value!(event.spans!);
let span = &spans[0];

assert_eq!(get_value!(span.sentry_tags["thread.id"]!), "42",);
assert_eq!(get_value!(span.sentry_tags["thread.name"]!), "main",);
}

#[test]
fn extract_thread_id_name_from_trace_context_into_sentry_tags() {
let json = r#"
{
"type": "transaction",
"platform": "python",
"start_timestamp": "2021-04-26T07:59:01+0100",
"timestamp": "2021-04-26T08:00:00+0100",
"transaction": "foo",
"contexts": {
"trace": {
"op": "queue.process",
"status": "ok",
"data": {
"thread.name": "main",
"thread.id": 42
}
}
}
}
"#;

let event = Annotated::<Event>::from_json(json)
.unwrap()
.into_value()
.unwrap();

let tags = extract_segment_tags(&event);

assert_eq!(tags.get(&SpanTagKey::ThreadId), Some(&"42".to_string()));
assert_eq!(tags.get(&SpanTagKey::ThreadName), Some(&"main".to_string()));
}
}
10 changes: 9 additions & 1 deletion relay-event-schema/src/protocol/contexts/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use relay_jsonschema_derive::JsonSchema;
use relay_protocol::{Annotated, Empty, Error, FromValue, IntoValue, Object, Value};

use crate::processor::ProcessValue;
use crate::protocol::{OperationType, OriginType, SpanStatus};
use crate::protocol::{OperationType, OriginType, SpanStatus, ThreadId};

/// A 32-character hex string as described in the W3C trace context spec.
#[derive(Clone, Debug, Default, PartialEq, Empty, IntoValue, ProcessValue)]
Expand Down Expand Up @@ -191,6 +191,14 @@ pub struct Data {
#[metastructure(field = "messaging.message.body.size")]
pub messaging_message_body_size: Annotated<Value>,

/// The ID of the thread from which the transaction originated from
#[metastructure(field = "thread.id")]
pub thread_id: Annotated<ThreadId>,

/// The name of the thread from which the transaction originated from
#[metastructure(field = "thread.name")]
pub thread_name: Annotated<String>,

/// Additional arbitrary fields for forwards compatibility.
#[metastructure(
additional_properties,
Expand Down
6 changes: 5 additions & 1 deletion relay-event-schema/src/protocol/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use relay_protocol::{Annotated, Empty, FromValue, Getter, IntoValue, Object, Val
use crate::processor::ProcessValue;
use crate::protocol::{
EventId, JsonLenientString, LenientString, Measurements, MetricsSummary, OperationType,
OriginType, SpanId, SpanStatus, Timestamp, TraceId,
OriginType, SpanId, SpanStatus, ThreadId, Timestamp, TraceId,
};

#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
Expand Down Expand Up @@ -314,6 +314,10 @@ pub struct SpanData {
#[metastructure(field = "thread.name")]
pub thread_name: Annotated<Value>,

/// ID of thread from where the span originated.
#[metastructure(field = "thread.id")]
pub thread_id: Annotated<ThreadId>,

/// Name of the segment that this span belongs to (see `segment_id`).
///
/// This corresponds to the transaction name in the transaction-based model.
Expand Down
11 changes: 11 additions & 0 deletions relay-event-schema/src/protocol/thread.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::fmt;

#[cfg(feature = "jsonschema")]
use relay_jsonschema_derive::JsonSchema;
use relay_protocol::{
Expand Down Expand Up @@ -71,6 +73,15 @@ impl Empty for ThreadId {
}
}

impl fmt::Display for ThreadId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ThreadId::Int(id) => write!(f, "{}", id),
ThreadId::String(id) => write!(f, "{}", id),
}
}
}

/// Possible lock types responsible for a thread's blocked state
#[derive(Debug, Copy, Clone, Eq, PartialEq, ProcessValue, Empty)]
#[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
Expand Down
Loading
Loading