Class: Logging::Appenders::Buffering::AsyncFlusher

Inherits:
Object
  • Object
show all
Defined in:
lib/logging/appenders/buffering.rb

Overview

The AsyncFlusher contains an internal run loop that will periodically wake up and flush any log events contained in the message buffer of the owning appender instance. The AsyncFlusher relies on a `signal` from the appender in order to wakeup and perform the flush on the appender.

Instance Method Summary collapse

Constructor Details

#initialize(appender, period) ⇒ AsyncFlusher

Create a new AsyncFlusher instance that will call the `flush` method on the given `appender`. The `flush` method will be called every `period` seconds, but only when the message buffer is non-empty.

appender - The Appender instance to periodically `flush` period - The Numeric sleep period or `nil`


381
382
383
384
385
386
387
388
389
390
391
# File 'lib/logging/appenders/buffering.rb', line 381

def initialize( appender, period )
  @appender = appender
  @period = period

  @mutex = Mutex.new
  @cv = ConditionVariable.new
  @thread = nil
  @waiting = nil
  @signaled = false
  @immediate = 0
end

Instance Method Details

#immediate?Boolean

Returns `true` if the flusher should immeidately write the buffer to the IO destination.

Returns:

  • (Boolean)

453
454
455
# File 'lib/logging/appenders/buffering.rb', line 453

def immediate?
  @immediate > 0
end

#signal(immediate = nil) ⇒ Object

Signal the async flusher. This will wake up the run loop if it is currently waiting for something to do. If the signal method is never called, the async flusher will never perform the flush action on the appender.

immediate - Set to `true` if the sleep period should be skipped

Returns this flusher instance


433
434
435
436
437
438
439
440
441
442
443
# File 'lib/logging/appenders/buffering.rb', line 433

def signal( immediate = nil )
  return if Thread.current == @thread   # don't signal ourselves
  return if @signaled                   # don't need to signal again

  @mutex.synchronize {
    @signaled = true
    @immediate += 1 if immediate
    @cv.signal
  }
  self
end

#startObject

Start the periodic flusher's internal run loop.

Returns this flusher instance


396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'lib/logging/appenders/buffering.rb', line 396

def start
  return if @thread

  @thread = Thread.new { loop {
    begin
      break if Thread.current[:stop]
      _wait_for_signal
      _try_to_sleep
      @appender.flush
    rescue => err
      ::Logging.log_internal {"AsyncFlusher for appender #{@appender.inspect} encountered an error"}
      ::Logging.log_internal_error(err)
    end
  }}

  self
end

#stopObject

Stop the async flusher's internal run loop.

Returns this flusher instance


417
418
419
420
421
422
423
# File 'lib/logging/appenders/buffering.rb', line 417

def stop
  return if @thread.nil?
  @thread[:stop] = true
  signal if waiting?
  @thread = nil
  self
end

#waiting?Boolean

Returns `true` if the flusher is waiting for a signal. Returns `false` if the flusher is somewhere in the processing loop.

Returns:

  • (Boolean)

447
448
449
# File 'lib/logging/appenders/buffering.rb', line 447

def waiting?
  @waiting
end