lumberjack 1.2.7 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,30 +8,30 @@ module Lumberjack
8
8
  # production.log.1, then production.log.2, etc.
9
9
  class SizeRollingLogFile < RollingLogFile
10
10
  attr_reader :max_size
11
-
11
+
12
12
  # Create an new log device to the specified file. The maximum size of the log file is specified with
13
13
  # the :max_size option. The unit can also be specified: "32K", "100M", "2G" are all valid.
14
14
  def initialize(path, options = {})
15
15
  @manual = options[:manual]
16
16
  @max_size = options[:max_size]
17
17
  if @max_size.is_a?(String)
18
- if @max_size.match(/^(\d+(\.\d+)?)([KMG])?$/i)
18
+ if @max_size =~ /^(\d+(\.\d+)?)([KMG])?$/i
19
19
  @max_size = $~[1].to_f
20
20
  units = $~[3].to_s.upcase
21
21
  case units
22
22
  when "K"
23
23
  @max_size *= 1024
24
24
  when "M"
25
- @max_size *= 1024 ** 2
25
+ @max_size *= 1024**2
26
26
  when "G"
27
- @max_size *= 1024 ** 3
27
+ @max_size *= 1024**3
28
28
  end
29
29
  @max_size = @max_size.round
30
30
  else
31
31
  raise ArgumentError.new("illegal value for :max_size (#{@max_size})")
32
32
  end
33
33
  end
34
-
34
+
35
35
  super
36
36
  end
37
37
 
@@ -44,15 +44,15 @@ module Lumberjack
44
44
  rescue SystemCallError
45
45
  false
46
46
  end
47
-
47
+
48
48
  protected
49
-
49
+
50
50
  # Calculate the next archive file name extension.
51
51
  def next_archive_number # :nodoc:
52
52
  max = 0
53
53
  Dir.glob("#{path}.*").each do |filename|
54
- if filename.match(/\.\d+$/)
55
- suffix = filename.split('.').last.to_i
54
+ if /\.\d+\z/ =~ filename
55
+ suffix = filename.split(".").last.to_i
56
56
  max = suffix if suffix > max
57
57
  end
58
58
  end
@@ -60,6 +60,9 @@ module Lumberjack
60
60
  # work id will only appear if it is present.
61
61
  #
62
62
  # The size of the internal buffer in bytes can be set by providing :buffer_size (defaults to 32K).
63
+ #
64
+ # @param [IO] stream The stream to write log entries to.
65
+ # @param [Hash] options The options for the device.
63
66
  def initialize(stream, options = {})
64
67
  @lock = Mutex.new
65
68
  @stream = stream
@@ -71,18 +74,24 @@ module Lumberjack
71
74
  @template = template
72
75
  else
73
76
  additional_lines = (options[:additional_lines] || DEFAULT_ADDITIONAL_LINES_TEMPLATE)
74
- @template = Template.new(template, :additional_lines => additional_lines, :time_format => options[:time_format])
77
+ @template = Template.new(template, additional_lines: additional_lines, time_format: options[:time_format])
75
78
  end
76
79
  end
77
80
 
78
81
  # Set the buffer size in bytes. The device will only be physically written to when the buffer size
79
82
  # is exceeded.
83
+ #
84
+ # @param [Integer] value The size of the buffer in bytes.
85
+ # @return [void]
80
86
  def buffer_size=(value)
81
87
  @buffer_size = value
82
88
  flush
83
89
  end
84
90
 
85
91
  # Write an entry to the stream. The entry will be converted into a string using the defined template.
92
+ #
93
+ # @param [LogEntry, String] entry The entry to write to the stream.
94
+ # @return [void]
86
95
  def write(entry)
87
96
  string = (entry.is_a?(LogEntry) ? @template.call(entry) : entry)
88
97
  return if string.nil?
@@ -105,12 +114,16 @@ module Lumberjack
105
114
  end
106
115
 
107
116
  # Close the underlying stream.
117
+ #
118
+ # @return [void]
108
119
  def close
