class Lumberjack::Device::Writer
If it is implemented, it will be called before every flush inside a mutex lock.
Subclasses can implement a before_flush
method if they have logic to execute before flushing the log.
and written to the stream in a batch when the buffer is full or when flush
is called.
This logging device writes log entries as strings to an IO stream. By default, messages will be buffered
def buffer_size=(value)
-
(void)
-
Parameters:
-
value
(Integer
) -- The size of the buffer in bytes.
def buffer_size=(value) @buffer_size = value flush end
def close
-
(void)
-
def close flush stream.close end
def datetime_format
-
(String)
- The datetime format.
def datetime_format @template.datetime_format if @template.respond_to?(:datetime_format) end
def datetime_format=(format)
-
(void)
-
Parameters:
-
format
(String
) -- The datetime format.
def datetime_format=(format) if @template.respond_to?(:datetime_format=) @template.datetime_format = format end end
def flush
-
(void)
-
def flush lines = nil @lock.synchronize do before_flush if respond_to?(:before_flush, true) lines = @buffer.pop! end write_to_stream(lines) if lines end
def initialize(stream, options = {})
-
options
(Hash
) -- The options for the device. -
stream
(IO
) -- The stream to write log entries to.
def initialize(stream, options = {}) @lock = Mutex.new @stream = stream @stream.sync = true if @stream.respond_to?(:sync=) @buffer = Buffer.new @buffer_size = (options[:buffer_size] || 0) template = (options[:template] || DEFAULT_FIRST_LINE_TEMPLATE) if template.respond_to?(:call) @template = template else additional_lines = (options[:additional_lines] || DEFAULT_ADDITIONAL_LINES_TEMPLATE) @template = Template.new(template, additional_lines: additional_lines, time_format: options[:time_format]) end end
def write(entry)
-
(void)
-
Parameters:
-
entry
(LogEntry, String
) -- The entry to write to the stream.
def write(entry) string = (entry.is_a?(LogEntry) ? @template.call(entry) : entry) return if string.nil? string = string.strip return if string.length == 0 unless string.encoding == Encoding::UTF_8 string = string.encode("UTF-8", invalid: :replace, undef: :replace) end if buffer_size > 1 @lock.synchronize do @buffer << string end flush if @buffer.size >= buffer_size else flush if respond_to?(:before_flush, true) write_to_stream(string) end end
def write_to_stream(lines)
def write_to_stream(lines) return if lines.empty? lines = lines.first if lines.is_a?(Array) && lines.size == 1 out = nil out = if lines.is_a?(Array) "#{lines.join(Lumberjack::LINE_SEPARATOR)}#{Lumberjack::LINE_SEPARATOR}" else "#{lines}#{Lumberjack::LINE_SEPARATOR}" end begin begin stream.write(out) rescue IOError => e # This condition can happen if another thread closed the stream in the `before_flush` call. # Synchronizing will handle the race condition, but since it's an exceptional case we don't # want to lock the thread on every stream write call. @lock.synchronize do if stream.closed? raise e else stream.write(out) end end end begin stream.flush rescue nil end rescue => e $stderr.write("#{e.class.name}: #{e.message}#{" at " + e.backtrace.first if e.backtrace}") $stderr.write(out) $stderr.flush end end