Skip to content

Commit 044595b

Browse files
committed
feat(metric-stats): Add additional tags to metric stats metrics
1 parent 9511e14 commit 044595b

File tree

2 files changed

+162
-10
lines changed

2 files changed

+162
-10
lines changed

relay-cardinality/src/config.rs

+13
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ pub enum CardinalityScope {
7777
Unknown,
7878
}
7979

80+
impl CardinalityScope {
81+
/// Returns the string representation of this scope.
82+
pub fn as_str(self) -> &'static str {
83+
match self {
84+
CardinalityScope::Organization => "organization",
85+
CardinalityScope::Project => "project",
86+
CardinalityScope::Type => "type",
87+
CardinalityScope::Name => "name",
88+
CardinalityScope::Unknown => "unknown",
89+
}
90+
}
91+
}
92+
8093
#[cfg(test)]
8194
mod tests {
8295
use super::*;

relay-server/src/metric_stats.rs

+149-10
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ impl MetricStats {
129129

130130
let mut tags = BTreeMap::from([
131131
("mri".to_owned(), bucket.name.to_string()),
132+
("mri.type".to_owned(), bucket.value.ty().to_string()),
132133
("mri.namespace".to_owned(), namespace.to_string()),
133134
(
134135
"outcome.id".to_owned(),
@@ -160,22 +161,30 @@ impl MetricStats {
160161
return None;
161162
}
162163

163-
let name = report.metric_name.as_ref()?;
164-
let namespace = name.namespace();
165-
166-
if !namespace.has_metric_stats() {
167-
return None;
168-
}
169-
170-
let tags = BTreeMap::from([
171-
("mri".to_owned(), name.to_string()),
172-
("mri.namespace".to_owned(), namespace.to_string()),
164+
let mut tags = BTreeMap::from([
165+
("cardinality.limit".to_owned(), limit.id.clone()),
166+
(
167+
"cardinality.scope".to_owned(),
168+
limit.scope.as_str().to_owned(),
169+
),
173170
(
174171
"cardinality.window".to_owned(),
175172
limit.window.window_seconds.to_string(),
176173
),
177174
]);
178175

176+
if let Some(ref name) = report.metric_name {
177+
tags.insert("mri".to_owned(), name.to_string());
178+
tags.insert("mri.namespace".to_owned(), name.namespace().to_string());
179+
if let Some(t) = name.try_type() {
180+
tags.insert("mri.type".to_owned(), t.to_string());
181+
}
182+
}
183+
184+
if let Some(t) = report.metric_type {
185+
tags.insert("mri.type".to_owned(), t.to_string());
186+
}
187+
179188
Some(Bucket {
180189
timestamp: UnixTimestamp::now(),
181190
width: 0,
@@ -190,7 +199,9 @@ impl MetricStats {
190199
#[cfg(test)]
191200
mod tests {
192201
use relay_base_schema::project::{ProjectId, ProjectKey};
202+
use relay_cardinality::{CardinalityScope, SlidingWindow};
193203
use relay_dynamic_config::GlobalConfig;
204+
use relay_metrics::MetricType;
194205
use relay_quotas::ReasonCode;
195206
use tokio::sync::mpsc::UnboundedReceiver;
196207

@@ -265,6 +276,7 @@ mod tests {
265276
bucket.tags,
266277
tags!(
267278
("mri", "d:custom/rt@millisecond"),
279+
("mri.type", "d"),
268280
("mri.namespace", "custom"),
269281
("outcome.id", "0"),
270282
)
@@ -285,6 +297,7 @@ mod tests {
285297
bucket.tags,
286298
tags!(
287299
("mri", "d:custom/rt@millisecond"),
300+
("mri.type", "d"),
288301
("mri.namespace", "custom"),
289302
("outcome.id", "2"),
290303
("outcome.reason", "foobar"),
@@ -294,6 +307,132 @@ mod tests {
294307
assert!(receiver.blocking_recv().is_none());
295308
}
296309

310+
#[test]
311+
fn test_metric_stats_cardinality_name() {
312+
let (ms, mut receiver) = create_metric_stats(1.0);
313+
314+
let scoping = scoping();
315+
let limit = CardinalityLimit {
316+
id: "test".to_owned(),
317+
passive: false,
318+
report: true,
319+
window: SlidingWindow {
320+
window_seconds: 246,
321+
granularity_seconds: 123,
322+
},
323+
limit: 99,
324+
scope: CardinalityScope::Name,
325+
namespace: None,
326+
};
327+
let report = CardinalityReport {
328+
organization_id: Some(scoping.organization_id),
329+
project_id: Some(scoping.project_id),
330+
metric_type: None,
331+
metric_name: Some(MetricName::from("d:custom/rt@millisecond")),
332+
cardinality: 12,
333+
};
334+
335+
ms.track_cardinality(scoping, &limit, &report);
336+
337+
drop(ms);
338+
339+
let Aggregator::MergeBuckets(mb) = receiver.blocking_recv().unwrap() else {
340+
panic!();
341+
};
342+
assert_eq!(mb.project_key(), scoping.project_key);
343+
344+
let mut buckets = mb.buckets();
345+
assert_eq!(buckets.len(), 1);
346+
let bucket = buckets.pop().unwrap();
347+
348+
assert_eq!(&*bucket.name, "g:metric_stats/cardinality@none");
349+
assert_eq!(
350+
bucket.value,
351+
BucketValue::Gauge(GaugeValue {
352+
last: 12.into(),
353+
min: 12.into(),
354+
max: 12.into(),
355+
sum: 12.into(),
356+
count: 1,
357+
})
358+
);
359+
assert_eq!(
360+
bucket.tags,
361+
tags!(
362+
("mri", "d:custom/rt@millisecond"),
363+
("mri.type", "d"),
364+
("mri.namespace", "custom"),
365+
("cardinality.limit", "test"),
366+
("cardinality.scope", "name"),
367+
("cardinality.window", "246"),
368+
)
369+
);
370+
371+
assert!(receiver.blocking_recv().is_none());
372+
}
373+
374+
#[test]
375+
fn test_metric_stats_cardinality_type() {
376+
let (ms, mut receiver) = create_metric_stats(1.0);
377+
378+
let scoping = scoping();
379+
let limit = CardinalityLimit {
380+
id: "test".to_owned(),
381+
passive: false,
382+
report: true,
383+
window: SlidingWindow {
384+
window_seconds: 246,
385+
granularity_seconds: 123,
386+
},
387+
limit: 99,
388+
scope: CardinalityScope::Type,
389+
namespace: None,
390+
};
391+
let report = CardinalityReport {
392+
organization_id: Some(scoping.organization_id),
393+
project_id: Some(scoping.project_id),
394+
metric_type: Some(MetricType::Distribution),
395+
metric_name: None,
396+
cardinality: 12,
397+
};
398+
399+
ms.track_cardinality(scoping, &limit, &report);
400+
401+
drop(ms);
402+
403+
let Aggregator::MergeBuckets(mb) = receiver.blocking_recv().unwrap() else {
404+
panic!();
405+
};
406+
assert_eq!(mb.project_key(), scoping.project_key);
407+
408+
let mut buckets = mb.buckets();
409+
assert_eq!(buckets.len(), 1);
410+
let bucket = buckets.pop().unwrap();
411+
412+
assert_eq!(&*bucket.name, "g:metric_stats/cardinality@none");
413+
assert_eq!(
414+
bucket.value,
415+
BucketValue::Gauge(GaugeValue {
416+
last: 12.into(),
417+
min: 12.into(),
418+
max: 12.into(),
419+
sum: 12.into(),
420+
count: 1,
421+
})
422+
);
423+
assert_eq!(
424+
bucket.tags,
425+
tags!(
426+
("mri.type", "d"),
427+
("cardinality.limit", "test"),
428+
("cardinality.scope", "type"),
429+
("cardinality.window", "246"),
430+
)
431+
);
432+
433+
assert!(receiver.blocking_recv().is_none());
434+
}
435+
297436
#[test]
298437
fn test_metric_stats_rollout_rate_disabled() {
299438
let (ms, mut receiver) = create_metric_stats(0.0);

0 commit comments

Comments
 (0)