109
120
  flush
110
121
  stream.close
111
122
  end
112
123
 
113
124
  # Flush the underlying stream.
125
+ #
126
+ # @return [void]
114
127
  def flush
115
128
  lines = nil
116
129
  @lock.synchronize do
@@ -120,10 +133,17 @@ module Lumberjack
120
133
  write_to_stream(lines) if lines
121
134
  end
122
135
 
136
+ # Get the datetime format.
137
+ #
138
+ # @return [String] The datetime format.
123
139
  def datetime_format
124
140
  @template.datetime_format if @template.respond_to?(:datetime_format)
125
141
  end
126
142
 
143
+ # Set the datetime format.
144
+ #
145
+ # @param [String] format The datetime format.
146
+ # @return [void]
127
147
  def datetime_format=(format)
128
148
  if @template.respond_to?(:datetime_format=)
129
149
  @template.datetime_format = format
@@ -133,14 +153,10 @@ module Lumberjack
133
153
  protected
134
154
 
135
155
  # Set the underlying stream.
136
- def stream=(stream)
137
- @stream = stream
138
- end
156
+ attr_writer :stream
139
157
 
140
158
  # Get the underlying stream.
141
- def stream
142
- @stream
143
- end
159
+ attr_reader :stream
144
160
 
145
161
  private
146
162
 
@@ -149,10 +165,10 @@ module Lumberjack
149
165
  lines = lines.first if lines.is_a?(Array) && lines.size == 1
150
166
 
151
167
  out = nil
152
- if lines.is_a?(Array)
153
- out = "#{lines.join(Lumberjack::LINE_SEPARATOR)}#{Lumberjack::LINE_SEPARATOR}"
168
+ out = if lines.is_a?(Array)
169
+ "#{lines.join(Lumberjack::LINE_SEPARATOR)}#{Lumberjack::LINE_SEPARATOR}"
154
170
  else
155
- out = "#{lines}#{Lumberjack::LINE_SEPARATOR}"
171
+ "#{lines}#{Lumberjack::LINE_SEPARATOR}"
156
172
  end
157
173
 
158
174
  begin
@@ -170,9 +186,13 @@ module Lumberjack
170
186
  end
171
187
  end
172
188
  end
173
- stream.flush rescue nil
189
+ begin
190
+ stream.flush
191
+ rescue
192
+ nil
193
+ end
174
194
  rescue => e
175
- $stderr.write("#{e.class.name}: #{e.message}#{' at ' + e.backtrace.first if e.backtrace}")
195
+ $stderr.write("#{e.class.name}: #{e.message}#{" at " + e.backtrace.first if e.backtrace}")
176
196
  $stderr.write(out)
177
197
  $stderr.flush
178
198
  end
@@ -4,38 +4,53 @@ module Lumberjack
4
4
  # This is an abstract class for logging devices. Subclasses must implement the +write+ method and
5
5
  # may implement the +close+ and +flush+ methods if applicable.
6
6
  class Device
7
- require_relative "device/writer.rb"
8
- require_relative "device/log_file.rb"
9
- require_relative "device/rolling_log_file.rb"
10
- require_relative "device/date_rolling_log_file.rb"
11
- require_relative "device/size_rolling_log_file.rb"
12
- require_relative "device/multi.rb"
13
- require_relative "device/null.rb"
7
+ require_relative "device/writer"
8
+ require_relative "device/log_file"
9
+ require_relative "device/rolling_log_file"
10
+ require_relative "device/date_rolling_log_file"
11
+ require_relative "device/size_rolling_log_file"
12
+ require_relative "device/multi"
13
+ require_relative "device/null"
14
14
 
15
15
  # Subclasses must implement this method to write a LogEntry.
16
+ #
17
+ # @param [Lumberjack::LogEntry] entry The entry to write.
18
+ # @return [void]
16
19
  def write(entry)
17
20
  raise NotImplementedError
18
21
  end
19
-
22
+
20
23
  # Subclasses may implement this method to close the device.
