Skip to content

Commit dbfd1b3

Browse files
authored
feat(spans): Parse supabase span descriptions (#3153)
The description only contains the table name, e.g. `"from(users)"`. In the future, we might want to parse `data.query` as well. See https://github.com/supabase-community/sentry-integration-js/blob/bae59de7e86c916d9396e2e2de55e6ac17e646d6/index.js#L259
1 parent 626e1a3 commit dbfd1b3

File tree

4 files changed

+75
-1
lines changed

4 files changed

+75
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
- Extend GPU context with data for Unreal Engine crash reports. ([#3144](https://github.com/getsentry/relay/pull/3144))
88
- Parametrize transaction in dynamic sampling context. ([#3141](https://github.com/getsentry/relay/pull/3141))
9+
- Parse & scrub span description for supabase. ([#3153](https://github.com/getsentry/relay/pull/3153))
910

1011
**Bug Fixes**:
1112

relay-event-normalization/src/normalize/span/description/mod.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use relay_event_schema::protocol::Span;
1313
use url::Url;
1414

1515
use crate::regexes::{
16-
DB_SQL_TRANSACTION_CORE_DATA_REGEX, REDIS_COMMAND_REGEX, RESOURCE_NORMALIZER_REGEX,
16+
DB_SQL_TRANSACTION_CORE_DATA_REGEX, DB_SUPABASE_REGEX, REDIS_COMMAND_REGEX,
17+
RESOURCE_NORMALIZER_REGEX,
1718
};
1819
use crate::span::description::resource::COMMON_PATH_SEGMENTS;
1920
use crate::span::tag_extraction::HTTP_METHOD_EXTRACTOR_REGEX;
@@ -70,6 +71,11 @@ pub(crate) fn scrub_span_description(
7071
// The description will only contain the entity queried and
7172
// the query type ("User find" for example).
7273
Some(description.to_owned())
74+
} else if span_origin == Some("auto.db.supabase") {
75+
// The description only contains the table name, e.g. `"from(users)`.
76+
// In the future, we might want to parse `data.query` as well.
77+
// See https://github.com/supabase-community/sentry-integration-js/blob/master/index.js#L259
78+
scrub_supabase(description)
7379
} else {
7480
let (scrubbed, mode) = sql::scrub_queries(db_system, description);
7581
if let sql::Mode::Parsed(ast) = mode {
@@ -141,6 +147,13 @@ fn scrub_core_data(string: &str) -> Option<String> {
141147
}
142148
}
143149

150+
fn scrub_supabase(string: &str) -> Option<String> {
151+
match DB_SUPABASE_REGEX.replace_all(string, "{%s}") {
152+
Cow::Owned(scrubbed) => Some(scrubbed),
153+
Cow::Borrowed(_) => None,
154+
}
155+
}
156+
144157
fn scrub_http(string: &str) -> Option<String> {
145158
let (method, url) = string.split_once(' ')?;
146159
if !HTTP_METHOD_EXTRACTOR_REGEX.is_match(method) {

relay-event-normalization/src/normalize/span/tag_extraction.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,12 @@ pub fn extract_tags(
365365
} else {
366366
None
367367
}
368+
} else if span.origin.as_str() == Some("auto.db.supabase") {
369+
scrubbed_description.as_deref().map(|s| {
370+
s.trim_start_matches("from(")
371+
.trim_end_matches(')')
372+
.to_owned()
373+
})
368374
} else if span_op.starts_with("db") {
369375
span.description
370376
.value()
@@ -1428,4 +1434,44 @@ LIMIT 1
14281434
Some(&"Chrome".to_string())
14291435
);
14301436
}
1437+
1438+
#[test]
1439+
fn supabase() {
1440+
let json = r#"{
1441+
"description": "from(my_table00)",
1442+
"op": "db.select",
1443+
"origin": "auto.db.supabase",
1444+
"data": {
1445+
"query": [
1446+
"select(*,other(*))",
1447+
"in(something, (value1,value2))"
1448+
]
1449+
}
1450+
}"#;
1451+
1452+
let span = Annotated::<Span>::from_json(json)
1453+
.unwrap()
1454+
.into_value()
1455+
.unwrap();
1456+
1457+
let tags = extract_tags(
1458+
&span,
1459+
&Config {
1460+
max_tag_value_size: 200,
1461+
},
1462+
None,
1463+
None,
1464+
false,
1465+
None,
1466+
);
1467+
1468+
assert_eq!(
1469+
tags.get(&SpanTagKey::Description).map(String::as_str),
1470+
Some("from(my_table{%s})")
1471+
);
1472+
assert_eq!(
1473+
tags.get(&SpanTagKey::Domain).map(String::as_str),
1474+
Some("my_table{%s}")
1475+
);
1476+
}
14311477
}

relay-event-normalization/src/regexes.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,17 @@ pub static RESOURCE_NORMALIZER_REGEX: Lazy<Regex> = Lazy::new(|| {
8181

8282
pub static DB_SQL_TRANSACTION_CORE_DATA_REGEX: Lazy<Regex> =
8383
Lazy::new(|| Regex::new(r"(?P<int>\d+)").unwrap());
84+
85+
pub static DB_SUPABASE_REGEX: Lazy<Regex> = Lazy::new(|| {
86+
Regex::new(
87+
r"(?xi)
88+
# UUIDs.
89+
(?P<uuid>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}) |
90+
# Hexadecimal strings with more than 5 digits.
91+
(?P<hex>[a-f0-9]{5}[a-f0-9]+) |
92+
# Integer IDs with more than one digit.
93+
(?P<int>\d\d+)
94+
",
95+
)
96+
.unwrap()
97+
});

0 commit comments

Comments
 (0)