Skip to content

Commit ce8315c

Browse files
committed
chore(sampling): appease the linting and miri gods
1 parent e482c90 commit ce8315c

6 files changed

Lines changed: 65 additions & 26 deletions

File tree

.github/labeler.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,9 @@ crashtracker:
6262
'libdd-crashtracker/**/*',
6363
'libdd-crashtracker-ffi/**/*',
6464
]
65+
66+
sampling:
67+
- changed-files:
68+
- any-glob-to-any-file: [
69+
'libdd-sampling/**/*',
70+
]

libdd-sampling/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ version = "0.1.0"
77
edition.workspace = true
88
rust-version.workspace = true
99
license.workspace = true
10+
homepage = "https://github.com/DataDog/libdatadog/tree/main/libdd-sampling"
1011
repository = "https://github.com/DataDog/libdatadog/tree/main/libdd-sampling"
1112
description = "Core sampling logic for Datadog tracing"
1213
authors.workspace = true
@@ -25,12 +26,12 @@ required-features = ["v04_span"]
2526
serde = { version = "1.0", features = ["derive"] }
2627
serde_json = "1.0"
2728
lru = "0.16.3"
28-
libdd-trace-utils = { path = "../libdd-trace-utils", optional = true }
29+
libdd-trace-utils = { path = "../libdd-trace-utils", version = "3.0.1", optional = true }
2930

3031
[features]
3132
v04_span = ["dep:libdd-trace-utils"]
3233

3334
[dev-dependencies]
3435
criterion = "0.5"
35-
libdd-common = { path = "../libdd-common", features = ["bench-utils"] }
36-
libdd-trace-utils = { path = "../libdd-trace-utils" }
36+
libdd-common = { path = "../libdd-common", version = "4.0.0", features = ["bench-utils"] }
37+
libdd-trace-utils = { path = "../libdd-trace-utils", version = "3.0.1" }

libdd-sampling/src/datadog_sampler.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ mod tests {
462462
}
463463
}
464464

465-
impl<'a> SpanProperties for TestSpan<'a> {
465+
impl SpanProperties for TestSpan<'_> {
466466
type Attribute<'b>
467467
= &'b TestAttribute
468468
where
@@ -544,7 +544,7 @@ mod tests {
544544
}
545545
}
546546