24
+ #
25
+ # @return [void]
21
26
  def close
22
27
  flush
23
28
  end
24
-
29
+
25
30
  # Subclasses may implement this method to reopen the device.
31
+ #
32
+ # @param [Object] logdev The log device to use.
33
+ # @return [void]
26
34
  def reopen(logdev = nil)
27
35
  flush
28
36
  end
29
-
37
+
30
38
  # Subclasses may implement this method to flush any buffers used by the device.
39
+ #
40
+ # @return [void]
31
41
  def flush
32
42
  end
33
-
43
+
34
44
  # Subclasses may implement this method to get the format for log timestamps.
45
+ #
46
+ # @return [String] The format for log timestamps.
35
47
  def datetime_format
36
48
  end
37
-
49
+
38
50
  # Subclasses may implement this method to set a format for log timestamps.
51
+ #
52
+ # @param [String] format The format for log timestamps.
53
+ # @return [void]
39
54
  def datetime_format=(format)
40
55
  end
41
56
  end
@@ -5,13 +5,13 @@ module Lumberjack
5
5
  # Format a Date, Time, or DateTime object. If you don't specify a format in the constructor,
6
6
  # it will use the ISO-8601 format.
7
7
  class DateTimeFormatter
8
-
9
8
  attr_reader :format
10
-
9
+
10
+ # @param [String] format The format to use when formatting the date/time object.
11
11
  def initialize(format = nil)
12
12
  @format = format.dup.to_s.freeze unless format.nil?
13
13
  end
14
-
14
+
15
15
  def call(obj)
16
16
  if @format && obj.respond_to?(:strftime)
17
17
  obj.strftime(@format)
@@ -7,9 +7,10 @@ module Lumberjack
7
7
  # passed to this object and the returned array is what will be logged. You can
8
8
  # use this to clean out superfluous lines.
9
9
  class ExceptionFormatter
10
-
11
10
  attr_accessor :backtrace_cleaner
12
11
 
12
+ # @param [#call] backtrace_cleaner An object that responds to `call` and takes
13
+ # an array of strings (the backtrace) and returns an array of strings (the
13
14
  def initialize(backtrace_cleaner = nil)
14
15
  self.backtrace_cleaner = backtrace_cleaner
15
16
  end
@@ -33,7 +34,6 @@ module Lumberjack
33
34
  trace
34
35
  end
35
36
  end
36
-
37
37
  end
38
38
  end
39
39
  end
@@ -6,14 +6,15 @@ module Lumberjack
6
6
  # as a default formatter for objects pulled from a data store. By default it will use :id as the
7
7
  # id attribute.
8
8
  class IdFormatter
9
+ # @param [Symbol, String] id_attribute The attribute to use as the id.
9
10
  def initialize(id_attribute = :id)
10
11
  @id_attribute = id_attribute
11
12
  end
12
-
13
+
13
14
  def call(obj)
14
15
  if obj.respond_to?(@id_attribute)
15
16
  id = obj.send(@id_attribute)
16
- { "class" => obj.class.name, "id" => id }
17
+ {"class" => obj.class.name, "id" => id}
17
18
  else
18
19
  obj.to_s
19
20
  end
@@ -1,20 +1,22 @@
1
1
  # frozen_string_literals: true
2
2
 
3
- require 'pp'
4
- require 'stringio'
3
+ require "pp"
4
+ require "stringio"
5
5
 
6
6
  module Lumberjack
7
7
  class Formatter
8
8
  # Format an object with it's pretty print method.
9
9
  class PrettyPrintFormatter
10
10
  attr_accessor :width
11
-
11
+
12
12
  # Create a new formatter. The maximum width of the message can be specified with the width
13
13
  # parameter (defaults to 79 characters).
14
+ #
15
+ # @param [Integer] width The maximum width of the message.
14
16
  def initialize(width = 79)
15
17
  @width = width
16
18
  end
17
-
19
+
18
20
  def call(obj)
19
21
  s = StringIO.new
