Skip to content

Commit 912a697

Browse files
authored
feat(profiling): add namespace for profile metrics (#3229)
Sentry PR that added the `profles` use case: https://github.com/getsentry/sentry/pull/65152/files
1 parent e831ffe commit 912a697

File tree

9 files changed

+72
-1
lines changed

9 files changed

+72
-1
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
- Add SDK information to spans. ([#3178](https://github.com/getsentry/relay/pull/3178))
3131
- Filter null values from metrics summary tags. ([#3204](https://github.com/getsentry/relay/pull/3204))
3232
- Emit a usage metric for every span seen. ([#3209](https://github.com/getsentry/relay/pull/3209))
33+
- Add namespace for profile metrics. ([#3229](https://github.com/getsentry/relay/pull/3229))
3334

3435
## 24.2.0
3536

relay-base-schema/src/metrics/mri.rs

+4
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ pub enum MetricNamespace {
112112
Transactions,
113113
/// Metrics extracted from spans.
114114
Spans,
115+
/// Metrics extracted from profile functions.
116+
Profiles,
115117
/// User-defined metrics directly sent by SDKs and applications.
116118
Custom,
117119
/// An unknown and unsupported metric.
@@ -133,6 +135,7 @@ impl MetricNamespace {
133135
MetricNamespace::Sessions => "sessions",
134136
MetricNamespace::Transactions => "transactions",
135137
MetricNamespace::Spans => "spans",
138+
MetricNamespace::Profiles => "profiles",
136139
MetricNamespace::Custom => "custom",
137140
MetricNamespace::Unsupported => "unsupported",
138141
}
@@ -147,6 +150,7 @@ impl std::str::FromStr for MetricNamespace {
147150
"sessions" => Ok(Self::Sessions),
148151
"transactions" => Ok(Self::Transactions),
149152
"spans" => Ok(Self::Spans),
153+
"profiles" => Ok(Self::Profiles),
150154
"custom" => Ok(Self::Custom),
151155
_ => Ok(Self::Unsupported),
152156
}

relay-cogs/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ pub enum AppFeature {
135135
MetricsTransactions,
136136
/// Metrics in the spans namespace.
137137
MetricsSpans,
138+
/// Metrics in the profiles namespace.
139+
MetricsProfiles,
138140
/// Metrics in the sessions namespace.
139141
MetricsSessions,
140142
/// Metrics in the custom namespace.
@@ -163,6 +165,7 @@ impl AppFeature {
163165
Self::MetricMeta => "metric_meta",
164166
Self::MetricsTransactions => "metrics_transactions",
165167
Self::MetricsSpans => "metrics_spans",
168+
Self::MetricsProfiles => "metrics_profiles",
166169
Self::MetricsSessions => "metrics_sessions",
167170
Self::MetricsCustom => "metrics_custom",
168171
Self::MetricsUnsupported => "metrics_unsupported",

relay-dynamic-config/src/global.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,23 @@ pub struct Options {
9494
)]
9595
pub profile_metrics_sample_rate: f32,
9696

97-
/// Kill switch for shutting down profile metrics
97+
/// Kill switch for shutting down unsampled_profile metrics
9898
#[serde(
9999
rename = "profiling.profile_metrics.unsampled_profiles.enabled",
100100
deserialize_with = "default_on_error",
101101
skip_serializing_if = "is_default"
102102
)]
103103
pub unsampled_profiles_enabled: bool,
104104

105+
/// Kill switch for shutting down profile function metrics
106+
/// ingestion in the generic-metrics platform
107+
#[serde(
108+
rename = "profiling.generic_metrics.functions_ingestion.enabled",
109+
deserialize_with = "default_on_error",
110+
skip_serializing_if = "is_default"
111+
)]
112+
pub profiles_function_generic_metrics_enabled: bool,
113+
105114
/// Kill switch for controlling the cardinality limiter.
106115
#[serde(
107116
rename = "relay.cardinality-limiter.mode",
@@ -169,6 +178,7 @@ pub struct MetricBucketEncodings {
169178
sessions: MetricEncoding,
170179
transactions: MetricEncoding,
171180
spans: MetricEncoding,
181+
profiles: MetricEncoding,
172182
custom: MetricEncoding,
173183
unsupported: MetricEncoding,
174184
}
@@ -180,6 +190,7 @@ impl MetricBucketEncodings {
180190
MetricNamespace::Sessions => self.sessions,
181191
MetricNamespace::Transactions => self.transactions,
182192
MetricNamespace::Spans => self.spans,
193+
MetricNamespace::Profiles => self.profiles,
183194
MetricNamespace::Custom => self.custom,
184195
MetricNamespace::Unsupported => self.unsupported,
185196
}

relay-metrics/src/cogs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ fn to_app_feature(ns: MetricNamespace) -> AppFeature {
3838
MetricNamespace::Sessions => AppFeature::MetricsSessions,
3939
MetricNamespace::Transactions => AppFeature::MetricsTransactions,
4040
MetricNamespace::Spans => AppFeature::MetricsSpans,
41+
MetricNamespace::Profiles => AppFeature::MetricsProfiles,
4142
MetricNamespace::Custom => AppFeature::MetricsCustom,
4243
MetricNamespace::Unsupported => AppFeature::MetricsUnsupported,
4344
}

relay-server/src/services/project.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,7 @@ fn is_metric_namespace_valid(state: &ProjectState, namespace: &MetricNamespace)
12461246
state.has_feature(Feature::ExtractSpansAndSpanMetricsFromEvent)
12471247
|| state.has_feature(Feature::StandaloneSpanIngestion)
12481248
}
1249+
MetricNamespace::Profiles => true,
12491250
MetricNamespace::Custom => state.has_feature(Feature::CustomMetrics),
12501251
MetricNamespace::Unsupported => false,
12511252
}

relay-server/src/services/store.rs

+11
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,17 @@ impl StoreService {
772772
);
773773
return Ok(());
774774
}
775+
MetricNamespace::Profiles => {
776+
if !self
777+
.global_config
778+
.current()
779+
.options
780+
.profiles_function_generic_metrics_enabled
781+
{
782+
return Ok(());
783+
}
784+
KafkaTopic::MetricsGeneric
785+
}
775786
_ => KafkaTopic::MetricsGeneric,
776787
};
777788
let headers = BTreeMap::from([("namespace".to_string(), namespace.to_string())]);

relay-server/src/utils/metric_stats.rs

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub struct MetricStats {
1212
custom: Stat,
1313
sessions: Stat,
1414
spans: Stat,
15+
profiles: Stat,
1516
transactions: Stat,
1617
unsupported: Stat,
1718
}
@@ -60,6 +61,7 @@ impl MetricStats {
6061
MetricNamespace::Sessions => &mut self.sessions,
6162
MetricNamespace::Transactions => &mut self.transactions,
6263
MetricNamespace::Spans => &mut self.spans,
64+
MetricNamespace::Profiles => &mut self.profiles,
6365
MetricNamespace::Custom => &mut self.custom,
6466
MetricNamespace::Unsupported => &mut self.unsupported,
6567
}

tests/integration/test_metrics.py

+37
Original file line numberDiff line numberDiff line change
@@ -2053,3 +2053,40 @@ def test_missing_global_filters_enables_metric_extraction(
20532053
tx, _ = tx_consumer.get_event()
20542054
assert tx is not None
20552055
assert metrics_consumer.get_metrics()
2056+
2057+
2058+
def test_profiles_metrics(mini_sentry, relay):
2059+
relay = relay(mini_sentry, options=TEST_CONFIG)
2060+
2061+
project_id = 42
2062+
mini_sentry.add_basic_project_config(project_id)
2063+
2064+
timestamp = int(datetime.now(tz=timezone.utc).timestamp())
2065+
metrics_payload = f"profiles/foo:42|c|T{timestamp}\nprofiles/bar:17|c|T{timestamp}"
2066+
2067+
relay.send_metrics(project_id, metrics_payload)
2068+
2069+
envelope = mini_sentry.captured_events.get(timeout=3)
2070+
assert len(envelope.items) == 1
2071+
2072+
metrics_item = envelope.items[0]
2073+
assert metrics_item.type == "metric_buckets"
2074+
2075+
received_metrics = json.loads(metrics_item.get_bytes().decode())
2076+
received_metrics = sorted(received_metrics, key=lambda x: x["name"])
2077+
assert received_metrics == [
2078+
{
2079+
"timestamp": timestamp,
2080+
"width": 1,
2081+
"name": "c:profiles/bar@none",
2082+
"value": 17.0,
2083+
"type": "c",
2084+
},
2085+
{
2086+
"timestamp": timestamp,
2087+
"width": 1,
2088+
"name": "c:profiles/foo@none",
2089+
"value": 42.0,
2090+
"type": "c",
2091+
},
2092+
]

0 commit comments

Comments
 (0)