547-
impl<'a> SamplingData for TestSamplingData<'a> {
547+
impl SamplingData for TestSamplingData<'_> {
548548
type TraceId = TestTraceId;
549549
type Properties<'b>
550550
= TestSpan<'b>

libdd-sampling/src/rate_limiter.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,34 @@ mod tests {
247247
}
248248

249249
#[test]
250+
#[cfg_attr(miri, ignore)]
251+
fn test_rate_limiter_accumulates_fractional_tokens() {
252+
// With rate=2/s each token takes 500ms. Sleeping 300ms twice (600ms total) must
253+
// yield at least one token. Before the fix, each sub-token call reset last_update
254+
// to the call time, so the second 300ms window also computed only 0.6 tokens and
255+
// the limiter starved indefinitely. Margins: the first assert!(!..) has 200ms of
256+
// headroom below 500ms; the final assert!(..) has 100ms of headroom above 500ms.
257+
let limiter = RateLimiter::new(2, None);
258+
259+
// Drain all initial tokens.
260+
for _ in 0..2 {
261+
assert!(limiter.is_allowed());
262+
}
263+
assert!(!limiter.is_allowed());
264+
265+
// First sleep: 300ms → 0.6 tokens, not enough to allow.
266+
thread::sleep(Duration::from_millis(300));
267+
assert!(!limiter.is_allowed());
268+
269+
// Second sleep: another 300ms. Total elapsed since drain ≈ 600ms → 1.2 tokens.
270+
// The fix preserves fractional progress so this succeeds; the old code reset
271+
// last_update on the first call and only saw another 0.6 tokens here.
272+
thread::sleep(Duration::from_millis(300));
273+
assert!(limiter.is_allowed());
274+
}
275+
276+
#[test]
277+
#[cfg_attr(miri, ignore)]
250278
fn test_rate_limiter_limit_rate() {
251279
let limiter = RateLimiter::new(5, None); // 5 per second
252280

@@ -269,6 +297,7 @@ mod tests {
269297
}
270298

271299
#[test]
300+
#[cfg_attr(miri, ignore)]
272301
fn test_rate_limiter_effective_rate() {
273302
let limiter = RateLimiter::new(50, None); // 50 per second
274303

@@ -292,6 +321,7 @@ mod tests {
292321
}
293322

294323
#[test]
324+
#[cfg_attr(miri, ignore)]
295325
fn test_rate_limiter_thread_safety() {
296326
let limiter = RateLimiter::new(100, None);
297327
let limiter_clone = limiter.clone();

libdd-sampling/src/sampling_rule.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,19 @@ impl From<&str> for RuleProvenance {
241241
}
242242
}
243243

244+
/// Helper struct for representing i64 values as ValueLike
245+
struct ValueI64(i64);
246+
247+
impl ValueLike for ValueI64 {
248+
fn extract_float(&self) -> Option<f64> {
249+
Some(self.0 as f64)
250+
}
251+
252+
fn extract_string(&self) -> Option<std::borrow::Cow<'_, str>> {
253+
Some(std::borrow::Cow::Owned(self.0.to_string()))
254+
}
255+
}
256+
244257
#[cfg(test)]
245258
mod tests {
246259
use super::*;
@@ -595,16 +608,3 @@ mod tests {
595608
assert!(RuleProvenance::Dynamic < RuleProvenance::Default);
596609
}
597610
}
598-
599-
/// Helper struct for representing i64 values as ValueLike
600-
struct ValueI64(i64);
601-
602-
impl ValueLike for ValueI64 {
603-
fn extract_float(&self) -> Option<f64> {
604-
Some(self.0 as f64)
605-
}
606-
607-
fn extract_string(&self) -> Option<std::borrow::Cow<'_, str>> {
608-
Some(std::borrow::Cow::Owned(self.0.to_string()))
609-
}
610-
}

libdd-sampling/src/v04_span.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl<'a, T: TraceData> V04SpanProperties<'a, T> {
134134
}
135135
}
136136

137-
impl<'a, T: TraceData> SpanProperties for V04SpanProperties<'a, T> {
137+
impl<T: TraceData> SpanProperties for V04SpanProperties<'_, T> {
138138
type Attribute<'b>
139139
= SpanAttribute<'b>
140140
where
@@ -189,7 +189,7 @@ pub struct V04SamplingData<'a, T: TraceData> {
189189
pub span: &'a Span<T>,
190190
}
191191

192-
impl<'a, T: TraceData> SamplingData for V04SamplingData<'a, T> {
192+
impl<T: TraceData> SamplingData for V04SamplingData<'_, T> {
193193
type TraceId = u128;
194194
type Properties<'b>
195195
= V04SpanProperties<'b, T>
@@ -286,9 +286,9 @@ mod tests {
286286

287287
#[test]
288288
fn test_span_attribute_value_metric() {
289-
let val = SpanAttributeValue::Metric(3.14);
290-
assert_eq!(val.extract_float(), Some(3.14));
291-
assert_eq!(val.extract_string(), Some(Cow::Owned("3.14".to_string())));
289+
let val = SpanAttributeValue::Metric(1.5);
290+
assert_eq!(val.extract_float(), Some(1.5));
291+
assert_eq!(val.extract_string(), Some(Cow::Owned("1.5".to_string())));
292292
}
293293

294294
#[test]
@@ -521,9 +521,11 @@ mod tests {
521521
#[test]
522522
fn test_integration_tags_apply_to_span() {
523523
let sampler = DatadogSampler::new(vec![], 100);
524-
let mut span = Span::<SliceData<'static>>::default();
525-
span.name = "op";
526-
span.service = "svc";
524+
let span = Span::<SliceData<'static>> {
525+
name: "op",
526+
service: "svc",
527+
..Default::default()
528+
};
527529

528530
let data = V04SamplingData {
529531
is_parent_sampled: None,

0 commit comments

Comments
 (0)