Class: Datadog::Tracing::Sampling::RuleSampler

Inherits:
Object
  • Object
show all
Defined in:
lib/datadog/tracing/sampling/rule_sampler.rb

Overview

Span Sampler that applies a set of Rules to decide on sampling outcome. Then, a rate limiter is applied.

If a trace does not conform to any rules, a default sampling strategy is applied.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rules = [], rate_limit: Datadog.configuration.tracing.sampling.rate_limit, rate_limiter: nil, default_sample_rate: Datadog.configuration.tracing.sampling.default_rate, default_sampler: nil) ⇒ RuleSampler

Returns a new instance of RuleSampler.

Parameters:

  • rules (Array<Rule>) (defaults to: [])

    ordered list of rules to be applied to a trace

  • rate_limit (Float) (defaults to: Datadog.configuration.tracing.sampling.rate_limit)

    number of traces per second, defaults to 100

  • rate_limiter (RateLimiter) (defaults to: nil)

    limiter applied after rule matching

  • default_sample_rate (Float) (defaults to: Datadog.configuration.tracing.sampling.default_rate)

    fallback sample rate when no rules apply to a trace, between [0,1], defaults to 1

  • default_sampler (Sample) (defaults to: nil)

    fallback strategy when no rules apply to a trace

[View source]

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/datadog/tracing/sampling/rule_sampler.rb', line 25

def initialize(
  rules = [],
  rate_limit: Datadog.configuration.tracing.sampling.rate_limit,
  rate_limiter: nil,
  default_sample_rate: Datadog.configuration.tracing.sampling.default_rate,
  default_sampler: nil
)
  @rules = if default_sample_rate && !default_sampler
             # Add to the end of the rule list a rule always matches any trace
             rules << SimpleRule.new(sample_rate: default_sample_rate)
           else
             rules
           end
  @rate_limiter = if rate_limiter
                    rate_limiter
                  elsif rate_limit
                    Core::TokenBucket.new(rate_limit)
                  else
                    Core::UnlimitedLimiter.new
                  end
  @default_sampler = if default_sampler
                       default_sampler
                     elsif default_sample_rate
                       nil
                     else
                       # TODO: Simplify .tags access, as `Tracer#tags` can't be arbitrarily changed anymore
                       RateByServiceSampler.new(1.0, env: -> { Tracing.send(:tracer).tags['env'] })
                     end
end

Instance Attribute Details

#default_samplerObject (readonly)

Returns the value of attribute default_sampler.


17
18
19
# File 'lib/datadog/tracing/sampling/rule_sampler.rb', line 17

def default_sampler
  @default_sampler
end

#rate_limiterObject (readonly)

Returns the value of attribute rate_limiter.


17
18
19
# File 'lib/datadog/tracing/sampling/rule_sampler.rb', line 17

def rate_limiter
  @rate_limiter
end

#rulesObject (readonly)

Returns the value of attribute rules.


17
18
19
# File 'lib/datadog/tracing/sampling/rule_sampler.rb', line 17

def rules
  @rules
end

Class Method Details

.parse(rules, rate_limit, default_sample_rate) ⇒ Object

[View source]

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/datadog/tracing/sampling/rule_sampler.rb', line 55

def self.parse(rules, rate_limit, default_sample_rate)
  parsed_rules = JSON.parse(rules).map do |rule|
    sample_rate = rule['sample_rate']

    begin
      sample_rate = Float(sample_rate)
    rescue
      raise "Rule '#{rule.inspect}' does not contain a float property `sample_rate`"
    end

    kwargs = {
      name: rule['name'],
      service: rule['service'],
      resource: rule['resource'],
      tags: rule['tags'],
      sample_rate: sample_rate,
      provenance: if (provenance = rule['provenance'])
                    # `Rule::PROVENANCE_*` values are symbols, so convert strings to match
                    provenance.to_sym
                  else
                    Rule::PROVENANCE_LOCAL
                  end,
    }

    kwargs.compact!

    SimpleRule.new(**kwargs)
  end

  new(parsed_rules, rate_limit: rate_limit, default_sample_rate: default_sample_rate)
rescue => e
  Datadog.logger.warn do
    "Could not parse trace sampling rules '#{rules}': #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
  end

  nil
end

Instance Method Details

#sample!(trace) ⇒ Object

[View source]

93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/datadog/tracing/sampling/rule_sampler.rb', line 93

def sample!(trace)
  sampled = sample_trace(trace) do |t|
    @default_sampler.sample!(t).tap do
      # We want to make sure the trace is tagged with the agent-derived
      # service rate. Retrieve this from the rate by service sampler.
      # Only do this if it was set by a RateByServiceSampler.
      trace.agent_sample_rate = @default_sampler.sample_rate(trace) if @default_sampler.is_a?(RateByServiceSampler)
    end
  end

  trace.sampled = sampled
end