relay_event_normalization/normalize/span/
mod.rs1use regex::Regex;
4use relay_conventions::attributes::{
5 SENTRY__DSC__PROJECT_ID, SENTRY__DSC__TRACE_ID, SENTRY__DSC__TRANSACTION,
6};
7use relay_event_schema::protocol::{Event, SpanData, TraceContext};
8use relay_protocol::Annotated;
9use std::sync::LazyLock;
10
11use crate::NormalizationConfig;
12
13pub mod ai;
14pub mod country_subregion;
15pub mod description;
16pub mod exclusive_time;
17pub mod tag_extraction;
18
19pub static TABLE_NAME_REGEX: LazyLock<Regex> = LazyLock::new(|| {
21 Regex::new(
22 r"(?ix)
23 [0-9a-f]{8}_[0-9a-f]{4}_[0-9a-f]{4}_[0-9a-f]{4}_[0-9a-f]{12} |
24 [0-9a-f]{8,} |
25 \d\d+
26 ",
27 )
28 .unwrap()
29});
30
31pub fn normalize_conventions(event: &mut Event) {
33 if let Some(data) = event
34 .contexts
35 .value_mut()
36 .as_mut()
37 .and_then(|c| c.get_mut::<TraceContext>())
38 .map(|c| &mut c.data)
39 {
40 crate::eap::normalize_attribute_names(data);
41 }
42
43 if let Some(spans) = event.spans.value_mut() {
44 for data in spans
45 .iter_mut()
46 .filter_map(|span| span.value_mut().as_mut())
47 .map(|span| &mut span.data)
48 {
49 crate::eap::normalize_attribute_names(data);
50 }
51 }
52}
53
54pub fn normalize_app_start_spans(event: &mut Event) {
58 if !event.sdk_name().eq("sentry.javascript.react-native")
59 || !(event.sdk_version().starts_with("4.4")
60 || event.sdk_version().starts_with("4.3")
61 || event.sdk_version().starts_with("4.2")
62 || event.sdk_version().starts_with("4.1")
63 || event.sdk_version().starts_with("4.0")
64 || event.sdk_version().starts_with('3'))
65 {
66 return;
67 }
68
69 if let Some(spans) = event.spans.value_mut() {
70 for span in spans {
71 if let Some(span) = span.value_mut()
72 && let Some(op) = span.op.value()
73 {
74 if op == "app_start_cold" {
75 span.op.set_value(Some("app.start.cold".to_owned()));
76 break;
77 } else if op == "app_start_warm" {
78 span.op.set_value(Some("app.start.warm".to_owned()));
79 break;
80 }
81 }
82 }
83 }
84}
85
86pub fn normalize_dsc_for_event_spans(event: &mut Event, config: &NormalizationConfig) {
88 if let Some(ctx) = event.context_mut::<TraceContext>() {
89 normalize_dsc_for_span_data(&mut ctx.data, config);
90 }
91 if let Some(spans) = event.spans.value_mut() {
92 for span in spans {
93 if let Some(span) = span.value_mut() {
94 normalize_dsc_for_span_data(&mut span.data, config);
95 }
96 }
97 }
98}
99
100pub fn normalize_dsc_for_span_data(
102 span_data: &mut Annotated<SpanData>,
103 config: &NormalizationConfig,
104) {
105 let Some(dsc) = config.dsc else {
106 return;
107 };
108
109 let data = span_data.get_or_insert_with(SpanData::default);
110 data.insert_value(SENTRY__DSC__TRACE_ID, dsc.trace_id.to_string());
111 if let Some(project_id) = &dsc.project_id {
112 data.insert_value(SENTRY__DSC__PROJECT_ID, project_id.to_string());
113 }
114 match &dsc.transaction {
115 Some(tx) if tx.len() <= config.max_tag_value_length => {
118 data.insert_value(SENTRY__DSC__TRANSACTION, tx.clone())
119 }
120 Some(_) => data.insert_value(SENTRY__DSC__TRANSACTION, "".to_owned()),
122 None => drop(data.remove(SENTRY__DSC__TRANSACTION)),
123 }
124}