Skip to content

Commit

Permalink
feat(performance): Update performance score calculation to checking p…
Browse files Browse the repository at this point in the history
…rofiles after the first match (#3804)

Updates the performance score calculation to break after find a profile
with a matching condition. This prevents any subsequent matching
profiles from overwriting calculated performance scores. This is needed
because we will be adding a `default` fallback profile with a condition
matching on any to the bottom of the profiles list.

#skip-changelog
  • Loading branch information
edwardgou-sentry committed Jul 11, 2024
1 parent bae3dc0 commit 447507c
Showing 1 changed file with 332 additions and 0 deletions.
332 changes: 332 additions & 0 deletions relay-event-normalization/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,7 @@ pub fn normalize_performance_score(
);
}
}
break; // Stop after the first matching profile.
}
}
}
Expand Down Expand Up @@ -3348,6 +3349,337 @@ mod tests {
"###);
}

#[test]
fn test_computed_performance_score_uses_first_matching_profile() {
let json = r#"
{
"type": "transaction",
"timestamp": "2021-04-26T08:00:05+0100",
"start_timestamp": "2021-04-26T08:00:00+0100",
"measurements": {
"a": {"value": 213, "unit": "millisecond"},
"b": {"value": 213, "unit": "millisecond"}
},
"contexts": {
"browser": {
"name": "Chrome",
"version": "120.1.1",
"type": "browser"
}
}
}
"#;

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

let performance_score: PerformanceScoreConfig = serde_json::from_value(json!({
"profiles": [
{
"name": "Mobile",
"scoreComponents": [
{
"measurement": "a",
"weight": 0.15,
"p10": 100,
"p50": 200,
},
{
"measurement": "b",
"weight": 0.30,
"p10": 100,
"p50": 200,
"optional": true
},
{
"measurement": "c",
"weight": 0.55,
"p10": 100,
"p50": 200,
"optional": true
},
],
"condition": {
"op":"eq",
"name": "event.contexts.browser.name",
"value": "Chrome Mobile"
}
},
{
"name": "Desktop",
"scoreComponents": [
{
"measurement": "a",
"weight": 0.15,
"p10": 900,
"p50": 1600,
},
{
"measurement": "b",
"weight": 0.30,
"p10": 1200,
"p50": 2400,
"optional": true
},
{
"measurement": "c",
"weight": 0.55,
"p10": 1200,
"p50": 2400,
"optional": true
},
],
"condition": {
"op":"eq",
"name": "event.contexts.browser.name",
"value": "Chrome"
}
},
{
"name": "Default",
"scoreComponents": [
{
"measurement": "a",
"weight": 0.15,
"p10": 100,
"p50": 200,
},
{
"measurement": "b",
"weight": 0.30,
"p10": 100,
"p50": 200,
"optional": true
},
{
"measurement": "c",
"weight": 0.55,
"p10": 100,
"p50": 200,
"optional": true
},
],
"condition": {
"op": "and",
"inner": [],
}
}
]
}))
.unwrap();

normalize_performance_score(&mut event, Some(&performance_score));

insta::assert_ron_snapshot!(SerializableAnnotated(&Annotated::new(event)), {}, @r###"
{
"type": "transaction",
"timestamp": 1619420405.0,
"start_timestamp": 1619420400.0,
"contexts": {
"browser": {
"name": "Chrome",
"version": "120.1.1",
"type": "browser",
},
},
"measurements": {
"a": {
"value": 213.0,
"unit": "millisecond",
},
"b": {
"value": 213.0,
"unit": "millisecond",
},
"score.a": {
"value": 0.33333215313291975,
"unit": "ratio",
},
"score.b": {
"value": 0.66666415149198,
"unit": "ratio",
},
"score.total": {
"value": 0.9999963046248997,
"unit": "ratio",
},
"score.weight.a": {
"value": 0.33333333333333337,
"unit": "ratio",
},
"score.weight.b": {
"value": 0.6666666666666667,
"unit": "ratio",
},
"score.weight.c": {
"value": 0.0,
"unit": "ratio",
},
},
}
"###);
}

#[test]
fn test_computed_performance_score_falls_back_to_default_profile() {
let json = r#"
{
"type": "transaction",
"timestamp": "2021-04-26T08:00:05+0100",
"start_timestamp": "2021-04-26T08:00:00+0100",
"measurements": {
"a": {"value": 213, "unit": "millisecond"},
"b": {"value": 213, "unit": "millisecond"}
},
"contexts": {}
}
"#;

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

let performance_score: PerformanceScoreConfig = serde_json::from_value(json!({
"profiles": [
{
"name": "Mobile",
"scoreComponents": [
{
"measurement": "a",
"weight": 0.15,
"p10": 900,
"p50": 1600,
"optional": true
},
{
"measurement": "b",
"weight": 0.30,
"p10": 1200,
"p50": 2400,
"optional": true
},
{
"measurement": "c",
"weight": 0.55,
"p10": 1200,
"p50": 2400,
"optional": true
},
],
"condition": {
"op":"eq",
"name": "event.contexts.browser.name",
"value": "Chrome Mobile"
}
},
{
"name": "Desktop",
"scoreComponents": [
{
"measurement": "a",
"weight": 0.15,
"p10": 900,
"p50": 1600,
"optional": true
},
{
"measurement": "b",
"weight": 0.30,
"p10": 1200,
"p50": 2400,
"optional": true
},
{
"measurement": "c",
"weight": 0.55,
"p10": 1200,
"p50": 2400,
"optional": true
},
],
"condition": {
"op":"eq",
"name": "event.contexts.browser.name",
"value": "Chrome"
}
},
{
"name": "Default",
"scoreComponents": [
{
"measurement": "a",
"weight": 0.15,
"p10": 100,
"p50": 200,
"optional": true
},
{
"measurement": "b",
"weight": 0.30,
"p10": 100,
"p50": 200,
"optional": true
},
{
"measurement": "c",
"weight": 0.55,
"p10": 100,
"p50": 200,
"optional": true
},
],
"condition": {
"op": "and",
"inner": [],
}
}
]
}))
.unwrap();

normalize_performance_score(&mut event, Some(&performance_score));

insta::assert_ron_snapshot!(SerializableAnnotated(&Annotated::new(event)), {}, @r###"
{
"type": "transaction",
"timestamp": 1619420405.0,
"start_timestamp": 1619420400.0,
"contexts": {},
"measurements": {
"a": {
"value": 213.0,
"unit": "millisecond",
},
"b": {
"value": 213.0,
"unit": "millisecond",
},
"score.a": {
"value": 0.15121816827413334,
"unit": "ratio",
},
"score.b": {
"value": 0.3024363365482667,
"unit": "ratio",
},
"score.total": {
"value": 0.4536545048224,
"unit": "ratio",
},
"score.weight.a": {
"value": 0.33333333333333337,
"unit": "ratio",
},
"score.weight.b": {
"value": 0.6666666666666667,
"unit": "ratio",
},
"score.weight.c": {
"value": 0.0,
"unit": "ratio",
},
},
}
"###);
}

#[test]
fn test_normalization_removes_reprocessing_context() {
let json = r#"{
Expand Down

0 comments on commit 447507c

Please sign in to comment.