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)


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

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.



31
32
33
# File 'lib/datadog/tracing/sampling/rate_limiter.rb', line 31

def max_tokens
  @max_tokens
end

#rateObject (readonly)

Returns the value of attribute rate.



31
32
33
# File 'lib/datadog/tracing/sampling/rate_limiter.rb', line 31

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



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

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



99
100
101
# File 'lib/datadog/tracing/sampling/rate_limiter.rb', line 99

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]+



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

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]+



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

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