Sha256: a2fac133739aebb183578358dbf27a4bce9be68898198dbddb1ce02585f8b7e3

Contents?: true

Size: 1.22 KB

Versions: 2

Compression:

Stored size: 1.22 KB

Contents

# typed: true

module Datadog
  module AppSec
    # Simple per-thread rate limiter
    # Since AppSec marks sampling to keep on a security event, this limits the flood of egress traces involving AppSec
    class RateLimiter
      def initialize(rate)
        @rate = rate
        @timestamps = []
      end

      def limit
        now = Time.now.to_f

        loop do
          oldest = @timestamps.first

          break if oldest.nil? || now - oldest < 1

          @timestamps.shift
        end

        @timestamps << now

        if (count = @timestamps.count) <= @rate
          yield
        else
          Datadog.logger.debug { "Rate limit hit: #{count}/#{@rate} AppSec traces/second" }
        end
      end

      class << self
        def limit(name, &block)
          rate_limiter(name).limit(&block)
        end

        protected

        def rate_limiter(name)
          case name
          when :traces
            Thread.current[:datadog_security_trace_rate_limiter] ||= RateLimiter.new(trace_rate_limit)
          else
            raise "unsupported rate limiter: #{name.inspect}"
          end
        end

        def trace_rate_limit
          Datadog::AppSec.settings.trace_rate_limit
        end
      end
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
ddtrace-1.0.0 lib/datadog/appsec/rate_limiter.rb
ddtrace-1.0.0.beta2 lib/datadog/appsec/rate_limiter.rb