Skip to content

Commit 5d2e385

Browse files
authored
ref(spans): Always extract span metrics (#4991)
Followup to: #4976, which added the usage metric metric extraction config, but metric extraction itself is also again hidden behind the `produces_spans()` flag. Removes the flag check for the generic span metric extraction. #skip-changelog
1 parent 6acb213 commit 5d2e385

File tree

6 files changed

+27
-17
lines changed

6 files changed

+27
-17
lines changed

relay-server/src/metrics_extraction/event.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,9 @@ fn extract_span_metrics_for_event(
104104
}
105105
}
106106

107-
// This function assumes it is only called when span metrics should be extracted, hence we
108-
// extract the span root counter unconditionally.
107+
// We unconditionally run metric extraction for spans. The count per root, is technically
108+
// only required for configurations which do have dynamic sampling enabled. But for the
109+
// sake of simplicity we always add it here.
109110
let transaction = transactions::get_transaction_name(event);
110111
let bucket = create_span_root_counter(
111112
event,

relay-server/src/services/processor.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1427,7 +1427,6 @@ impl EnvelopeProcessorService {
14271427

14281428
// If spans were already extracted for an event, we rely on span processing to extract metrics.
14291429
let extract_spans = !spans_extracted.0
1430-
&& project_info.config.features.produces_spans()
14311430
&& utils::sample(global.options.span_extraction_sample_rate.unwrap_or(1.0)).is_keep();
14321431

14331432
let metrics = crate::metrics_extraction::event::extract_metrics(

relay-server/src/services/processor/metrics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ fn is_metric_namespace_valid(state: &ProjectInfo, namespace: MetricNamespace) ->
6060
match namespace {
6161
MetricNamespace::Sessions => true,
6262
MetricNamespace::Transactions => true,
63-
MetricNamespace::Spans => state.config.features.produces_spans(),
63+
MetricNamespace::Spans => true,
6464
MetricNamespace::Custom => state.has_feature(Feature::CustomMetrics),
6565
MetricNamespace::Stats => true,
6666
MetricNamespace::Unsupported => false,

tests/integration/test_metrics.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,7 @@ def test_transaction_metrics_extraction_external_relays(
10241024
assert len(metrics_envelope.items) == 1
10251025

10261026
payload = json.loads(metrics_envelope.items[0].get_bytes().decode())
1027-
assert len(payload) == 4
1027+
assert len(payload) == 6
10281028

10291029
by_name = {m["name"]: m for m in payload}
10301030
light_metric = by_name["d:transactions/duration_light@millisecond"]
@@ -1087,7 +1087,7 @@ def test_transaction_metrics_extraction_processing_relays(
10871087
tx_consumer.assert_empty()
10881088

10891089
if expect_metrics_extraction:
1090-
metrics = metrics_by_name(metrics_consumer, 4, timeout=3)
1090+
metrics = metrics_by_name(metrics_consumer, 6, timeout=3)
10911091
metric_usage = metrics["c:transactions/usage@none"]
10921092
assert metric_usage["tags"] == {}
10931093
assert metric_usage["value"] == 1.0
@@ -1332,20 +1332,22 @@ def test_limit_custom_measurements(
13321332
event, _ = transactions_consumer.get_event()
13331333
assert len(event["measurements"]) == 2
13341334

1335-
# Expect exactly 5 metrics:
1336-
# (transaction.duration, transaction.duration_light, transactions.count_per_root_project, 1 builtin, 1 custom)
1337-
metrics = metrics_by_name(metrics_consumer, 6)
1338-
metrics.pop("headers")
1339-
1340-
assert metrics.keys() == {
1335+
expected_metrics = {
13411336
"c:transactions/usage@none",
13421337
"d:transactions/duration@millisecond",
13431338
"d:transactions/duration_light@millisecond",
13441339
"c:transactions/count_per_root_project@none",
13451340
"d:transactions/measurements.foo@none",
13461341
"d:transactions/measurements.bar@none",
1342+
"c:spans/usage@none",
1343+
"c:spans/count_per_root_project@none",
13471344
}
13481345

1346+
metrics = metrics_by_name(metrics_consumer, len(expected_metrics))
1347+
metrics.pop("headers")
1348+
1349+
assert metrics.keys() == expected_metrics
1350+
13491351

13501352
@pytest.mark.parametrize("has_measurements_config", [True, False])
13511353
def test_do_not_drop_custom_measurements_in_static(
@@ -1856,7 +1858,7 @@ def test_metrics_extraction_with_computed_context_filters(
18561858
]
18571859

18581860
# Verify that all three metrics were extracted
1859-
metrics = metrics_by_name(metrics_consumer, 7)
1861+
metrics = metrics_by_name(metrics_consumer, 9)
18601862

18611863
# Check each extracted metric
18621864
for metric_name in metric_names:

tests/integration/test_outcome.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,11 +1452,11 @@ def make_envelope():
14521452
"source": "pop-relay",
14531453
"timestamp": time_within_delta(),
14541454
}
1455-
for category in [6, 11] # Profile, ProfileIndexed
1455+
for category in [DataCategory.PROFILE.value, DataCategory.PROFILE_INDEXED.value]
14561456
]
14571457

14581458
# Make sure the profile will not be counted as accepted:
1459-
metrics = metrics_by_name(metrics_consumer, 4)
1459+
metrics = metrics_by_name(metrics_consumer, 7)
14601460
assert "has_profile" not in metrics["d:transactions/duration@millisecond"]["tags"]
14611461
assert "has_profile" not in metrics["c:transactions/usage@none"]["tags"]
14621462

@@ -1621,10 +1621,10 @@ def make_envelope():
16211621
"source": "processing-relay",
16221622
"timestamp": time_within_delta(),
16231623
}
1624-
for category in [6, 11] # Profile, ProfileIndexed
1624+
for category in [DataCategory.PROFILE.value, DataCategory.PROFILE_INDEXED.value]
16251625
]
16261626

1627-
metrics = metrics_by_name(metrics_consumer, 4)
1627+
metrics = metrics_by_name(metrics_consumer, 7)
16281628
assert "has_profile" not in metrics["d:transactions/duration@millisecond"]["tags"]
16291629
assert "has_profile" not in metrics["c:transactions/usage@none"]["tags"]
16301630

tests/integration/test_store.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,14 @@ def test_processing_quota_transaction_indexing(
916916
timeout=3,
917917
)
918918

919+
# Ignore span metrics, they may be emitted because rate limits from transactions are not
920+
# currently enforced for spans, which they should be. See: https://github.com/getsentry/relay/issues/4961.
921+
metrics = {metric["name"] for (metric, _) in metrics_consumer.get_metrics()}
922+
assert metrics == {
923+
"c:spans/count_per_root_project@none",
924+
"c:spans/usage@none",
925+
}
926+
919927

920928
def test_events_buffered_before_auth(relay, mini_sentry):
921929
evt = threading.Event()

0 commit comments

Comments
 (0)