Class: Fluent::Plugin::JsonSizeLimit::RateLimitedLogger

Inherits:
Object
  • Object
show all
Defined in:
lib/fluent/plugin/json_size_limit/rate_limited_logger.rb

Overview

Serializes rate-limit state across Fluentd threads without putting a lock on the normal record-processing path.

Constant Summary collapse

MONOTONIC_TIME =
-> { Process.clock_gettime(Process::CLOCK_MONOTONIC) }

Instance Method Summary collapse

Constructor Details

#initialize(logger, interval, clock: MONOTONIC_TIME) ⇒ RateLimitedLogger

Returns a new instance of RateLimitedLogger.

Raises:

  • (ArgumentError)


11
12
13
14
15
16
17
18
19
20
# File 'lib/fluent/plugin/json_size_limit/rate_limited_logger.rb', line 11

def initialize(logger, interval, clock: MONOTONIC_TIME)
  raise ArgumentError, "interval must not be negative" unless interval.is_a?(Numeric) && !interval.negative?
  raise ArgumentError, "clock must respond to call" unless clock.respond_to?(:call)

  @logger = logger
  @interval = interval
  @clock = clock
  @mutex = Mutex.new
  @states = {}
end

Instance Method Details

#emit(level, category, message, fields = {}) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/fluent/plugin/json_size_limit/rate_limited_logger.rb', line 22

def emit(level, category, message, fields = {})
  return write(level, message, fields) if @interval.zero?

  now = @clock.call
  suppressed = @mutex.synchronize do
    state = (@states[category] ||= {last_at: nil, suppressed: 0})

    if state[:last_at].nil? || now - state[:last_at] >= @interval
      suppressed_count = state[:suppressed]
      state[:last_at] = now
      state[:suppressed] = 0
      suppressed_count
    else
      state[:suppressed] += 1
      nil
    end
  end
  return unless suppressed

  fields = fields.merge(suppressed_events: suppressed) if suppressed.positive?
  write(level, message, fields)
end

#flushObject



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/fluent/plugin/json_size_limit/rate_limited_logger.rb', line 45

def flush
  summaries = @mutex.synchronize do
    @states.filter_map do |category, state|
      next unless state[:suppressed].positive?

      summary = [category, state[:suppressed]]
      state[:suppressed] = 0
      summary
    end
  end

  summaries.each do |category, suppressed|
    write(
      :info,
      "Suppressed repeated jsonsizelimit events before shutdown",
      {category: category, suppressed_events: suppressed}
    )
  end
end