20
22
  PP.pp(obj, s)
@@ -9,6 +9,8 @@ module Lumberjack
9
9
  class RecusiveReferenceError < StandardError
10
10
  end
11
11
 
12
+ # @param [Formatter] formatter The formatter to call on each element
13
+ # in the structure.
12
14
  def initialize(formatter = nil)
13
15
  @formatter = formatter
14
16
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literals: true
2
+
3
+ module Lumberjack
4
+ class Formatter
5
+ # Truncate a string object to a specific length. This is useful
6
+ # for formatting messages when there is a limit on the number of
7
+ # characters that can be logged per message. This formatter should
8
+ # only be used when necessary since it is a lossy formatter.
9
+ #
10
+ # When a string is truncated, it will have a unicode ellipsis
11
+ # character (U+2026) appended to the end of the string.
12
+ class TruncateFormatter
13
+ # @param [Integer] length The maximum length of the string (defaults to 32K)
14
+ def initialize(length = 32768)
15
+ @length = length
16
+ end
17
+
18
+ def call(obj)
19
+ if obj.is_a?(String) && obj.length > @length
20
+ "#{obj[0, @length - 1]}…"
21
+ else
22
+ obj
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -12,25 +12,28 @@ module Lumberjack
12
12
  #
13
13
  # Enumerable objects (including Hash and Array) will call the formatter recursively for each element.
14
14
  class Formatter
15
- require_relative "formatter/date_time_formatter.rb"
16
- require_relative "formatter/exception_formatter.rb"
17
- require_relative "formatter/id_formatter.rb"
18
- require_relative "formatter/inspect_formatter.rb"
19
- require_relative "formatter/object_formatter.rb"
20
- require_relative "formatter/pretty_print_formatter.rb"
21
- require_relative "formatter/string_formatter.rb"
22
- require_relative "formatter/strip_formatter.rb"
23
- require_relative "formatter/structured_formatter.rb"
15
+ require_relative "formatter/date_time_formatter"
16
+ require_relative "formatter/exception_formatter"
17
+ require_relative "formatter/id_formatter"
18
+ require_relative "formatter/inspect_formatter"
19
+ require_relative "formatter/object_formatter"
20
+ require_relative "formatter/pretty_print_formatter"
21
+ require_relative "formatter/string_formatter"
22
+ require_relative "formatter/strip_formatter"
23
+ require_relative "formatter/structured_formatter"
24
+ require_relative "formatter/truncate_formatter"
24
25
 
25
26
  class << self
26
27
  # Returns a new empty formatter with no mapping. For historical reasons, a formatter
27
28
  # is initialized with mappings to help output objects as strings. This will return one
28
29
  # without the default mappings.
30
+ #
31
+ # @return [Lumberjack::Formatter] a new empty formatter
29
32
  def empty
30
33
  new.clear
31
34
  end
32
35
  end
33
-
36
+
34
37
  def initialize
35
38
  @class_formatters = {}
36
39
  @module_formatters = {}
@@ -45,7 +48,17 @@ module Lumberjack
45
48
  # that responds to the +call+ method or as a symbol representing one of the predefined
46
49
  # formatters, or as a block to the method call.
47
50
  #
48
- # The predefined formatters are: :inspect, :string, :exception, and :pretty_print.
51
+ # The predefined formatters are:
52
+ # - :date_time
53
+ # - :exception
54
+ # - :id
55
+ # - :inspect
56
+ # - :object
57
+ # - :pretty_print
58
+ # - :string
59
+ # - :strip
60
+ # - :structured
61
+ # - :truncate
49
62
  #
50
63
  # You can add multiple classes at once by passing an array of classes.
51
64
  #
@@ -53,7 +66,18 @@ module Lumberjack
53
66
  # help avoid loading dependency issues. This applies only to classes; modules cannot be
54
67
  # passed in as strings.
55
68
  #
