Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 109 additions & 4 deletions relay-server/src/metrics_extraction/transactions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};

use relay_base_schema::events::EventType;
use relay_common::time::UnixTimestamp;
Expand All @@ -24,6 +24,18 @@ pub mod types;
/// cardinality data such as raw URLs.
const PLACEHOLDER_UNPARAMETERIZED: &str = "<< unparameterized >>";

/// Tags we set on metrics for performance score measurements (e.g. `score.lcp.weight`).
///
/// These are a subset of "universal" tags.
const PERFORMANCE_SCORE_TAGS: [CommonTag; 6] = [
CommonTag::BrowserName,
CommonTag::Environment,
CommonTag::GeoCountryCode,
CommonTag::Release,
CommonTag::Transaction,
CommonTag::TransactionOp,
];

/// Extract HTTP method
/// See <https://github.com/getsentry/snuba/blob/2e038c13a50735d58cc9397a29155ab5422a62e5/snuba/datasets/errors_processor.py#L64-L67>.
fn extract_http_method(transaction: &Event) -> Option<String> {
Expand Down Expand Up @@ -263,6 +275,13 @@ impl TransactionExtractor<'_> {
let light_tags = extract_light_transaction_tags(event);

// Measurements
let measurement_names: BTreeSet<_> = event
.measurements
.value()
.into_iter()
.flat_map(|measurements| measurements.keys())
.map(String::as_str)
.collect();
if let Some(measurements) = event.measurements.value() {
for (name, annotated) in measurements.iter() {
let measurement = match annotated.value() {
Expand All @@ -275,9 +294,27 @@ impl TransactionExtractor<'_> {
None => continue,
};

// We treat a measurement as "performance score" if its name is the name of another
// measurement prefixed by `score.`.
let is_performance_score = name == "score.total"
|| name
.strip_prefix("score.weight.")
.or_else(|| name.strip_prefix("score."))
.map_or(false, |suffix| measurement_names.contains(suffix));
Comment on lines +299 to +303
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is clumsy: It would be better to mark measurements as "performance score" somehow, but they might originate from a downstream relay so any kind of flag would have to be serialized into the event JSON.


let measurement_tags = TransactionMeasurementTags {
measurement_rating: get_measurement_rating(name, value),
universal_tags: tags.clone(),
universal_tags: if is_performance_score {
CommonTags(
tags.0
.iter()
.filter(|&(key, _)| PERFORMANCE_SCORE_TAGS.contains(key))
.map(|(key, value)| (key.clone(), value.clone()))
.collect::<BTreeMap<_, _>>(),
)
} else {
tags.clone()
},
};

metrics.project_metrics.push(
Expand Down Expand Up @@ -434,11 +471,12 @@ mod tests {
use relay_dynamic_config::AcceptTransactionNames;
use relay_event_normalization::{
normalize_event, set_default_transaction_source, BreakdownsConfig,
DynamicMeasurementsConfig, MeasurementsConfig, NormalizationConfig,
DynamicMeasurementsConfig, MeasurementsConfig, NormalizationConfig, PerformanceScoreConfig,
PerformanceScoreProfile, PerformanceScoreWeightedComponent,
};
use relay_event_schema::protocol::User;
use relay_metrics::BucketValue;
use relay_protocol::Annotated;
use relay_protocol::{Annotated, RuleCondition};

use super::*;

Expand Down Expand Up @@ -520,6 +558,19 @@ mod tests {
breakdowns_config: Some(&breakdowns_config),
enrich_spans: false,
normalize_spans: true,
performance_score: Some(&PerformanceScoreConfig {
profiles: vec![PerformanceScoreProfile {
name: Some("".into()),
score_components: vec![PerformanceScoreWeightedComponent {
measurement: "lcp".into(),
weight: 0.5,
p10: 2.0,
p50: 3.0,
optional: false,
}],
condition: Some(RuleCondition::all()),
}],
}),
..Default::default()
},
)
Expand Down Expand Up @@ -629,6 +680,60 @@ mod tests {
"transaction.status": "ok",
},
},
Bucket {
timestamp: UnixTimestamp(1619420400),
width: 0,
name: "d:transactions/measurements.score.lcp@ratio",
value: Distribution(
[
0.0,
],
),
tags: {
"browser.name": "Chrome",
"environment": "fake_environment",
"geo.country_code": "US",
"release": "1.2.3",
"transaction": "gEt /api/:version/users/",
"transaction.op": "mYOp",
},
},
Bucket {
timestamp: UnixTimestamp(1619420400),
width: 0,
name: "d:transactions/measurements.score.total@ratio",
value: Distribution(
[
0.0,
],
),
tags: {
"browser.name": "Chrome",
"environment": "fake_environment",
"geo.country_code": "US",
"release": "1.2.3",
"transaction": "gEt /api/:version/users/",
"transaction.op": "mYOp",
},
},
Bucket {
timestamp: UnixTimestamp(1619420400),
width: 0,
name: "d:transactions/measurements.score.weight.lcp@ratio",
value: Distribution(
[
1.0,
],
),
tags: {
"browser.name": "Chrome",
"environment": "fake_environment",
"geo.country_code": "US",
"release": "1.2.3",
"transaction": "gEt /api/:version/users/",
"transaction.op": "mYOp",
},
},
Bucket {
timestamp: UnixTimestamp(1619420400),
width: 0,
Expand Down