Class: Lumberjack::Device::Writer

Inherits:
Lumberjack::Device show all
Defined in:
lib/lumberjack/device/writer.rb

Overview

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.

Subclasses can implement a before_flush method if they have logic to execute before flushing the log. If it is implemented, it will be called before every flush inside a mutex lock.

Direct Known Subclasses

LogFile

Defined Under Namespace

Classes: Buffer

Constant Summary collapse

DEFAULT_FIRST_LINE_TEMPLATE =
"[:time :severity :progname(:pid) #:unit_of_work_id] :message :tags"
DEFAULT_ADDITIONAL_LINES_TEMPLATE =
"#{Lumberjack::LINE_SEPARATOR}> [#:unit_of_work_id] :message"

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Lumberjack::Device

#cleanup_files!, #do_once, #reopen

Constructor Details

#initialize(stream, options = {}) ⇒ Writer

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).



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/lumberjack/device/writer.rb', line 63

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

Instance Attribute Details

#buffer_sizeObject

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



15
16
17
# File 'lib/lumberjack/device/writer.rb', line 15

def buffer_size
  @buffer_size
end

Instance Method Details

#closeObject

Close the underlying stream.



108
109
110
111
# File 'lib/lumberjack/device/writer.rb', line 108

def close
  flush
  stream.close
end

#datetime_formatObject



123
124
125
# File 'lib/lumberjack/device/writer.rb', line 123

def datetime_format
  @template.datetime_format if @template.respond_to?(:datetime_format)
end

#datetime_format=(format) ⇒ Object



127
128
129
130
131
# File 'lib/lumberjack/device/writer.rb', line 127

def datetime_format=(format)
  if @template.respond_to?(:datetime_format=)
    @template.datetime_format = format
  end
end

#flushObject

Flush the underlying stream.



114
115
116
117
118
119
120
121
# File 'lib/lumberjack/device/writer.rb', line 114

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

#write(entry) ⇒ Object

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



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/lumberjack/device/writer.rb', line 86

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