Skip to content

Commit 717a98f

Browse files
committed
perf(sampling): change api to avoid collecting meta and metrics
1 parent 860abbc commit 717a98f

5 files changed

Lines changed: 220 additions & 91 deletions

File tree

libdd-sampling/src/datadog_sampler.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,10 @@ mod tests {
463463
}
464464

465465
impl<'a> SpanProperties for TestSpan<'a> {
466-
type Attribute = TestAttribute;
466+
type Attribute<'b>
467+
= &'b TestAttribute
468+
where
469+
Self: 'b;
467470

468471
fn operation_name(&self) -> Cow<'_, str> {
469472
self.get_operation_name()
@@ -505,10 +508,7 @@ mod tests {
505508
})
506509
}
507510

508-
fn attributes<'b>(&'b self) -> impl Iterator<Item = &'b Self::Attribute>
509-
where
510-
Self: 'b,
511-
{
511+
fn attributes(&self) -> impl Iterator<Item = &TestAttribute> + '_ {
512512
self.attributes.iter()
513513
}
514514

libdd-sampling/src/dd_sampling.rs

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,22 @@ mod tests {
257257

258258
#[test]
259259
fn test_priority_from_str() {
260-
assert_eq!("1".parse::<SamplingPriority>().unwrap(), priority::AUTO_KEEP);
261-
assert_eq!("0".parse::<SamplingPriority>().unwrap(), priority::AUTO_REJECT);
262-
assert_eq!("2".parse::<SamplingPriority>().unwrap(), priority::USER_KEEP);
263-
assert_eq!("-1".parse::<SamplingPriority>().unwrap(), priority::USER_REJECT);
260+
assert_eq!(
261+
"1".parse::<SamplingPriority>().unwrap(),
262+
priority::AUTO_KEEP
263+
);
264+
assert_eq!(
265+
"0".parse::<SamplingPriority>().unwrap(),
266+
priority::AUTO_REJECT
267+
);
268+
assert_eq!(
269+
"2".parse::<SamplingPriority>().unwrap(),
270+
priority::USER_KEEP
271+
);
272+
assert_eq!(
273+
"-1".parse::<SamplingPriority>().unwrap(),
274+
priority::USER_REJECT
275+
);
264276
assert!("not_a_number".parse::<SamplingPriority>().is_err());
265277
assert!("999".parse::<SamplingPriority>().is_err()); // overflows i8
266278
}
@@ -281,22 +293,46 @@ mod tests {
281293
// DEFAULT and AGENT_RATE_BY_SERVICE use AUTO priority
282294
assert_eq!(mechanism::DEFAULT.to_priority(true), priority::AUTO_KEEP);
283295
assert_eq!(mechanism::DEFAULT.to_priority(false), priority::AUTO_REJECT);
284-
assert_eq!(mechanism::AGENT_RATE_BY_SERVICE.to_priority(true), priority::AUTO_KEEP);
285-
assert_eq!(mechanism::AGENT_RATE_BY_SERVICE.to_priority(false), priority::AUTO_REJECT);
296+
assert_eq!(
297+
mechanism::AGENT_RATE_BY_SERVICE.to_priority(true),
298+
priority::AUTO_KEEP
299+
);
300+
assert_eq!(
301+
mechanism::AGENT_RATE_BY_SERVICE.to_priority(false),
302+
priority::AUTO_REJECT
303+
);
286304
assert_eq!(mechanism::APPSEC.to_priority(true), priority::AUTO_KEEP);
287305
assert_eq!(mechanism::APPSEC.to_priority(false), priority::AUTO_REJECT);
288306
}
289307

290308
#[test]
291309
fn test_mechanism_to_priority_user_pair() {
292310
// Rule-based mechanisms use USER priority
293-
assert_eq!(mechanism::LOCAL_USER_TRACE_SAMPLING_RULE.to_priority(true), priority::USER_KEEP);
294-
assert_eq!(mechanism::LOCAL_USER_TRACE_SAMPLING_RULE.to_priority(false), priority::USER_REJECT);
295-
assert_eq!(mechanism::REMOTE_USER_TRACE_SAMPLING_RULE.to_priority(true), priority::USER_KEEP);
296-
assert_eq!(mechanism::REMOTE_DYNAMIC_TRACE_SAMPLING_RULE.to_priority(true), priority::USER_KEEP);
311+
assert_eq!(
312+
mechanism::LOCAL_USER_TRACE_SAMPLING_RULE.to_priority(true),
313+
priority::USER_KEEP
314+
);
315+
assert_eq!(
316+
mechanism::LOCAL_USER_TRACE_SAMPLING_RULE.to_priority(false),
317+
priority::USER_REJECT
318+
);
319+
assert_eq!(
320+
mechanism::REMOTE_USER_TRACE_SAMPLING_RULE.to_priority(true),
321+
priority::USER_KEEP
322+
);
323+
assert_eq!(
324+
mechanism::REMOTE_DYNAMIC_TRACE_SAMPLING_RULE.to_priority(true),
325+
priority::USER_KEEP
326+
);
297327
assert_eq!(mechanism::MANUAL.to_priority(true), priority::USER_KEEP);
298-
assert_eq!(mechanism::SPAN_SAMPLING_RULE.to_priority(false), priority::USER_REJECT);
299-
assert_eq!(mechanism::DATA_JOBS_MONITORING.to_priority(true), priority::USER_KEEP);
328+
assert_eq!(
329+
mechanism::SPAN_SAMPLING_RULE.to_priority(false),
330+
priority::USER_REJECT
331+
);
332+
assert_eq!(
333+
mechanism::DATA_JOBS_MONITORING.to_priority(true),
334+
priority::USER_KEEP
335+
);
300336
}
301337

302338
#[test]
@@ -320,7 +356,10 @@ mod tests {
320356
assert_eq!(mechanism::OTLP_INGEST_PROBABILISTIC_SAMPLING.to_cow(), "-9");
321357
assert_eq!(mechanism::DATA_JOBS_MONITORING.to_cow(), "-10");
322358
assert_eq!(mechanism::REMOTE_USER_TRACE_SAMPLING_RULE.to_cow(), "-11");
323-
assert_eq!(mechanism::REMOTE_DYNAMIC_TRACE_SAMPLING_RULE.to_cow(), "-12");
359+
assert_eq!(
360+
mechanism::REMOTE_DYNAMIC_TRACE_SAMPLING_RULE.to_cow(),
361+
"-12"
362+
);
324363
// Unknown mechanism falls back to Display
325364
assert_eq!(SamplingMechanism::from_u8(99).to_cow(), "-99");
326365
}
@@ -329,15 +368,30 @@ mod tests {
329368
fn test_mechanism_display() {
330369
assert_eq!(mechanism::DEFAULT.to_string(), "-0");
331370
assert_eq!(mechanism::LOCAL_USER_TRACE_SAMPLING_RULE.to_string(), "-3");
332-
assert_eq!(mechanism::REMOTE_DYNAMIC_TRACE_SAMPLING_RULE.to_string(), "-12");
371+
assert_eq!(
372+
mechanism::REMOTE_DYNAMIC_TRACE_SAMPLING_RULE.to_string(),
373+
"-12"
374+
);
333375
}
334376

335377
#[test]
336378
fn test_mechanism_from_str() {
337-
assert_eq!("-0".parse::<SamplingMechanism>().unwrap(), mechanism::DEFAULT);
338-
assert_eq!("-1".parse::<SamplingMechanism>().unwrap(), mechanism::AGENT_RATE_BY_SERVICE);
339-
assert_eq!("-3".parse::<SamplingMechanism>().unwrap(), mechanism::LOCAL_USER_TRACE_SAMPLING_RULE);
340-
assert_eq!("-12".parse::<SamplingMechanism>().unwrap(), mechanism::REMOTE_DYNAMIC_TRACE_SAMPLING_RULE);
379+
assert_eq!(
380+
"-0".parse::<SamplingMechanism>().unwrap(),
381+
mechanism::DEFAULT
382+
);
383+
assert_eq!(
384+
"-1".parse::<SamplingMechanism>().unwrap(),
385+
mechanism::AGENT_RATE_BY_SERVICE
386+
);
387+
assert_eq!(
388+
"-3".parse::<SamplingMechanism>().unwrap(),
389+
mechanism::LOCAL_USER_TRACE_SAMPLING_RULE
390+
);
391+
assert_eq!(
392+
"-12".parse::<SamplingMechanism>().unwrap(),
393+
mechanism::REMOTE_DYNAMIC_TRACE_SAMPLING_RULE
394+
);
341395
}
342396

343397
#[test]

libdd-sampling/src/sampling_rule.rs

Lines changed: 99 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,10 @@ mod tests {
293293
}
294294

295295
impl crate::types::SpanProperties for TestSpan {
296-
type Attribute = TestAttr;
296+
type Attribute<'a>
297+
= &'a TestAttr
298+
where
299+
Self: 'a;
297300

298301
fn operation_name(&self) -> Cow<'_, str> {
299302
Cow::Borrowed(self.name)
@@ -310,10 +313,7 @@ mod tests {
310313
fn status_code(&self) -> Option<u32> {
311314
self.status_code
312315
}
313-
fn attributes<'a>(&'a self) -> impl Iterator<Item = &'a TestAttr>
314-
where
315-
Self: 'a,
316-
{
316+
fn attributes(&self) -> impl Iterator<Item = &TestAttr> + '_ {
317317
self.attrs.iter()
318318
}
319319
fn get_alternate_key<'b>(&self, key: &'b str) -> Option<Cow<'b, str>> {
@@ -362,9 +362,21 @@ mod tests {
362362
#[test]
363363
fn test_from_configs_preserves_provenance() {
364364
let configs = vec![
365-
SamplingRuleConfig { sample_rate: 1.0, provenance: "customer".into(), ..Default::default() },
366-
SamplingRuleConfig { sample_rate: 0.5, provenance: "dynamic".into(), ..Default::default() },
367-
SamplingRuleConfig { sample_rate: 0.1, provenance: "default".into(), ..Default::default() },
365+
SamplingRuleConfig {
366+
sample_rate: 1.0,
367+
provenance: "customer".into(),
368+
..Default::default()
369+
},
370+
SamplingRuleConfig {
371+
sample_rate: 0.5,
372+
provenance: "dynamic".into(),
373+
..Default::default()
374+
},
375+
SamplingRuleConfig {
376+
sample_rate: 0.1,
377+
provenance: "default".into(),
378+
..Default::default()
379+
},
368380
];
369381
let rules = SamplingRule::from_configs(configs);
370382
assert_eq!(rules[0].provenance, "customer");
@@ -377,7 +389,10 @@ mod tests {
377389
#[test]
378390
fn test_matches_http_status_code_rule_matching() {
379391
let rule = SamplingRule::new(
380-
1.0, None, None, None,
392+
1.0,
393+
None,
394+
None,
395+
None,
381396
Some(HashMap::from([("http.status_code".into(), "200".into())])),
382397
None,
383398
);
@@ -389,7 +404,10 @@ mod tests {
389404
#[test]
390405
fn test_matches_http_status_code_rule_not_matching() {
391406
let rule = SamplingRule::new(
392-
1.0, None, None, None,
407+
1.0,
408+
None,
409+
None,
410+
None,
393411
Some(HashMap::from([("http.status_code".into(), "200".into())])),
394412
None,
395413
);
@@ -401,7 +419,10 @@ mod tests {
401419
#[test]
402420
fn test_matches_http_status_code_absent_returns_false() {
403421
let rule = SamplingRule::new(
404-
1.0, None, None, None,
422+
1.0,
423+
None,
424+
None,
425+
None,
405426
Some(HashMap::from([("http.status_code".into(), "200".into())])),
406427
None,
407428
);
@@ -412,8 +433,14 @@ mod tests {
412433
#[test]
413434
fn test_matches_http_response_status_code_key() {
414435
let rule = SamplingRule::new(
415-
1.0, None, None, None,
416-
Some(HashMap::from([("http.response.status_code".into(), "404".into())])),
436+
1.0,
437+
None,
438+
None,
439+
None,
440+
Some(HashMap::from([(
441+
"http.response.status_code".into(),
442+
"404".into(),
443+
)])),
417444
None,
418445
);
419446
let mut span = make_span("op", "svc", "res");
@@ -424,7 +451,10 @@ mod tests {
424451
#[test]
425452
fn test_matches_http_status_code_wildcard() {
426453
let rule = SamplingRule::new(
427-
1.0, None, None, None,
454+
1.0,
455+
None,
456+
None,
457+
None,
428458
Some(HashMap::from([("http.status_code".into(), "2*".into())])),
429459
None,
430460
);
@@ -440,25 +470,43 @@ mod tests {
440470
// Rule uses DD key "http.method"; span stores OTel key "http.request.method"
441471
// with alternate mapping back to "http.method"
442472
let rule = SamplingRule::new(
443-
1.0, None, None, None,
473+
1.0,
474+
None,
475+
None,
476+
None,
444477
Some(HashMap::from([("http.method".into(), "POST".into())])),
445478
None,
446479
);
447480
let mut span = make_span("op", "svc", "res");
448-
span.attrs = vec![TestAttr { key: "http.request.method", value: TestValue { value: "POST", is_metric: false } }];
481+
span.attrs = vec![TestAttr {
482+
key: "http.request.method",
483+
value: TestValue {
484+
value: "POST",
485+
is_metric: false,
486+
},
487+
}];
449488
span.alternates = vec![("http.request.method", "http.method")];
450489
assert!(rule.matches(&span));
451490
}
452491

453492
#[test]
454493
fn test_matches_alternate_key_value_mismatch() {
455494
let rule = SamplingRule::new(
456-
1.0, None, None, None,
495+
1.0,
496+
None,
497+
None,
498+
None,
457499
Some(HashMap::from([("http.method".into(), "POST".into())])),
458500
None,
459501
);
460502
let mut span = make_span("op", "svc", "res");
461-
span.attrs = vec![TestAttr { key: "http.request.method", value: TestValue { value: "GET", is_metric: false } }];
503+
span.attrs = vec![TestAttr {
504+
key: "http.request.method",
505+
value: TestValue {
506+
value: "GET",
507+
is_metric: false,
508+
},
509+
}];
462510
span.alternates = vec![("http.request.method", "http.method")];
463511
assert!(!rule.matches(&span));
464512
}
@@ -467,12 +515,21 @@ mod tests {
467515
fn test_matches_non_http_tag_no_alternate_fallback() {
468516
// Non-http. keys do NOT fall through to alternate-key scan
469517
let rule = SamplingRule::new(
470-
1.0, None, None, None,
518+
1.0,
519+
None,
520+
None,
521+
None,
471522
Some(HashMap::from([("custom.tag".into(), "value".into())])),
472523
None,
473524
);
474525
let mut span = make_span("op", "svc", "res");
475-
span.attrs = vec![TestAttr { key: "some.other.key", value: TestValue { value: "value", is_metric: false } }];
526+
span.attrs = vec![TestAttr {
527+
key: "some.other.key",
528+
value: TestValue {
529+
value: "value",
530+
is_metric: false,
531+
},
532+
}];
476533
span.alternates = vec![("some.other.key", "custom.tag")];
477534
assert!(!rule.matches(&span));
478535
}
@@ -482,24 +539,42 @@ mod tests {
482539
#[test]
483540
fn test_match_attribute_value_non_integer_float_wildcard_matches() {
484541
let rule = SamplingRule::new(
485-
1.0, None, None, None,
542+
1.0,
543+
None,
544+
None,
545+
None,
486546
Some(HashMap::from([("score".into(), "*".into())])),
487547
None,
488548
);
489549
let mut span = make_span("op", "svc", "res");
490-
span.attrs = vec![TestAttr { key: "score", value: TestValue { value: "3.14", is_metric: true } }];
550+
span.attrs = vec![TestAttr {
551+
key: "score",
552+
value: TestValue {
553+
value: "3.14",
554+
is_metric: true,
555+
},
556+
}];
491557
assert!(rule.matches(&span));
492558
}
493559

494560
#[test]
495561
fn test_match_attribute_value_non_integer_float_non_wildcard_no_match() {
496562
let rule = SamplingRule::new(
497-
1.0, None, None, None,
563+
1.0,
564+
None,
565+
None,
566+
None,
498567
Some(HashMap::from([("score".into(), "3.14".into())])),
499568
None,
500569
);
501570
let mut span = make_span("op", "svc", "res");
502-
span.attrs = vec![TestAttr { key: "score", value: TestValue { value: "3.14", is_metric: true } }];
571+
span.attrs = vec![TestAttr {
572+
key: "score",
573+
value: TestValue {
574+
value: "3.14",
575+
is_metric: true,
576+
},
577+
}];
503578
assert!(!rule.matches(&span));
504579
}
505580

0 commit comments

Comments
 (0)