1
0
mirror of https://github.com/meineerde/rackstash.git synced 2025-10-17 14:01:01 +00:00

Synchronize all writes of the IO adapter against the underlying IO object

This commit is contained in:
Holger Just 2017-07-27 18:06:05 +02:00
parent be6e3517de
commit dcf21d0bfa

View File

@ -32,6 +32,34 @@ module Rackstash
# use-case include {Rackstash::Adapters::File} or
# {Rackstash::Adapters::TCP}.
class IO < Adapter
# This module is by default included into all objects passed to
# {Adapters::IO#initialize}. It allows to synchronize all write accesses
# against this object, even when writing to the same object from multiple
# adapters concurrently.
#
# This e.g. allows multiple Loggers in the same process to write to
# `STDERR` concurrently without risking any overlapping log lines.
module RackstashLock
# Initialize the Mutex to synchronize any accesses of a Rackstash
# adapter to the extended IO object. This method needs to be called at
# least once on an IO object after {RackstashLock} was included into it.
#
# @return [nil]
def init_for_rackstash
@lock_for_rackstash ||= Mutex.new
nil
end
# @yield Obtains a lock on the IO object, runs the block, and releases
# the lock when the block completes.
# @return [Object] the return value of the block
def synchronize_for_rackstash
@lock_for_rackstash.synchronize do
yield
end
end
end
register_for ->(o) { o.respond_to?(:write) && o.respond_to?(:close) }
# @return [Boolean] `true` to ensure that the IO device is flushed after
@ -48,10 +76,10 @@ module Rackstash
raise TypeError, "#{io.inspect} does not look like an IO object"
end
io.extend(RackstashLock) unless io.respond_to?(:synchronize_for_rackstash)
io.init_for_rackstash if io.respond_to?(:init_for_rackstash)
@io = io
@flush_immediately = !!flush_immediately
@mutex = Mutex.new
end
# Write a single log line with a trailing newline character to the IO
@ -60,7 +88,7 @@ module Rackstash
# @param log [#to_s] the encoded log event
# @return [nil]
def write_single(log)
@mutex.synchronize do
@io.synchronize_for_rackstash do
@io.write normalize_line(log)
@io.flush if @flush_immediately
end
@ -74,7 +102,7 @@ module Rackstash
#
# @return [nil]
def close
@mutex.synchronize do
@io.synchronize_for_rackstash do
@io.close
end
nil