Skip to content

Commit

Permalink
feat(webvitals): adds optional performance score components (#2783)
Browse files Browse the repository at this point in the history
Adds support for an `optional` PerformanceScoreWeightedComponent.
Measurements that are marked optional will not block performance score
processing if they are missing, and will have their weight set to 0.
  • Loading branch information
edwardgou-sentry authored Nov 30, 2023
1 parent 2508800 commit 24b39d0
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

- Ingest OpenTelemetry and standalone Sentry spans via HTTP or an envelope. ([#2620](https://github.com/getsentry/relay/pull/2620))
- Partition and split metric buckets just before sending. Log outcomes for metrics. ([#2682](https://github.com/getsentry/relay/pull/2682))
- Support optional `PerformanceScoreWeightedComponent` in performance score processing. ([#2783](https://github.com/getsentry/relay/pull/2783))
- Return global config ready status to downstream relays. ([#2765](https://github.com/getsentry/relay/pull/2765))
- Add Mixed JS/Android Profiles events processing. ([#2706](https://github.com/getsentry/relay/pull/2706))
- Allow to ingest measurements on a span. ([#2792](https://github.com/getsentry/relay/pull/2792))
Expand Down
4 changes: 4 additions & 0 deletions relay-event-normalization/src/normalize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ pub struct PerformanceScoreWeightedComponent {
pub p10: f64,
/// Median used to define the log-normal for calculation
pub p50: f64,
/// Whether the measurement is optional. If the measurement is missing, performance score processing
/// may still continue, and the weight will be 0.
#[serde(default)]
pub optional: bool,
}

/// Defines a profile for performance score.
Expand Down
128 changes: 124 additions & 4 deletions relay-event-normalization/src/normalize/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,20 +736,29 @@ fn normalize_performance_score(
if profile.score_components.iter().any(|c| {
!measurements.contains_key(c.measurement.as_str())
&& c.weight.abs() >= f64::EPSILON
&& !c.optional
}) {
// All measurements with a profile weight greater than 0 are required to exist
// on the event. Skip calculating performance scores if a measurement with
// weight is missing.
// All non-optional measurements with a profile weight greater than 0 are
// required to exist on the event. Skip calculating performance scores if
// a measurement with weight is missing.
break;
}
let mut score_total = 0.0;
let mut weight_total = 0.0;
for component in &profile.score_components {
// Skip optional components if they are not present on the event.
if component.optional
&& !measurements.contains_key(component.measurement.as_str())
{
continue;
}
weight_total += component.weight;
}
for component in &profile.score_components {
let normalized_component_weight = component.weight / weight_total;
// Optional measurements that are not present are given a weight of 0.
let mut normalized_component_weight = 0.0;
if let Some(value) = measurements.get_value(component.measurement.as_str()) {
normalized_component_weight = component.weight / weight_total;
let cdf = utils::calculate_cdf_score(value, component.p10, component.p50);
let component_score = cdf * normalized_component_weight;
score_total += component_score;
Expand Down Expand Up @@ -2221,4 +2230,115 @@ mod tests {
}
"###);
}

#[test]
fn test_computed_performance_score_optional_measurement() {
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": "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"
}
}
]
}))
.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",
},
},
}
"###);
}
}

0 comments on commit 24b39d0

Please sign in to comment.