56
- # === Examples
69
+ # @param [Class, Module, String, Array<Class, Module, String>] klass The class or module to add a formatter for.
70
+ # @param [Symbol, Class, String, #call] formatter The formatter to use for the class.
71
+ # If a symbol is passed in, it will be used to load one of the predefined formatters.
72
+ # If a class is passed in, it will be initialized with the args passed in.
73
+ # Otherwise, the object will be used as the formatter and must respond to call method.
74
+ # @param [Array] args Arguments to pass to the formatter when it is initialized.
75
+ # @yield [obj] A block that will be used as the formatter for the class.
76
+ # @yieldparam [Object] obj The object to format.
77
+ # @yieldreturn [String] The formatted string.
78
+ # @return [self] Returns itself so that add statements can be chained together.
79
+ #
80
+ # @example
57
81
  #
58
82
  # # Use a predefined formatter
59
83
  # formatter.add(MyClass, :pretty_print)
@@ -66,18 +90,27 @@ module Lumberjack
66
90
  #
67
91
  # # Add statements can be chained together
68
92
  # formatter.add(MyClass, :pretty_print).add(YourClass){|obj| obj.humanize}
69
- def add(klass, formatter = nil, &block)
93
+ def add(klass, formatter = nil, *args, &block)
70
94
  formatter ||= block
71
95
  if formatter.nil?
72
96
  remove(klass)
73
97
  else
98
+ formatter_class_name = nil
74
99
  if formatter.is_a?(Symbol)
75
- formatter_class_name = "#{formatter.to_s.gsub(/(^|_)([a-z])/){|m| $~[2].upcase}}Formatter"
76
- formatter = Formatter.const_get(formatter_class_name).new
100
+ formatter_class_name = "#{formatter.to_s.gsub(/(^|_)([a-z])/) { |m| $~[2].upcase }}Formatter"
101
+ elsif formatter.is_a?(String)
102
+ formatter_class_name = formatter
103
+ end
104
+ if formatter_class_name
105
+ formatter = Formatter.const_get(formatter_class_name)
77
106
  end
78
-
107
+
108
+ if formatter.is_a?(Class)
109
+ formatter = formatter.new(*args)
110
+ end
111
+
79
112
  Array(klass).each do |k|
80
- if k.class == Module
113
+ if k.instance_of?(Module)
81
114
  @module_formatters[k] = formatter
82
115
  else
83
116
  k = k.name if k.is_a?(Class)
@@ -95,9 +128,12 @@ module Lumberjack
95
128
  # You can also pass class names as strings instead of the classes themselves. This can
96
129
  # help avoid loading dependency issues. This applies only to classes; modules cannot be
97
130
  # passed in as strings.
131
+ #
132
+ # @param [Class, Module, String, Array<Class, Module, String>] klass The class or module to remove the formatters for.
133
+ # @return [self] Returns itself so that remove statements can be chained together.
98
134
  def remove(klass)
99
135
  Array(klass).each do |k|
100
- if k.class == Module
136
+ if k.instance_of?(Module)
101
137
  @module_formatters.delete(k)
102
138
  else
103
139
  k = k.name if k.is_a?(Class)
@@ -106,18 +142,23 @@ module Lumberjack
106
142
  end
107
143
  self
108
144
  end
109
-
145
+
110
146
  # Remove all formatters including the default formatter. Can be chained to add method calls.
147
+ #
148
+ # @return [self] Returns itself so that clear statements can be chained together.
111
149
  def clear
112
150
  @class_formatters.clear
113
151
  @module_formatters.clear
114
152
  self
115
153
  end
116
154
 
117
- # Format a message object as a string.
155
+ # Format a message object by applying all formatters attached to it.
156
+ #
157
+ # @param [Object] message The message object to format.
158
+ # @return [Object] The formatted object.
118
159
  def format(message)
119
160
  formatter = formatter_for(message.class)
120
- if formatter && formatter.respond_to?(:call)
161
+ if formatter&.respond_to?(:call)
121
162
  formatter.call(message)
122
163
  else
123
164
  message
@@ -126,6 +167,11 @@ module Lumberjack
126
167
 
