From 94cb3df759108f483b7cf3c2f41e0c6262eefb06 Mon Sep 17 00:00:00 2001 From: David Herberth Date: Thu, 28 Mar 2024 17:02:16 +0100 Subject: [PATCH 1/2] feat(metric-stats): Report cardinality to metric stats --- CHANGELOG.md | 1 + relay-cardinality/benches/redis_impl.rs | 4 +- relay-cardinality/src/config.rs | 2 +- relay-cardinality/src/limiter.rs | 2 +- relay-cardinality/src/redis/cache.rs | 6 +- relay-cardinality/src/redis/limiter.rs | 6 +- relay-cardinality/src/redis/script.rs | 8 +-- relay-cardinality/src/redis/state.rs | 2 +- relay-server/src/metric_stats.rs | 80 ++++++++++++++++++++++++- relay-server/src/service.rs | 4 +- relay-server/src/services/processor.rs | 12 ++++ relay-server/src/testutils.rs | 13 +++- tests/integration/test_metric_stats.py | 55 +++++++++++++++-- 13 files changed, 171 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 150e54b0f96..e99c6f94cb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Apply rate limits to span metrics. ([#3255](https://github.com/getsentry/relay/pull/3255)) - Extract metrics from transaction spans. ([#3273](https://github.com/getsentry/relay/pull/3273), [#3324](https://github.com/getsentry/relay/pull/3324)) - Implement volume metric stats. ([#3281](https://github.com/getsentry/relay/pull/3281)) +- Implement cardinality metric stats. ([#3360](https://github.com/getsentry/relay/pull/3360)) - Scrub transactions before enforcing quotas. ([#3248](https://github.com/getsentry/relay/pull/3248)) - Implement metric name based cardinality limits. ([#3313](https://github.com/getsentry/relay/pull/3313)) - Kafka topic config supports default topic names as keys. ([#3282](https://github.com/getsentry/relay/pull/3282)) diff --git a/relay-cardinality/benches/redis_impl.rs b/relay-cardinality/benches/redis_impl.rs index 42561e82d03..96d356c9a4c 100644 --- a/relay-cardinality/benches/redis_impl.rs +++ b/relay-cardinality/benches/redis_impl.rs @@ -58,7 +58,7 @@ struct Params { } impl Params { - fn new(limit: u64, rounds: usize, num_hashes: usize) -> Self { + fn new(limit: u32, rounds: usize, num_hashes: usize) -> Self { Self { limits: vec![CardinalityLimit { id: "limit".to_owned(), @@ -140,7 +140,7 @@ impl Params { EntryId(usize::MAX - i as usize), MetricNamespace::Custom, &self.name, - i as u32, + i, ) }) .collect::>() diff --git a/relay-cardinality/src/config.rs b/relay-cardinality/src/config.rs index f67f9c458f3..cc3ac72594e 100644 --- a/relay-cardinality/src/config.rs +++ b/relay-cardinality/src/config.rs @@ -28,7 +28,7 @@ pub struct CardinalityLimit { /// The sliding window to enforce the cardinality limits in. pub window: SlidingWindow, /// The cardinality limit. - pub limit: u64, + pub limit: u32, /// Scope which the limit applies to. pub scope: CardinalityScope, diff --git a/relay-cardinality/src/limiter.rs b/relay-cardinality/src/limiter.rs index 1a0339a9011..29d5aca9aa5 100644 --- a/relay-cardinality/src/limiter.rs +++ b/relay-cardinality/src/limiter.rs @@ -44,7 +44,7 @@ pub struct CardinalityReport { pub name: Option, /// The current cardinality. - pub cardinality: u64, + pub cardinality: u32, } /// Accumulator of all cardinality limiter decisions. diff --git a/relay-cardinality/src/redis/cache.rs b/relay-cardinality/src/redis/cache.rs index 5a85573aaaa..51d0742a149 100644 --- a/relay-cardinality/src/redis/cache.rs +++ b/relay-cardinality/src/redis/cache.rs @@ -96,7 +96,7 @@ impl<'a> CacheRead<'a> { Self { inner, timestamp } } - pub fn check(&self, scope: &QuotaScoping, hash: u32, limit: u64) -> CacheOutcome { + pub fn check(&self, scope: &QuotaScoping, hash: u32, limit: u32) -> CacheOutcome { let Some(cache) = self.inner.cache.get(scope) else { return CacheOutcome::Unknown; }; @@ -166,7 +166,7 @@ struct ScopedCache { } impl ScopedCache { - fn check(&self, slot: Slot, hash: u32, limit: u64) -> CacheOutcome { + fn check(&self, slot: Slot, hash: u32, limit: u32) -> CacheOutcome { if slot != self.current_slot { return CacheOutcome::Unknown; } @@ -174,7 +174,7 @@ impl ScopedCache { if self.hashes.contains(&hash) { // Local cache copy contains the hash -> accept it straight away CacheOutcome::Accepted - } else if self.hashes.len() as u64 >= limit { + } else if self.hashes.len().try_into().unwrap_or(u32::MAX) >= limit { // We have more or the same amount of items in the local cache as the cardinality // limit -> this new item/hash is rejected. CacheOutcome::Rejected diff --git a/relay-cardinality/src/redis/limiter.rs b/relay-cardinality/src/redis/limiter.rs index 0492b14c9df..4da5929cbe1 100644 --- a/relay-cardinality/src/redis/limiter.rs +++ b/relay-cardinality/src/redis/limiter.rs @@ -91,7 +91,7 @@ impl RedisSetLimiter { .inspect(|(_, result)| { metric!( histogram(CardinalityLimiterHistograms::RedisSetCardinality) = - result.cardinality, + result.cardinality as u64, id = state.id(), ); }) @@ -188,7 +188,7 @@ impl Limiter for RedisSetLimiter { struct CheckedLimits { scope: QuotaScoping, - cardinality: u64, + cardinality: u32, entries: Vec, statuses: Vec, } @@ -292,7 +292,7 @@ mod tests { } #[track_caller] - fn assert_cardinality(&self, limit: &CardinalityLimit, cardinality: u64) { + fn assert_cardinality(&self, limit: &CardinalityLimit, cardinality: u32) { let Some(r) = self.reports.get(limit) else { panic!("expected cardinality report for limit {limit:?}"); }; diff --git a/relay-cardinality/src/redis/script.rs b/relay-cardinality/src/redis/script.rs index ba01bf44a11..563ef1d5fbb 100644 --- a/relay-cardinality/src/redis/script.rs +++ b/relay-cardinality/src/redis/script.rs @@ -36,7 +36,7 @@ impl FromRedisValue for Status { #[derive(Debug)] pub struct CardinalityScriptResult { /// Cardinality of the limit. - pub cardinality: u64, + pub cardinality: u32, /// Status for each hash passed to the script. pub statuses: Vec, } @@ -124,7 +124,7 @@ impl CardinalityScript { /// Returns a [`redis::ScriptInvocation`] with all keys and arguments prepared. fn prepare_invocation( &self, - limit: u64, + limit: u32, expire: u64, hashes: impl Iterator, keys: impl Iterator, @@ -156,7 +156,7 @@ impl<'a> CardinalityScriptPipeline<'a> { /// Adds another invocation of the script to the pipeline. pub fn add_invocation( &mut self, - limit: u64, + limit: u32, expire: u64, hashes: impl Iterator, keys: impl Iterator, @@ -196,7 +196,7 @@ mod tests { fn invoke_one( &self, con: &mut Connection, - limit: u64, + limit: u32, expire: u64, hashes: impl Iterator, keys: impl Iterator, diff --git a/relay-cardinality/src/redis/state.rs b/relay-cardinality/src/redis/state.rs index 155dc71f4b0..0908f3f2f60 100644 --- a/relay-cardinality/src/redis/state.rs +++ b/relay-cardinality/src/redis/state.rs @@ -16,7 +16,7 @@ use crate::{ #[derive(Debug)] pub struct LimitState<'a> { /// The limit of the quota. - pub limit: u64, + pub limit: u32, /// Scoping of the quota. partial_scope: PartialQuotaScoping, diff --git a/relay-server/src/metric_stats.rs b/relay-server/src/metric_stats.rs index cb2f74846c6..16e1cd5738d 100644 --- a/relay-server/src/metric_stats.rs +++ b/relay-server/src/metric_stats.rs @@ -1,8 +1,11 @@ use std::collections::BTreeMap; use std::sync::{Arc, OnceLock}; +use relay_cardinality::{CardinalityLimit, CardinalityReport}; use relay_config::Config; -use relay_metrics::{Aggregator, Bucket, BucketValue, MergeBuckets, MetricName, UnixTimestamp}; +use relay_metrics::{ + Aggregator, Bucket, BucketValue, GaugeValue, MergeBuckets, MetricName, UnixTimestamp, +}; use relay_quotas::Scoping; use relay_system::Addr; @@ -18,6 +21,14 @@ fn volume_metric_mri() -> MetricName { .clone() } +fn cardinality_metric_mri() -> MetricName { + static CARDINALITY_METRIC_MRI: OnceLock = OnceLock::new(); + + CARDINALITY_METRIC_MRI + .get_or_init(|| "g:metric_stats/cardinality@none".into()) + .clone() +} + /// Tracks stats about metrics. /// /// Metric stats are similar to outcomes for envelopes, they record @@ -48,7 +59,7 @@ impl MetricStats { /// Tracks the metric volume and outcome for the bucket. pub fn track(&self, scoping: Scoping, bucket: Bucket, outcome: Outcome) { - if !self.config.processing_enabled() || !self.is_rolled_out(scoping.organization_id) { + if !self.is_enabled(scoping) { return; } @@ -66,6 +77,35 @@ impl MetricStats { .send(MergeBuckets::new(scoping.project_key, vec![volume])); } + /// Tracks the cardinality of a metric. + pub fn cardinality( + &self, + scoping: Scoping, + limit: &CardinalityLimit, + report: &CardinalityReport, + ) { + if !self.is_enabled(scoping) { + return; + } + + let Some(cardinality) = self.to_cardinality_metric(limit, report) else { + return; + }; + + relay_log::trace!( + "Tracking cardinality '{}' for mri '{}': {}", + limit.id, + report.name.as_deref().unwrap_or("-"), + report.cardinality, + ); + self.aggregator + .send(MergeBuckets::new(scoping.project_key, vec![cardinality])); + } + + fn is_enabled(&self, scoping: Scoping) -> bool { + self.config.processing_enabled() && self.is_rolled_out(scoping.organization_id) + } + fn is_rolled_out(&self, organization_id: u64) -> bool { let rate = self .global_config @@ -109,6 +149,42 @@ impl MetricStats { metadata: Default::default(), }) } + + fn to_cardinality_metric( + &self, + limit: &CardinalityLimit, + report: &CardinalityReport, + ) -> Option { + let cardinality = report.cardinality; + if cardinality == 0 { + return None; + } + + let name = report.name.as_ref()?; + let namespace = name.namespace(); + + if !namespace.has_metric_stats() { + return None; + } + + let tags = BTreeMap::from([ + ("mri".to_owned(), name.to_string()), + ("mri.namespace".to_owned(), namespace.to_string()), + ( + "cardinality.window".to_owned(), + limit.window.window_seconds.to_string(), + ), + ]); + + Some(Bucket { + timestamp: UnixTimestamp::now(), + width: 0, + name: cardinality_metric_mri(), + value: BucketValue::Gauge(GaugeValue::single(cardinality.into())), + tags, + metadata: Default::default(), + }) + } } #[cfg(test)] diff --git a/relay-server/src/service.rs b/relay-server/src/service.rs index cef36d19e9c..d41fc3a8dbc 100644 --- a/relay-server/src/service.rs +++ b/relay-server/src/service.rs @@ -152,7 +152,7 @@ impl ServiceState { config.clone(), global_config_handle.clone(), outcome_aggregator.clone(), - metric_stats, + metric_stats.clone(), )? .start_in(rt), ), @@ -180,6 +180,8 @@ impl ServiceState { aggregator.clone(), #[cfg(feature = "processing")] store.clone(), + #[cfg(feature = "processing")] + metric_stats, ) .spawn_handler(processor_rx); diff --git a/relay-server/src/services/processor.rs b/relay-server/src/services/processor.rs index a4dbeb67607..f83f95a6131 100644 --- a/relay-server/src/services/processor.rs +++ b/relay-server/src/services/processor.rs @@ -48,6 +48,7 @@ use tokio::sync::Semaphore; #[cfg(feature = "processing")] use { + crate::metric_stats::MetricStats, crate::services::store::{Store, StoreEnvelope}, crate::utils::{EnvelopeLimiter, ItemAction, MetricsLimiter}, itertools::Itertools, @@ -929,6 +930,8 @@ struct InnerProcessor { cardinality_limiter: Option, #[cfg(feature = "processing")] store_forwarder: Option>, + #[cfg(feature = "processing")] + metric_stats: MetricStats, } impl EnvelopeProcessorService { @@ -945,6 +948,7 @@ impl EnvelopeProcessorService { test_store: Addr, #[cfg(feature = "processing")] aggregator: Addr, #[cfg(feature = "processing")] store_forwarder: Option>, + #[cfg(feature = "processing")] metric_stats: MetricStats, ) -> Self { let geoip_lookup = config.geoip_path().and_then(|p| { match GeoIpLookup::open(p).context(ServiceError::GeoIp) { @@ -991,6 +995,8 @@ impl EnvelopeProcessorService { .map(CardinalityLimiter::new), #[cfg(feature = "processing")] store_forwarder, + #[cfg(feature = "processing")] + metric_stats, config, }; @@ -2178,6 +2184,12 @@ impl EnvelopeProcessorService { } } + for (limit, reports) in limits.cardinality_reports() { + for report in reports { + self.inner.metric_stats.cardinality(scoping, limit, report); + } + } + if matches!(cardinality_limiter_mode, CardinalityLimiterMode::Passive) { return limits.into_source(); } diff --git a/relay-server/src/testutils.rs b/relay-server/src/testutils.rs index 9a569c6b1bc..01382d23906 100644 --- a/relay-server/src/testutils.rs +++ b/relay-server/src/testutils.rs @@ -14,6 +14,8 @@ use relay_test::mock_service; use crate::envelope::{Envelope, Item, ItemType}; use crate::extractors::RequestMeta; +#[cfg(feature = "processing")] +use crate::metric_stats::MetricStats; use crate::services::global_config::GlobalConfigHandle; use crate::services::outcome::TrackOutcome; use crate::services::processor::EnvelopeProcessorService; @@ -125,8 +127,9 @@ pub fn create_test_processor(config: Config) -> EnvelopeProcessorService { .filter(|_| config.processing_enabled()) .map(|redis_config| relay_redis::RedisPool::new(redis_config).unwrap()); + let config = Arc::new(config); EnvelopeProcessorService::new( - Arc::new(config), + Arc::clone(&config), GlobalConfigHandle::fixed(Default::default()), Cogs::noop(), #[cfg(feature = "processing")] @@ -136,9 +139,15 @@ pub fn create_test_processor(config: Config) -> EnvelopeProcessorService { upstream_relay, test_store, #[cfg(feature = "processing")] - _aggregator, + _aggregator.clone(), #[cfg(feature = "processing")] None, + #[cfg(feature = "processing")] + MetricStats::new( + config, + GlobalConfigHandle::fixed(Default::default()), + _aggregator, + ), ) } diff --git a/tests/integration/test_metric_stats.py b/tests/integration/test_metric_stats.py index d7b73fa0d76..6e531832e81 100644 --- a/tests/integration/test_metric_stats.py +++ b/tests/integration/test_metric_stats.py @@ -8,22 +8,26 @@ @dataclass class MetricStatsByMri: volume: dict[str, Any] + cardinality: dict[str, Any] other: list[Any] def metric_stats_by_mri(metrics_consumer, count, timeout=None): volume = dict() + cardinality = dict() other = list() for _ in range(count): metric, _ = metrics_consumer.get_metric(timeout) if metric["name"] == "c:metric_stats/volume@none": volume[metric["tags"]["mri"]] = metric + elif metric["name"] == "g:metric_stats/cardinality@none": + cardinality[metric["tags"]["mri"]] = metric else: other.append(metric) metrics_consumer.assert_empty() - return MetricStatsByMri(volume=volume, other=other) + return MetricStatsByMri(volume=volume, cardinality=cardinality, other=other) @pytest.mark.parametrize("mode", ["default", "chain"]) @@ -56,12 +60,25 @@ def test_metric_stats_simple( "organizations:custom-metrics", "organizations:metric-stats", ] + project_config["config"]["metrics"] = { + "cardinalityLimits": [ + { + "id": "custom", + "window": {"windowSeconds": 3600, "granularitySeconds": 600}, + "report": True, + "limit": 100, + "scope": "name", + "namespace": "custom", + } + ] + } relay.send_metrics( - project_id, "custom/foo:1337|d\ncustom/foo:12|d\ncustom/bar:42|s" + project_id, "custom/foo:1337|d\ncustom/foo:12|d|#tag:value\ncustom/bar:42|s" ) - metrics = metric_stats_by_mri(metrics_consumer, 4) + metrics = metric_stats_by_mri(metrics_consumer, 7) + assert metrics.volume["d:custom/foo@none"]["org_id"] == 0 assert metrics.volume["d:custom/foo@none"]["project_id"] == project_id assert metrics.volume["d:custom/foo@none"]["value"] == 2.0 @@ -78,7 +95,37 @@ def test_metric_stats_simple( "mri.namespace": "custom", "outcome.id": "0", } - assert len(metrics.other) == 2 + assert len(metrics.volume) == 2 + assert metrics.cardinality["d:custom/foo@none"]["org_id"] == 0 + assert metrics.cardinality["d:custom/foo@none"]["project_id"] == project_id + assert metrics.cardinality["d:custom/foo@none"]["value"] == { + "count": 1, + "last": 2.0, + "max": 2.0, + "min": 2.0, + "sum": 2.0, + } + assert metrics.cardinality["d:custom/foo@none"]["tags"] == { + "mri": "d:custom/foo@none", + "mri.namespace": "custom", + "cardinality.window": "3600", + } + assert metrics.cardinality["s:custom/bar@none"]["org_id"] == 0 + assert metrics.cardinality["s:custom/bar@none"]["project_id"] == project_id + assert metrics.cardinality["s:custom/bar@none"]["value"] == { + "count": 1, + "last": 1.0, + "max": 1.0, + "min": 1.0, + "sum": 1.0, + } + assert metrics.cardinality["s:custom/bar@none"]["tags"] == { + "mri": "s:custom/bar@none", + "mri.namespace": "custom", + "cardinality.window": "3600", + } + assert len(metrics.cardinality) == 2 + assert len(metrics.other) == 3 def test_metric_stats_max_flush_bytes( From 239e00078f86b5151d1d63266f6f9b08f8d4463c Mon Sep 17 00:00:00 2001 From: David Herberth Date: Wed, 3 Apr 2024 10:31:54 +0200 Subject: [PATCH 2/2] naming issues --- relay-cardinality/benches/redis_impl.rs | 2 +- relay-cardinality/src/limiter.rs | 10 +++++----- relay-cardinality/src/redis/limiter.rs | 4 ++-- relay-server/src/metric_stats.rs | 12 ++++++------ relay-server/src/services/processor.rs | 4 +++- relay-server/src/services/store.rs | 3 ++- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/relay-cardinality/benches/redis_impl.rs b/relay-cardinality/benches/redis_impl.rs index 96d356c9a4c..ebed52f373c 100644 --- a/relay-cardinality/benches/redis_impl.rs +++ b/relay-cardinality/benches/redis_impl.rs @@ -43,7 +43,7 @@ struct NoopReporter; impl<'a> Reporter<'a> for NoopReporter { fn reject(&mut self, _limit_id: &'a CardinalityLimit, _entry_id: EntryId) {} - fn cardinality(&mut self, _limit: &'a CardinalityLimit, _report: CardinalityReport) {} + fn report_cardinality(&mut self, _limit: &'a CardinalityLimit, _report: CardinalityReport) {} } #[derive(Debug)] diff --git a/relay-cardinality/src/limiter.rs b/relay-cardinality/src/limiter.rs index 29d5aca9aa5..58f1b2098ef 100644 --- a/relay-cardinality/src/limiter.rs +++ b/relay-cardinality/src/limiter.rs @@ -59,7 +59,7 @@ pub trait Reporter<'a> { /// /// For example, with a name scoped limit can be called once for every /// metric name matching the limit. - fn cardinality(&mut self, limit: &'a CardinalityLimit, report: CardinalityReport); + fn report_cardinality(&mut self, limit: &'a CardinalityLimit, report: CardinalityReport); } /// Limiter responsible to enforce limits. @@ -204,7 +204,7 @@ impl<'a> Reporter<'a> for DefaultReporter<'a> { } #[inline(always)] - fn cardinality(&mut self, limit: &'a CardinalityLimit, report: CardinalityReport) { + fn report_cardinality(&mut self, limit: &'a CardinalityLimit, report: CardinalityReport) { if !limit.report { return; } @@ -624,7 +624,7 @@ mod tests { I: IntoIterator>, T: Reporter<'a>, { - reporter.cardinality( + reporter.report_cardinality( &limits[0], CardinalityReport { organization_id: Some(scoping.organization_id), @@ -634,7 +634,7 @@ mod tests { }, ); - reporter.cardinality( + reporter.report_cardinality( &limits[0], CardinalityReport { organization_id: Some(scoping.organization_id), @@ -644,7 +644,7 @@ mod tests { }, ); - reporter.cardinality( + reporter.report_cardinality( &limits[2], CardinalityReport { organization_id: Some(scoping.organization_id), diff --git a/relay-cardinality/src/redis/limiter.rs b/relay-cardinality/src/redis/limiter.rs index 4da5929cbe1..2461d4941fd 100644 --- a/relay-cardinality/src/redis/limiter.rs +++ b/relay-cardinality/src/redis/limiter.rs @@ -163,7 +163,7 @@ impl Limiter for RedisSetLimiter { })?; for result in results { - reporter.cardinality(state.cardinality_limit(), result.to_report()); + reporter.report_cardinality(state.cardinality_limit(), result.to_report()); // This always acquires a write lock, but we only hit this // if we previously didn't satisfy the request from the cache, @@ -306,7 +306,7 @@ mod tests { self.entries.insert(entry_id); } - fn cardinality(&mut self, limit: &'a CardinalityLimit, report: CardinalityReport) { + fn report_cardinality(&mut self, limit: &'a CardinalityLimit, report: CardinalityReport) { let reports = self.reports.entry(limit.clone()).or_default(); reports.push(report); reports.sort(); diff --git a/relay-server/src/metric_stats.rs b/relay-server/src/metric_stats.rs index 16e1cd5738d..a6fd9831616 100644 --- a/relay-server/src/metric_stats.rs +++ b/relay-server/src/metric_stats.rs @@ -58,7 +58,7 @@ impl MetricStats { } /// Tracks the metric volume and outcome for the bucket. - pub fn track(&self, scoping: Scoping, bucket: Bucket, outcome: Outcome) { + pub fn track_metric(&self, scoping: Scoping, bucket: Bucket, outcome: Outcome) { if !self.is_enabled(scoping) { return; } @@ -78,7 +78,7 @@ impl MetricStats { } /// Tracks the cardinality of a metric. - pub fn cardinality( + pub fn track_cardinality( &self, scoping: Scoping, limit: &CardinalityLimit, @@ -239,10 +239,10 @@ mod tests { let scoping = scoping(); let mut bucket = Bucket::parse(b"rt@millisecond:57|d", UnixTimestamp::now()).unwrap(); - ms.track(scoping, bucket.clone(), Outcome::Accepted); + ms.track_metric(scoping, bucket.clone(), Outcome::Accepted); bucket.metadata.merges = bucket.metadata.merges.saturating_add(41); - ms.track( + ms.track_metric( scoping, bucket, Outcome::RateLimited(Some(ReasonCode::new("foobar"))), @@ -300,7 +300,7 @@ mod tests { let scoping = scoping(); let bucket = Bucket::parse(b"rt@millisecond:57|d", UnixTimestamp::now()).unwrap(); - ms.track(scoping, bucket, Outcome::Accepted); + ms.track_metric(scoping, bucket, Outcome::Accepted); drop(ms); @@ -314,7 +314,7 @@ mod tests { let scoping = scoping(); let bucket = Bucket::parse(b"transactions/rt@millisecond:57|d", UnixTimestamp::now()).unwrap(); - ms.track(scoping, bucket, Outcome::Accepted); + ms.track_metric(scoping, bucket, Outcome::Accepted); drop(ms); diff --git a/relay-server/src/services/processor.rs b/relay-server/src/services/processor.rs index f83f95a6131..07520e20379 100644 --- a/relay-server/src/services/processor.rs +++ b/relay-server/src/services/processor.rs @@ -2186,7 +2186,9 @@ impl EnvelopeProcessorService { for (limit, reports) in limits.cardinality_reports() { for report in reports { - self.inner.metric_stats.cardinality(scoping, limit, report); + self.inner + .metric_stats + .track_cardinality(scoping, limit, report); } } diff --git a/relay-server/src/services/store.rs b/relay-server/src/services/store.rs index a8360fd2b90..95dd2a76c35 100644 --- a/relay-server/src/services/store.rs +++ b/relay-server/src/services/store.rs @@ -402,7 +402,8 @@ impl StoreService { // This logic will be improved iterated on and change once we move serialization logic // back into the processor service. if has_success { - self.metric_stats.track(scoping, bucket, Outcome::Accepted); + self.metric_stats + .track_metric(scoping, bucket, Outcome::Accepted); } }