class Lumberjack::Device::Writer

This logging device writes log entries as strings to an IO stream. By default, messages will be buffered and written to the stream in a batch when the buffer is full or when flush is called.

Constants

DEFAULT_ADDITIONAL_LINES_TEMPLATE
DEFAULT_FIRST_LINE_TEMPLATE

Attributes

buffer_size[R]

The size of the internal buffer. Defaults to 32K.

Public Class Methods

new(stream, options = {}) click to toggle source

Create a new device to write log entries to a stream. Entries are converted to strings using a Template. The template can be specified using the :template option. This can either be a Proc or a string that will compile into a Template object.

If the template is a Proc, it should accept an LogEntry as its only argument and output a string.

If the template is a template string, it will be used to create a Template. The :additional_lines and :time_format options will be passed through to the Template constuctor.

The default template is "[:time :severity :progname(:pid) #:unit_of_work_id] :message" with additional lines formatted as "\n [#:unit_of_work_id] :message". The unit of work id will only appear if it is present.

The size of the internal buffer in bytes can be set by providing :buffer_size (defaults to 32K).

# File lib/lumberjack/device/writer.rb, line 59
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

Public Instance Methods

buffer_size=(value) click to toggle source

Set the buffer size in bytes. The device will only be physically written to when the buffer size is exceeded.

# File lib/lumberjack/device/writer.rb, line 76
def buffer_size=(value)
  @buffer_size = value
  flush
end
close() click to toggle source

Close the underlying stream.

# File lib/lumberjack/device/writer.rb, line 94
def close
  flush
  stream.close
end
flush() click to toggle source

Flush the underlying stream.

# File lib/lumberjack/device/writer.rb, line 100
def flush
  lines = nil
  @lock.synchronize do
    before_flush
    lines = @buffer.pop!
  end
  
  unless lines.empty?
    out = "#{lines.join(Lumberjack::LINE_SEPARATOR)}#{Lumberjack::LINE_SEPARATOR}"
    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
        # to lock the thread on every stream write call.
        @lock.synchronize do
          if stream.closed?
            raise e
          else
            stream.write(out)
          end
        end
      end
      stream.flush rescue nil
    rescue => e
      $stderr.write("#{e.class.name}: #{e.message}#{' at ' + e.backtrace.first if e.backtrace}")
      $stderr.write(out)
      $stderr.flush
    end
  end
end
write(entry) click to toggle source

Write an entry to the stream. The entry will be converted into a string using the defined template.

# File lib/lumberjack/device/writer.rb, line 82
def write(entry)
  string = @template.call(entry)
  unless string.nil?
    string = string.encode("UTF-8".freeze, invalid: :replace, undef: :replace)
    @lock.synchronize do
      @buffer << string
    end
  end
  flush if @buffer.size >= buffer_size
end

Protected Instance Methods

before_flush() click to toggle source

Callback method that will be executed before data is written to the stream. Subclasses can override this method if needed. This method will be called in a mutex lock.

# File lib/lumberjack/device/writer.rb, line 137
def before_flush
end
stream() click to toggle source

Get the underlying stream.

# File lib/lumberjack/device/writer.rb, line 146
def stream
  @stream
end
stream=(stream) click to toggle source

Set the underlying stream.

# File lib/lumberjack/device/writer.rb, line 141
def stream=(stream)
  @stream = stream
end