diff --git a/CHANGELOG.md b/CHANGELOG.md index f5a158bfb6..4cb832ccfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Use same keys for OTel span attributes and Sentry span data. ([#3457](https://github.com/getsentry/relay/pull/3457)) - Support passing owner when upserting Monitors. ([#3468](https://github.com/getsentry/relay/pull/3468)) - Extract `frames.slow`, `frames.frozen`, and `frames.total` metrics from mobile spans. ([#3473](https://github.com/getsentry/relay/pull/3473)) +- Extract `frames.delay` metric from mobile spans. ([#3472](https://github.com/getsentry/relay/pull/3472)) **Internal**: diff --git a/relay-dynamic-config/src/defaults.rs b/relay-dynamic-config/src/defaults.rs index 7b46f674c8..9b4bea4c01 100644 --- a/relay-dynamic-config/src/defaults.rs +++ b/relay-dynamic-config/src/defaults.rs @@ -727,6 +727,38 @@ fn span_metrics( .always(), ], }, + MetricSpec { + category: DataCategory::Span, + mri: "g:spans/mobile.frames_delay@second".into(), + field: Some("span.measurements.frames.delay.value".into()), + condition: Some(is_mobile.clone() & duration_condition.clone()), + tags: vec![ + Tag::with_key("transaction") + .from_field("span.sentry_tags.transaction") + .always(), + Tag::with_key("environment") + .from_field("span.sentry_tags.environment") + .always(), + Tag::with_key("release") + .from_field("span.sentry_tags.release") + .always(), + Tag::with_key("span.description") + .from_field("span.sentry_tags.description") + .always(), + Tag::with_key("span.op") + .from_field("span.sentry_tags.op") + .always(), + Tag::with_key("span.group") + .from_field("span.sentry_tags.group") + .always(), + Tag::with_key("device.class") + .from_field("span.sentry_tags.device.class") + .always(), + Tag::with_key("os.name") + .from_field("span.sentry_tags.os.name") + .always(), + ], + }, ]; if double_write_distributions_as_gauges { diff --git a/relay-event-normalization/src/normalize/span/tag_extraction.rs b/relay-event-normalization/src/normalize/span/tag_extraction.rs index 13f49fe9f7..ced5742931 100644 --- a/relay-event-normalization/src/normalize/span/tag_extraction.rs +++ b/relay-event-normalization/src/normalize/span/tag_extraction.rs @@ -8,7 +8,7 @@ use std::ops::ControlFlow; use once_cell::sync::Lazy; use regex::Regex; -use relay_base_schema::metrics::{InformationUnit, MetricUnit}; +use relay_base_schema::metrics::{DurationUnit, InformationUnit, MetricUnit}; use relay_event_schema::protocol::{ AppContext, BrowserContext, Event, Measurement, OsContext, Span, Timestamp, TraceContext, }; @@ -662,10 +662,15 @@ pub fn extract_measurements(span: &mut Span, is_mobile: bool) { if is_mobile { if let Some(data) = span.data.value() { - for (field, key) in [ - (&data.frames_frozen, "frames.frozen"), - (&data.frames_slow, "frames.slow"), - (&data.frames_total, "frames.total"), + for (field, key, unit) in [ + (&data.frames_frozen, "frames.frozen", MetricUnit::None), + (&data.frames_slow, "frames.slow", MetricUnit::None), + (&data.frames_total, "frames.total", MetricUnit::None), + ( + &data.frames_delay, + "frames.delay", + MetricUnit::Duration(DurationUnit::Second), + ), ] { if let Some(value) = match field.value() { Some(Value::F64(f)) => Some(*f), @@ -678,7 +683,7 @@ pub fn extract_measurements(span: &mut Span, is_mobile: bool) { key.into(), Measurement { value: value.into(), - unit: MetricUnit::None.into(), + unit: unit.into(), } .into(), ); diff --git a/relay-event-schema/src/protocol/span.rs b/relay-event-schema/src/protocol/span.rs index 92088f734d..5fcc9e5e5a 100644 --- a/relay-event-schema/src/protocol/span.rs +++ b/relay-event-schema/src/protocol/span.rs @@ -315,6 +315,10 @@ pub struct SpanData { #[metastructure(field = "sentry.frames.total", legacy_alias = "frames.total")] pub frames_total: Annotated, + // Frames Delay (in seconds) + #[metastructure(field = "frames.delay")] + pub frames_delay: Annotated, + /// Other fields in `span.data`. #[metastructure(additional_properties, pii = "true", retain = "true")] other: Object, @@ -512,7 +516,8 @@ mod tests { "code.namespace": "ns", "frames.slow": 1, "frames.frozen": 2, - "frames.total": 9 + "frames.total": 9, + "frames.delay": 100 }"#; let data = Annotated::::from_json(data) .unwrap() @@ -571,6 +576,9 @@ mod tests { frames_total: I64( 9, ), + frames_delay: I64( + 100, + ), other: { "bar": String( "3", diff --git a/relay-event-schema/src/protocol/span/convert.rs b/relay-event-schema/src/protocol/span/convert.rs index 0df665c36c..62cc4b493c 100644 --- a/relay-event-schema/src/protocol/span/convert.rs +++ b/relay-event-schema/src/protocol/span/convert.rs @@ -291,6 +291,7 @@ mod tests { frames_slow: ~, frames_frozen: ~, frames_total: ~, + frames_delay: ~, other: {}, }, sentry_tags: ~, diff --git a/relay-server/src/metrics_extraction/event.rs b/relay-server/src/metrics_extraction/event.rs index f1f10a4a98..8b2b739c13 100644 --- a/relay-server/src/metrics_extraction/event.rs +++ b/relay-server/src/metrics_extraction/event.rs @@ -1155,7 +1155,8 @@ mod tests { "data": { "frames.slow": 1, "frames.frozen": 2, - "frames.total": 9 + "frames.total": 9, + "frames.delay": 0.1 } }, { diff --git a/relay-server/src/metrics_extraction/snapshots/relay_server__metrics_extraction__event__tests__extract_span_metrics_mobile.snap b/relay-server/src/metrics_extraction/snapshots/relay_server__metrics_extraction__event__tests__extract_span_metrics_mobile.snap index fdcfec4593..f49fc457a8 100644 --- a/relay-server/src/metrics_extraction/snapshots/relay_server__metrics_extraction__event__tests__extract_span_metrics_mobile.snap +++ b/relay-server/src/metrics_extraction/snapshots/relay_server__metrics_extraction__event__tests__extract_span_metrics_mobile.snap @@ -116,6 +116,9 @@ expression: "(&event.value().unwrap().spans, metrics)" frames_total: I64( 9, ), + frames_delay: F64( + 0.1, + ), other: {}, }, sentry_tags: { @@ -136,6 +139,12 @@ expression: "(&event.value().unwrap().spans, metrics)" received: ~, measurements: Measurements( { + "frames.delay": Measurement { + value: 0.1, + unit: Duration( + Second, + ), + }, "frames.frozen": Measurement { value: 2.0, unit: None, @@ -407,6 +416,7 @@ expression: "(&event.value().unwrap().spans, metrics)" frames_slow: ~, frames_frozen: ~, frames_total: ~, + frames_delay: ~, other: {}, }, sentry_tags: { @@ -494,6 +504,7 @@ expression: "(&event.value().unwrap().spans, metrics)" frames_slow: ~, frames_frozen: ~, frames_total: ~, + frames_delay: ~, other: {}, }, sentry_tags: { @@ -859,6 +870,32 @@ expression: "(&event.value().unwrap().spans, metrics)" merges: 1, }, }, + Bucket { + timestamp: UnixTimestamp(1597976303), + width: 0, + name: MetricName( + "g:spans/mobile.frames_delay@second", + ), + value: Gauge( + GaugeValue { + last: 0.1, + min: 0.1, + max: 0.1, + sum: 0.1, + count: 1, + }, + ), + tags: { + "device.class": "1", + "os.name": "iOS", + "release": "1.2.3", + "span.op": "ui.load.initial_display", + "transaction": "gEt /api/:version/users/", + }, + metadata: BucketMetadata { + merges: 1, + }, + }, Bucket { timestamp: UnixTimestamp(1597976303), width: 0, diff --git a/relay-spans/src/span.rs b/relay-spans/src/span.rs index 7391aa8811..3cb41cf407 100644 --- a/relay-spans/src/span.rs +++ b/relay-spans/src/span.rs @@ -660,6 +660,7 @@ mod tests { frames_slow: ~, frames_frozen: ~, frames_total: ~, + frames_delay: ~, other: {}, }, sentry_tags: ~,