Sha256: ff92dd2faf3cb183f73e1ba628b8f56ea68ea6953e87b7b66b1a7670270b0c66

Contents?: true

Size: 1.39 KB

Versions: 6

Compression:

Stored size: 1.39 KB

Contents

# frozen_string_literal: 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

        # reset a rate limiter: used for testing
        def reset!(name)
          Thread.current[:datadog_security_trace_rate_limiter] = nil
        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.configuration.appsec.trace_rate_limit
        end
      end
    end
  end
end

Version data entries

6 entries across 6 versions & 1 rubygems

Version Path
datadog-2.3.0 lib/datadog/appsec/rate_limiter.rb
datadog-2.2.0 lib/datadog/appsec/rate_limiter.rb
datadog-2.1.0 lib/datadog/appsec/rate_limiter.rb
datadog-2.0.0 lib/datadog/appsec/rate_limiter.rb
datadog-2.0.0.beta2 lib/datadog/appsec/rate_limiter.rb
datadog-2.0.0.beta1 lib/datadog/appsec/rate_limiter.rb