Class: Datadog::Tracing::Sampling::TokenBucket

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

Overview

Implementation of the Token Bucket metering algorithm for rate limiting.

See Also:

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rate, max_tokens = rate) ⇒ TokenBucket

Returns a new instance of TokenBucket.

Parameters:

  • rate (Numeric)

    Allowance rate, in units per second if rate is negative, always allow if rate is zero, never allow

  • max_tokens (Numeric) (defaults to: rate)

    Limit of available tokens

Raises:

  • (ArgumentError)


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/datadog/tracing/sampling/rate_limiter.rb', line 39

def initialize(rate, max_tokens = rate)
  super()

  raise ArgumentError, "rate must be a number: #{rate}" unless rate.is_a?(Numeric)
  raise ArgumentError, "max_tokens must be a number: #{max_tokens}" unless max_tokens.is_a?(Numeric)

  @rate = rate
  @max_tokens = max_tokens

  @tokens = max_tokens
  @total_messages = 0
  @conforming_messages = 0
  @prev_conforming_messages = nil
  @prev_total_messages = nil
  @current_window = nil

  @last_refill = Core::Utils::Time.get_time
end

Instance Attribute Details

#max_tokensObject (readonly)

Returns the value of attribute max_tokens.



33
34
35
# File 'lib/datadog/tracing/sampling/rate_limiter.rb', line 33

def max_tokens
  @max_tokens
end

#rateObject (readonly)

Returns the value of attribute rate.



33
34
35
# File 'lib/datadog/tracing/sampling/rate_limiter.rb', line 33

def rate
  @rate
end

Instance Method Details

#allow?(size) ⇒ Boolean

Checks if a message of provided +size+ conforms with the current bucket limit.

If it does, return +true+ and remove +size+ tokens from the bucket. If it does not, return +false+ without affecting the tokens from the bucket.

Returns:

  • (Boolean)

    +true+ if message conforms with current bucket limit



67
68
69
70
71
# File 'lib/datadog/tracing/sampling/rate_limiter.rb', line 67

def allow?(size)
  allowed = should_allow?(size)
  update_rate_counts(allowed)
  allowed
end

#available_tokensNumeric

Returns number of tokens currently available.

Returns:

  • (Numeric)

    number of tokens currently available



101
102
103
# File 'lib/datadog/tracing/sampling/rate_limiter.rb', line 101

def available_tokens
  @tokens
end

#current_window_rateFloat

Ratio of 'conformance' per 'total messages' checked on this bucket

Returns +1.0+ when no messages have been checked yet.

Returns:

  • (Float)

    Conformance ratio, between +[0,1]+



94
95
96
97
98
# File 'lib/datadog/tracing/sampling/rate_limiter.rb', line 94

def current_window_rate
  return 1.0 if @total_messages.zero?

  @conforming_messages.to_f / @total_messages
end

#effective_rateFloat

Ratio of 'conformance' per 'total messages' checked averaged for the past 2 buckets

Returns +1.0+ when no messages have been checked yet.

Returns:

  • (Float)

    Conformance ratio, between +[0,1]+



79
80
81
82
83
84
85
86
# File 'lib/datadog/tracing/sampling/rate_limiter.rb', line 79

def effective_rate
  return 0.0 if @rate.zero?
  return 1.0 if @rate < 0 || @total_messages.zero?

  return current_window_rate if @prev_conforming_messages.nil? || @prev_total_messages.nil?

  (@conforming_messages.to_f + @prev_conforming_messages.to_f) / (@total_messages + @prev_total_messages)
end