Files
lighthouse/common/tracing_samplers/src/lib.rs
2026-01-22 05:11:26 +00:00

79 lines
2.4 KiB
Rust

//! OpenTelemetry samplers for filtering traces.
use opentelemetry::Context;
use opentelemetry::trace::{Link, SamplingDecision, SamplingResult, SpanKind, TraceState};
use opentelemetry_sdk::trace::ShouldSample;
/// A sampler that only samples spans whose names start with a given prefix.
///
/// This sampler is designed to be used with `Sampler::ParentBased`, which will:
/// - Use this sampler's decision for root spans (no parent)
/// - Automatically inherit the parent's sampling decision for child spans
///
/// This ensures that only traces starting from known instrumented code paths are exported,
/// reducing noise from partially instrumented code paths.
#[derive(Debug, Clone)]
pub struct PrefixBasedSampler {
prefix: &'static str,
}
impl PrefixBasedSampler {
pub fn new(prefix: &'static str) -> Self {
Self { prefix }
}
}
impl ShouldSample for PrefixBasedSampler {
fn should_sample(
&self,
_parent_context: Option<&Context>,
_trace_id: opentelemetry::trace::TraceId,
name: &str,
_span_kind: &SpanKind,
_attributes: &[opentelemetry::KeyValue],
_links: &[Link],
) -> SamplingResult {
if name.starts_with(self.prefix) {
SamplingResult {
decision: SamplingDecision::RecordAndSample,
attributes: Vec::new(),
trace_state: TraceState::default(),
}
} else {
SamplingResult {
decision: SamplingDecision::Drop,
attributes: Vec::new(),
trace_state: TraceState::default(),
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use opentelemetry::trace::TraceId;
#[test]
fn prefix_based_sampler_filters_by_prefix() {
let sampler = PrefixBasedSampler::new("test_");
let trace_id = TraceId::from_hex("0123456789abcdef0123456789abcdef").unwrap();
// Spans with prefix should be sampled
let result = sampler.should_sample(
None,
trace_id,
"test_my_span",
&SpanKind::Internal,
&[],
&[],
);
assert!(matches!(result.decision, SamplingDecision::RecordAndSample));
// Spans without prefix should be dropped
let result =
sampler.should_sample(None, trace_id, "other_span", &SpanKind::Internal, &[], &[]);
assert!(matches!(result.decision, SamplingDecision::Drop));
}
}