lumberjack 1.2.7 → 1.2.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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