127
168
  # Compatibility with the Logger::Formatter signature. This method will just convert the message
128
169
  # object to a string and ignores the other parameters.
170
+ #
171
+ # @param [Integer, String, Symbol] severity The severity of the message.
172
+ # @param [Time] timestamp The time the message was logged.
173
+ # @param [String] progname The name of the program logging the message.
174
+ # @param [Object] msg The message object to format.
129
175
  def call(severity, timestamp, progname, msg)
130
176
  "#{format(msg)}#{Lumberjack::LINE_SEPARATOR}"
131
177
  end
@@ -133,9 +179,9 @@ module Lumberjack
133
179
  private
134
180
 
135
181
  # Find the formatter for a class by looking it up using the class hierarchy.
136
- def formatter_for(klass) #:nodoc:
182
+ def formatter_for(klass) # :nodoc:
137
183
  check_modules = true
138
- while klass != nil do
184
+ until klass.nil?
139
185
  formatter = @class_formatters[klass.name]
140
186
  return formatter if formatter
141
187
 
@@ -10,6 +10,14 @@ module Lumberjack
10
10
 
11
11
  UNIT_OF_WORK_ID = "unit_of_work_id"
12
12
 
13
+ # Create a new log entry.
14
+ #
15
+ # @param [Time] time The time the log entry was created.
16
+ # @param [Integer, String] severity The severity of the log entry.
17
+ # @param [String] message The message to log.
18
+ # @param [String] progname The name of the program that created the log entry.
19
+ # @param [Integer] pid The process id of the program that created the log entry.
20
+ # @param [Hash] tags A hash of tags to associate with the log entry.
13
21
  def initialize(time, severity, message, progname, pid, tags)
14
22
  @time = time
15
23
  @severity = (severity.is_a?(Integer) ? severity : Severity.label_to_level(severity))
@@ -17,10 +25,10 @@ module Lumberjack
17
25
  @progname = progname
18
26
  @pid = pid
19
27
  # backward compatibility with 1.0 API where the last argument was the unit of work id
20
- if tags.nil? || tags.is_a?(Hash)
21
- @tags = tags
28
+ @tags = if tags.nil? || tags.is_a?(Hash)
29
+ tags
22
30
  else
23
- @tags = { UNIT_OF_WORK_ID => tags }
31
+ {UNIT_OF_WORK_ID => tags}
24
32
  end
25
33
  end
26
34
 
@@ -29,7 +37,7 @@ module Lumberjack
29
37
  end
30
38
 
31
39
  def to_s
32
- "[#{time.strftime(TIME_FORMAT)}.#{(time.usec / 1000.0).round.to_s.rjust(3, '0')} #{severity_label} #{progname}(#{pid})#{tags_to_s}] #{message}"
40
+ "[#{time.strftime(TIME_FORMAT)}.#{(time.usec / 1000.0).round.to_s.rjust(3, "0")} #{severity_label} #{progname}(#{pid})#{tags_to_s}] #{message}"
33
41
  end
34
42
 
35
43
  def inspect
@@ -46,10 +54,10 @@ module Lumberjack
46
54
  if tags
47
55
  tags[UNIT_OF_WORK_ID] = value
48
56
  else
49
- @tags = { UNIT_OF_WORK_ID => value }
57
+ @tags = {UNIT_OF_WORK_ID => value}
50
58
  end
51
59
  end
52
-
60
+
53
61
  # Return the tag with the specified name.
54
62
  def tag(name)
55
63
  tags[name.to_s] if tags
@@ -58,10 +66,8 @@ module Lumberjack
58
66
  private
59
67
 
60
68
  def tags_to_s
61
- tags_string = String.new
62
- if tags
63
- tags.each { |name, value| tags_string << " #{name}:#{value.inspect}" }
64
- end
69
+ tags_string = ""
70
+ tags&.each { |name, value| tags_string << " #{name}:#{value.inspect}" }
65
71
  tags_string
66
72
  end
67
73
  end