Line data Source code
1 : #include "span_sampler.h" 2 : 3 : #include "json.hpp" 4 : #include "sampling_mechanism.h" 5 : #include "sampling_priority.h" 6 : #include "sampling_util.h" 7 : #include "span_data.h" 8 : 9 : namespace datadog { 10 : namespace tracing { 11 : 12 1 : SpanSampler::SynchronizedLimiter::SynchronizedLimiter(const Clock& clock, 13 1 : double max_per_second) 14 1 : : limiter(clock, max_per_second) {} 15 : 16 11 : SpanSampler::Rule::Rule(const FinalizedSpanSamplerConfig::Rule& rule, 17 11 : const Clock& clock) 18 : : FinalizedSpanSamplerConfig::Rule(rule), 19 11 : limiter_(max_per_second ? std::make_unique<SynchronizedLimiter>( 20 : clock, *max_per_second) 21 22 : : nullptr) {} 22 : 23 2012 : SamplingDecision SpanSampler::Rule::decide(const SpanData& span) { 24 2012 : SamplingDecision decision; 25 2012 : decision.mechanism = int(SamplingMechanism::SPAN_RULE); 26 2012 : decision.origin = SamplingDecision::Origin::LOCAL; 27 2012 : decision.configured_rate = sample_rate; 28 2012 : decision.limiter_max_per_second = max_per_second; 29 : 30 2012 : const std::uint64_t threshold = max_id_from_rate(sample_rate); 31 2012 : if (knuth_hash(span.span_id) >= threshold) { 32 1 : decision.priority = int(SamplingPriority::USER_DROP); 33 1 : return decision; 34 : } 35 : 36 2011 : if (!limiter_) { 37 1011 : decision.priority = int(SamplingPriority::USER_KEEP); 38 1011 : return decision; 39 : } 40 : 41 1000 : std::lock_guard<std::mutex> lock(limiter_->mutex); 42 1000 : const auto result = limiter_->limiter.allow(); 43 1000 : if (result.allowed) { 44 100 : decision.priority = int(SamplingPriority::USER_KEEP); 45 : } else { 46 900 : decision.priority = int(SamplingPriority::USER_DROP); 47 : } 48 1000 : decision.limiter_effective_rate = result.effective_rate; 49 : 50 1000 : return decision; 51 1000 : } 52 : 53 603 : SpanSampler::SpanSampler(const FinalizedSpanSamplerConfig& config, 54 603 : const Clock& clock) { 55 614 : for (const auto& rule : config.rules) { 56 11 : rules_.push_back(Rule{rule, clock}); 57 : } 58 603 : } 59 : 60 37238 : SpanSampler::Rule* SpanSampler::match(const SpanData& span) { 61 37238 : const auto found = std::find_if(rules_.begin(), rules_.end(), 62 2023 : [&](Rule& rule) { return rule.match(span); }); 63 37238 : if (found != rules_.end()) { 64 2012 : return &*found; 65 : } 66 35226 : return nullptr; 67 : } 68 : 69 503 : nlohmann::json SpanSampler::config_json() const { 70 503 : std::vector<nlohmann::json> rules; 71 503 : for (const auto& rule : rules_) { 72 0 : rules.push_back(to_json(rule)); 73 : } 74 : 75 2012 : return nlohmann::json::object({ 76 : {"rules", rules}, 77 3018 : }); 78 503 : } 79 : 80 : } // namespace tracing 81 : } // namespace datadog