Skip to content

Commit

Permalink
ref(spans): Reduced set of metrics/tags for all orgs (#2924)
Browse files Browse the repository at this point in the history
Follow-up to #2907: Apply reduced
set of span metrics and tags regardless of feature flag.

ref: getsentry/team-ingest#252
  • Loading branch information
jjbayer committed Jan 10, 2024
1 parent 3c6811d commit 4bccbbb
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 998 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
- Introduce the configuration option `http.global_metrics`. When enabled, Relay submits metric buckets not through regular project-scoped Envelopes, but instead through the global endpoint. When this Relay serves a high number of projects, this can reduce the overall request volume. ([#2902](https://github.com/getsentry/relay/pull/2902))
- Record the size of global metrics requests in statsd as `upstream.metrics.body_size`. ([#2908](https://github.com/getsentry/relay/pull/2908))
- Make Kafka spans compatible with the Snuba span schema. ([#2917](https://github.com/getsentry/relay/pull/2917), [#2926](https://github.com/getsentry/relay/pull/2926))
- Only extract span metrics / tags when they are needed. ([#2907](https://github.com/getsentry/relay/pull/2907), [#2923](https://github.com/getsentry/relay/pull/2923))
- Only extract span metrics / tags when they are needed. ([#2907](https://github.com/getsentry/relay/pull/2907), [#2923](https://github.com/getsentry/relay/pull/2923), [#2924](https://github.com/getsentry/relay/pull/2924))
- Normalize metric resource identifiers in `event._metrics_summary` and `span._metrics_summary`. ([#2914](https://github.com/getsentry/relay/pull/2914))

## 23.12.1
Expand Down
352 changes: 2 additions & 350 deletions relay-dynamic-config/src/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,364 +47,16 @@ pub fn add_span_metrics(project_config: &mut ProjectConfig) {
return;
}

// The "all-modules" feature flag is our de-facto feature flag for experimental features.
// Hijack it for the new, more restrictive config.
let is_experimental = project_config
.features
.has(Feature::SpanMetricsExtractionAllModules);

if is_experimental {
config.metrics.extend(span_metrics_reduced());
} else {
config.metrics.extend(span_metrics_legacy());
};
config.metrics.extend(span_metrics());

config._span_metrics_extended = true;
if config.version == 0 {
config.version = MetricExtractionConfig::VERSION;
}
}

/// The original set of metrics & tags.
fn span_metrics_legacy() -> impl IntoIterator<Item = MetricSpec> {
let is_disabled = RuleCondition::glob("span.op", DISABLED_DATABASES);
let is_mongo = RuleCondition::eq("span.system", "mongodb")
| RuleCondition::glob("span.description", MONGODB_QUERIES);
let resource_condition = RuleCondition::glob("span.op", RESOURCE_SPAN_OPS);

let span_op_conditions = RuleCondition::eq("span.op", "http.client")
| RuleCondition::glob("span.op", MOBILE_OPS)
| RuleCondition::glob("span.op", "file.*")
| (RuleCondition::glob("span.op", "db*") & !is_disabled & !is_mongo)
| resource_condition.clone();

// For mobile spans, only extract duration metrics when they are below a threshold.
let duration_condition = RuleCondition::negate(RuleCondition::glob("span.op", MOBILE_OPS))
| RuleCondition::lte(
"span.exclusive_time",
Number::from_f64(MAX_DURATION_MOBILE_MS).unwrap_or(0.into()),
);
let mobile_condition = RuleCondition::eq("span.sentry_tags.mobile", "true");
let app_start_condition = RuleCondition::glob("span.op", "app.start.*")
& RuleCondition::eq("span.description", APP_START_ROOT_SPAN_DESCRIPTIONS);

[
MetricSpec {
category: DataCategory::Span,
mri: "d:spans/exclusive_time@millisecond".into(),
field: Some("span.exclusive_time".into()),
condition: Some(span_op_conditions.clone() & duration_condition.clone()),
tags: vec![
// Common tags:
Tag::with_key("environment")
.from_field("span.sentry_tags.environment")
.always(),
Tag::with_key("transaction.method")
.from_field("span.sentry_tags.transaction.method")
.always(),
Tag::with_key("transaction.op")
.from_field("span.sentry_tags.transaction.op")
.always(),
Tag::with_key("span.action")
.from_field("span.sentry_tags.action")
.always(),
Tag::with_key("span.category")
.from_field("span.sentry_tags.category")
.always(),
Tag::with_key("span.description")
.from_field("span.sentry_tags.description")
.always(),
Tag::with_key("span.domain")
.from_field("span.sentry_tags.domain")
.always(),
Tag::with_key("span.group")
.from_field("span.sentry_tags.group")
.always(),
Tag::with_key("span.module")
.from_field("span.sentry_tags.module")
.always(),
Tag::with_key("span.op")
.from_field("span.sentry_tags.op")
.always(),
Tag::with_key("span.status")
.from_field("span.status") // from top-level field
.always(),
Tag::with_key("span.status_code")
.from_field("span.sentry_tags.status_code")
.always(),
Tag::with_key("span.system")
.from_field("span.sentry_tags.system")
.always(),
Tag::with_key("transaction")
.from_field("span.sentry_tags.transaction")
.always(),
// Mobile:
Tag::with_key("device.class")
.from_field("span.sentry_tags.device.class")
.when(mobile_condition.clone()),
Tag::with_key("os.name") // TODO: might not be needed on both `exclusive_time` metrics
.from_field("span.sentry_tags.os.name")
.when(mobile_condition.clone()),
Tag::with_key("release")
.from_field("span.sentry_tags.release")
.when(mobile_condition.clone()),
Tag::with_key("ttfd")
.from_field("span.sentry_tags.ttfd")
.when(mobile_condition.clone()),
Tag::with_key("ttid")
.from_field("span.sentry_tags.ttid")
.when(mobile_condition.clone()),
Tag::with_key("span.main_thread")
.from_field("span.sentry_tags.main_thread")
.when(mobile_condition.clone()),
// Resource module:
Tag::with_key("file_extension")
.from_field("span.sentry_tags.file_extension")
.when(resource_condition.clone()),
Tag::with_key("resource.render_blocking_status")
.from_field("span.sentry_tags.resource.render_blocking_status")
.when(resource_condition.clone()),
],
},
MetricSpec {
category: DataCategory::Span,
mri: "d:spans/exclusive_time_light@millisecond".into(),
field: Some("span.exclusive_time".into()),
condition: Some(span_op_conditions.clone() & duration_condition.clone()),
tags: vec![
Tag::with_key("environment")
.from_field("span.sentry_tags.environment")
.always(),
Tag::with_key("transaction.method")
.from_field("span.sentry_tags.transaction.method")
.always(),
Tag::with_key("transaction.op")
.from_field("span.sentry_tags.transaction.op")
.always(),
Tag::with_key("span.action")
.from_field("span.sentry_tags.action")
.always(),
Tag::with_key("span.category")
.from_field("span.sentry_tags.category")
.always(),
Tag::with_key("span.description")
.from_field("span.sentry_tags.description")
.always(),
Tag::with_key("span.domain")
.from_field("span.sentry_tags.domain")
.always(),
Tag::with_key("span.group")
.from_field("span.sentry_tags.group")
.always(),
Tag::with_key("span.module")
.from_field("span.sentry_tags.module")
.always(),
Tag::with_key("span.op")
.from_field("span.sentry_tags.op")
.always(),
Tag::with_key("span.status")
.from_field("span.status") // from top-level field
.always(),
Tag::with_key("span.status_code")
.from_field("span.sentry_tags.status_code")
.always(),
Tag::with_key("span.system")
.from_field("span.sentry_tags.system")
.always(),
// Mobile:
Tag::with_key("device.class")
.from_field("span.sentry_tags.device.class")
.when(mobile_condition.clone()),
Tag::with_key("os.name") // TODO: might not be needed on both `exclusive_time` metrics
.from_field("span.sentry_tags.os.name")
.when(mobile_condition.clone()),
Tag::with_key("release")
.from_field("span.sentry_tags.release")
.when(mobile_condition.clone()),
// Resource module:
Tag::with_key("file_extension")
.from_field("span.sentry_tags.file_extension")
.when(resource_condition.clone()),
Tag::with_key("resource.render_blocking_status")
.from_field("span.sentry_tags.resource.render_blocking_status")
.when(resource_condition.clone()),
],
},
MetricSpec {
category: DataCategory::Span,
mri: "d:spans/http.response_content_length@byte".into(),
field: Some("span.data.http\\.response_content_length".into()),
condition: Some(
span_op_conditions.clone()
& resource_condition.clone()
& RuleCondition::gt("span.data.http\\.response_content_length", 0),
),
tags: vec![
Tag::with_key("environment")
.from_field("span.sentry_tags.environment")
.always(), // already guarded by condition on metric
Tag::with_key("file_extension")
.from_field("span.sentry_tags.file_extension")
.always(), // already guarded by condition on metric
Tag::with_key("resource.render_blocking_status")
.from_field("span.sentry_tags.resource.render_blocking_status")
.always(), // already guarded by condition on metric
Tag::with_key("span.description")
.from_field("span.sentry_tags.description")
.always(), // already guarded by condition on metric
Tag::with_key("span.domain")
.from_field("span.sentry_tags.domain")
.always(), // already guarded by condition on metric
Tag::with_key("span.group")
.from_field("span.sentry_tags.group")
.always(), // already guarded by condition on metric
Tag::with_key("span.op")
.from_field("span.sentry_tags.op")
.always(), // already guarded by condition on metric
Tag::with_key("transaction")
.from_field("span.sentry_tags.transaction")
.always(), // already guarded by condition on metric
],
},
MetricSpec {
category: DataCategory::Span,
mri: "d:spans/http.decoded_response_content_length@byte".into(),
field: Some("span.data.http\\.decoded_response_content_length".into()),
condition: Some(
span_op_conditions.clone()
& resource_condition.clone()
& RuleCondition::gt("span.data.http\\.decoded_response_content_length", 0),
),
tags: vec![
Tag::with_key("environment")
.from_field("span.sentry_tags.environment")
.always(), // already guarded by condition on metric
Tag::with_key("file_extension")
.from_field("span.sentry_tags.file_extension")
.always(), // already guarded by condition on metric
Tag::with_key("resource.render_blocking_status")
.from_field("span.sentry_tags.resource.render_blocking_status")
.always(), // already guarded by condition on metric
Tag::with_key("span.description")
.from_field("span.sentry_tags.description")
.always(), // already guarded by condition on metric
Tag::with_key("span.domain")
.from_field("span.sentry_tags.domain")
.always(), // already guarded by condition on metric
Tag::with_key("span.group")
.from_field("span.sentry_tags.group")
.always(), // already guarded by condition on metric
Tag::with_key("span.op")
.from_field("span.sentry_tags.op")
.always(), // already guarded by condition on metric
],
},
MetricSpec {
category: DataCategory::Span,
mri: "d:spans/http.response_transfer_size@byte".into(),
field: Some("span.data.http\\.response_transfer_size".into()),
condition: Some(
span_op_conditions.clone()
& resource_condition.clone()
& RuleCondition::gt("span.data.http\\.response_transfer_size", 0),
),
tags: vec![
Tag::with_key("environment")
.from_field("span.sentry_tags.environment")
.always(), // already guarded by condition on metric
Tag::with_key("file_extension")
.from_field("span.sentry_tags.file_extension")
.always(), // already guarded by condition on metric
Tag::with_key("resource.render_blocking_status")
.from_field("span.sentry_tags.resource.render_blocking_status")
.always(), // already guarded by condition on metric
Tag::with_key("span.description")
.from_field("span.sentry_tags.description")
.always(), // already guarded by condition on metric
Tag::with_key("span.domain")
.from_field("span.sentry_tags.domain")
.always(), // already guarded by condition on metric
Tag::with_key("span.group")
.from_field("span.sentry_tags.group")
.always(), // already guarded by condition on metric
Tag::with_key("span.op")
.from_field("span.sentry_tags.op")
.always(), // already guarded by condition on metric
],
},
MetricSpec {
category: DataCategory::Span,
mri: "c:spans/count_per_op@none".into(),
field: None,
condition: Some(duration_condition.clone()),
tags: vec![
Tag::with_key("span.category")
.from_field("span.sentry_tags.category")
.always(),
Tag::with_key("span.op")
.from_field("span.sentry_tags.op")
.always(),
Tag::with_key("span.system")
.from_field("span.sentry_tags.system")
.always(),
],
},
MetricSpec {
category: DataCategory::Span,
mri: "c:spans/count_per_segment@none".into(),
field: None,
condition: Some(mobile_condition.clone() & duration_condition.clone()),
tags: vec![
Tag::with_key("transaction.op")
.from_field("span.sentry_tags.transaction.op")
.always(),
Tag::with_key("transaction")
.from_field("span.sentry_tags.transaction")
.always(),
Tag::with_key("release")
.from_field("span.sentry_tags.release")
.always(), // mobile only - already guarded by condition on metric
],
},
MetricSpec {
category: DataCategory::Span,
mri: "d:spans/duration@millisecond".into(),
field: Some("span.duration".into()),
condition: Some(
duration_condition.clone() & mobile_condition.clone() & app_start_condition.clone(),
),
tags: vec![
Tag::with_key("span.op")
.from_field("span.sentry_tags.op")
.always(), // already guarded by condition on metric
Tag::with_key("span.description")
.from_field("span.sentry_tags.description")
.always(), // already guarded by condition on metric
Tag::with_key("span.group")
.from_field("span.sentry_tags.group")
.always(), // already guarded by condition on metric
Tag::with_key("transaction")
.from_field("span.sentry_tags.transaction")
.always(), // already guarded by condition on metric
Tag::with_key("device.class")
.from_field("span.sentry_tags.device.class")
.always(), // already guarded by condition on metric
Tag::with_key("release")
.from_field("span.sentry_tags.release")
.always(), // already guarded by condition on metric
Tag::with_key("os.name")
.from_field("span.sentry_tags.os.name")
.always(), // already guarded by condition on metric
Tag::with_key("environment")
.from_field("span.sentry_tags.environment")
.always(), // already guarded by condition on metric
],
},
]
}

/// Metrics with tags applied as required.
fn span_metrics_reduced() -> impl IntoIterator<Item = MetricSpec> {
fn span_metrics() -> impl IntoIterator<Item = MetricSpec> {
let is_db = RuleCondition::eq("span.sentry_tags.category", "db")
& !(RuleCondition::eq("span.system", "mongodb")
| RuleCondition::glob("span.op", DISABLED_DATABASES)
Expand Down
Loading

0 comments on commit 4bccbbb

Please sign in to comment.