lumberjack 1.2.3 → 1.2.8
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -8
- data/{MIT_LICENSE → MIT_LICENSE.txt} +0 -0
- data/README.md +11 -8
- data/VERSION +1 -1
- data/lib/lumberjack.rb +38 -28
- data/lib/lumberjack/device.rb +12 -12
- data/lib/lumberjack/device/date_rolling_log_file.rb +7 -7
- data/lib/lumberjack/device/log_file.rb +6 -6
- data/lib/lumberjack/device/multi.rb +6 -6
- data/lib/lumberjack/device/null.rb +1 -1
- data/lib/lumberjack/device/rolling_log_file.rb +43 -19
- data/lib/lumberjack/device/size_rolling_log_file.rb +9 -9
- data/lib/lumberjack/device/writer.rb +12 -12
- data/lib/lumberjack/formatter.rb +15 -15
- data/lib/lumberjack/formatter/date_time_formatter.rb +2 -3
- data/lib/lumberjack/formatter/exception_formatter.rb +0 -2
- data/lib/lumberjack/formatter/id_formatter.rb +2 -2
- data/lib/lumberjack/formatter/pretty_print_formatter.rb +4 -4
- data/lib/lumberjack/formatter/structured_formatter.rb +31 -16
- data/lib/lumberjack/log_entry.rb +8 -10
- data/lib/lumberjack/logger.rb +90 -28
- data/lib/lumberjack/rack.rb +3 -3
- data/lib/lumberjack/rack/request_id.rb +1 -1
- data/lib/lumberjack/rack/unit_of_work.rb +1 -1
- data/lib/lumberjack/severity.rb +1 -2
- data/lib/lumberjack/tag_formatter.rb +1 -3
- data/lib/lumberjack/tagged_logger_support.rb +0 -1
- data/lib/lumberjack/tagged_logging.rb +29 -0
- data/lib/lumberjack/tags.rb +1 -1
- data/lib/lumberjack/template.rb +2 -2
- data/lumberjack.gemspec +12 -16
- metadata +5 -46
@@ -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
|
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
|
25
|
+
@max_size *= 1024**2
|
26
26
|
when "G"
|
27
|
-
@max_size *= 1024
|
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
|
55
|
-
suffix = filename.split(
|
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
|
@@ -71,7 +71,7 @@ module Lumberjack
|
|
71
71
|
@template = template
|
72
72
|
else
|
73
73
|
additional_lines = (options[:additional_lines] || DEFAULT_ADDITIONAL_LINES_TEMPLATE)
|
74
|
-
@template = Template.new(template, :
|
74
|
+
@template = Template.new(template, additional_lines: additional_lines, time_format: options[:time_format])
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
@@ -133,14 +133,10 @@ module Lumberjack
|
|
133
133
|
protected
|
134
134
|
|
135
135
|
# Set the underlying stream.
|
136
|
-
|
137
|
-
@stream = stream
|
138
|
-
end
|
136
|
+
attr_writer :stream
|
139
137
|
|
140
138
|
# Get the underlying stream.
|
141
|
-
|
142
|
-
@stream
|
143
|
-
end
|
139
|
+
attr_reader :stream
|
144
140
|
|
145
141
|
private
|
146
142
|
|
@@ -149,10 +145,10 @@ module Lumberjack
|
|
149
145
|
lines = lines.first if lines.is_a?(Array) && lines.size == 1
|
150
146
|
|
151
147
|
out = nil
|
152
|
-
if lines.is_a?(Array)
|
153
|
-
|
148
|
+
out = if lines.is_a?(Array)
|
149
|
+
"#{lines.join(Lumberjack::LINE_SEPARATOR)}#{Lumberjack::LINE_SEPARATOR}"
|
154
150
|
else
|
155
|
-
|
151
|
+
"#{lines}#{Lumberjack::LINE_SEPARATOR}"
|
156
152
|
end
|
157
153
|
|
158
154
|
begin
|
@@ -170,9 +166,13 @@ module Lumberjack
|
|
170
166
|
end
|
171
167
|
end
|
172
168
|
end
|
173
|
-
|
169
|
+
begin
|
170
|
+
stream.flush
|
171
|
+
rescue
|
172
|
+
nil
|
173
|
+
end
|
174
174
|
rescue => e
|
175
|
-
$stderr.write("#{e.class.name}: #{e.message}#{
|
175
|
+
$stderr.write("#{e.class.name}: #{e.message}#{" at " + e.backtrace.first if e.backtrace}")
|
176
176
|
$stderr.write(out)
|
177
177
|
$stderr.flush
|
178
178
|
end
|
data/lib/lumberjack/formatter.rb
CHANGED
@@ -12,15 +12,15 @@ 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
|
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
|
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
24
|
|
25
25
|
class << self
|
26
26
|
# Returns a new empty formatter with no mapping. For historical reasons, a formatter
|
@@ -30,7 +30,7 @@ module Lumberjack
|
|
30
30
|
new.clear
|
31
31
|
end
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def initialize
|
35
35
|
@class_formatters = {}
|
36
36
|
@module_formatters = {}
|
@@ -72,10 +72,10 @@ module Lumberjack
|
|
72
72
|
remove(klass)
|
73
73
|
else
|
74
74
|
if formatter.is_a?(Symbol)
|
75
|
-
formatter_class_name = "#{formatter.to_s.gsub(/(^|_)([a-z])/){|m| $~[2].upcase}}Formatter"
|
75
|
+
formatter_class_name = "#{formatter.to_s.gsub(/(^|_)([a-z])/) { |m| $~[2].upcase }}Formatter"
|
76
76
|
formatter = Formatter.const_get(formatter_class_name).new
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
Array(klass).each do |k|
|
80
80
|
if k.class == Module
|
81
81
|
@module_formatters[k] = formatter
|
@@ -106,7 +106,7 @@ module Lumberjack
|
|
106
106
|
end
|
107
107
|
self
|
108
108
|
end
|
109
|
-
|
109
|
+
|
110
110
|
# Remove all formatters including the default formatter. Can be chained to add method calls.
|
111
111
|
def clear
|
112
112
|
@class_formatters.clear
|
@@ -117,7 +117,7 @@ module Lumberjack
|
|
117
117
|
# Format a message object as a string.
|
118
118
|
def format(message)
|
119
119
|
formatter = formatter_for(message.class)
|
120
|
-
if formatter
|
120
|
+
if formatter&.respond_to?(:call)
|
121
121
|
formatter.call(message)
|
122
122
|
else
|
123
123
|
message
|
@@ -135,7 +135,7 @@ module Lumberjack
|
|
135
135
|
# Find the formatter for a class by looking it up using the class hierarchy.
|
136
136
|
def formatter_for(klass) #:nodoc:
|
137
137
|
check_modules = true
|
138
|
-
|
138
|
+
until klass.nil?
|
139
139
|
formatter = @class_formatters[klass.name]
|
140
140
|
return formatter if formatter
|
141
141
|
|
@@ -5,13 +5,12 @@ 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
|
+
|
11
10
|
def initialize(format = nil)
|
12
11
|
@format = format.dup.to_s.freeze unless format.nil?
|
13
12
|
end
|
14
|
-
|
13
|
+
|
15
14
|
def call(obj)
|
16
15
|
if @format && obj.respond_to?(:strftime)
|
17
16
|
obj.strftime(@format)
|
@@ -7,7 +7,6 @@ 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
|
|
13
12
|
def initialize(backtrace_cleaner = nil)
|
@@ -33,7 +32,6 @@ module Lumberjack
|
|
33
32
|
trace
|
34
33
|
end
|
35
34
|
end
|
36
|
-
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
@@ -9,11 +9,11 @@ module Lumberjack
|
|
9
9
|
def initialize(id_attribute = :id)
|
10
10
|
@id_attribute = id_attribute
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def call(obj)
|
14
14
|
if obj.respond_to?(@id_attribute)
|
15
15
|
id = obj.send(@id_attribute)
|
16
|
-
{
|
16
|
+
{"class" => obj.class.name, "id" => id}
|
17
17
|
else
|
18
18
|
obj.to_s
|
19
19
|
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
# frozen_string_literals: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
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
14
|
def initialize(width = 79)
|
15
15
|
@width = width
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def call(obj)
|
19
19
|
s = StringIO.new
|
20
20
|
PP.pp(obj, s)
|
@@ -6,6 +6,9 @@ module Lumberjack
|
|
6
6
|
class Formatter
|
7
7
|
# Dereference arrays and hashes and recursively call formatters on each element.
|
8
8
|
class StructuredFormatter
|
9
|
+
class RecusiveReferenceError < StandardError
|
10
|
+
end
|
11
|
+
|
9
12
|
def initialize(formatter = nil)
|
10
13
|
@formatter = formatter
|
11
14
|
end
|
@@ -18,31 +21,43 @@ module Lumberjack
|
|
18
21
|
|
19
22
|
def call_with_references(obj, references)
|
20
23
|
if obj.is_a?(Hash)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
with_object_reference(obj, references) do
|
25
|
+
hash = {}
|
26
|
+
obj.each do |name, value|
|
27
|
+
value = call_with_references(value, references)
|
28
|
+
hash[name.to_s] = value unless value.is_a?(RecusiveReferenceError)
|
29
|
+
end
|
30
|
+
hash
|
27
31
|
end
|
28
|
-
references.delete(obj.object_id)
|
29
|
-
hash
|
30
32
|
elsif obj.is_a?(Enumerable) && obj.respond_to?(:size) && obj.size != Float::INFINITY
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
with_object_reference(obj, references) do
|
34
|
+
array = []
|
35
|
+
obj.each do |value|
|
36
|
+
value = call_with_references(value, references)
|
37
|
+
array << value unless value.is_a?(RecusiveReferenceError)
|
38
|
+
end
|
39
|
+
array
|
37
40
|
end
|
38
|
-
references.delete(obj.object_id)
|
39
|
-
array
|
40
41
|
elsif @formatter
|
41
42
|
@formatter.format(obj)
|
42
43
|
else
|
43
44
|
obj
|
44
45
|
end
|
45
46
|
end
|
47
|
+
|
48
|
+
def with_object_reference(obj, references)
|
49
|
+
if obj.is_a?(Enumerable)
|
50
|
+
return RecusiveReferenceError.new if references.include?(obj.object_id)
|
51
|
+
references << obj.object_id
|
52
|
+
begin
|
53
|
+
yield
|
54
|
+
ensure
|
55
|
+
references.delete(obj.object_id)
|
56
|
+
end
|
57
|
+
else
|
58
|
+
yield
|
59
|
+
end
|
60
|
+
end
|
46
61
|
end
|
47
62
|
end
|
48
63
|
end
|
data/lib/lumberjack/log_entry.rb
CHANGED
@@ -17,10 +17,10 @@ module Lumberjack
|
|
17
17
|
@progname = progname
|
18
18
|
@pid = pid
|
19
19
|
# 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
|
-
|
20
|
+
@tags = if tags.nil? || tags.is_a?(Hash)
|
21
|
+
tags
|
22
22
|
else
|
23
|
-
|
23
|
+
{UNIT_OF_WORK_ID => tags}
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -29,7 +29,7 @@ module Lumberjack
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def to_s
|
32
|
-
"[#{time.strftime(TIME_FORMAT)}.#{(time.usec / 1000.0).round.to_s.rjust(3,
|
32
|
+
"[#{time.strftime(TIME_FORMAT)}.#{(time.usec / 1000.0).round.to_s.rjust(3, "0")} #{severity_label} #{progname}(#{pid})#{tags_to_s}] #{message}"
|
33
33
|
end
|
34
34
|
|
35
35
|
def inspect
|
@@ -46,10 +46,10 @@ module Lumberjack
|
|
46
46
|
if tags
|
47
47
|
tags[UNIT_OF_WORK_ID] = value
|
48
48
|
else
|
49
|
-
@tags = {
|
49
|
+
@tags = {UNIT_OF_WORK_ID => value}
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
# Return the tag with the specified name.
|
54
54
|
def tag(name)
|
55
55
|
tags[name.to_s] if tags
|
@@ -58,10 +58,8 @@ module Lumberjack
|
|
58
58
|
private
|
59
59
|
|
60
60
|
def tags_to_s
|
61
|
-
tags_string =
|
62
|
-
|
63
|
-
tags.each { |name, value| tags_string << " #{name}:#{value.inspect}" }
|
64
|
-
end
|
61
|
+
tags_string = ""
|
62
|
+
tags&.each { |name, value| tags_string << " #{name}:#{value.inspect}" }
|
65
63
|
tags_string
|
66
64
|
end
|
67
65
|
end
|
data/lib/lumberjack/logger.rb
CHANGED
@@ -63,7 +63,7 @@ module Lumberjack
|
|
63
63
|
# * :max_size - If the log device is a file path, it will be a Device::SizeRollingLogFile if this is set.
|
64
64
|
#
|
65
65
|
# All other options are passed to the device constuctor.
|
66
|
-
def initialize(device =
|
66
|
+
def initialize(device = $stdout, options = {})
|
67
67
|
options = options.dup
|
68
68
|
self.level = options.delete(:level) || INFO
|
69
69
|
self.progname = options.delete(:progname)
|
@@ -100,19 +100,19 @@ module Lumberjack
|
|
100
100
|
thread_local_value(:lumberjack_logger_level) || @level
|
101
101
|
end
|
102
102
|
|
103
|
-
|
103
|
+
alias sev_threshold level
|
104
104
|
|
105
105
|
# Set the log level using either an integer level like Logger::INFO or a label like
|
106
106
|
# :info or "info"
|
107
107
|
def level=(value)
|
108
|
-
if value.is_a?(Integer)
|
109
|
-
|
108
|
+
@level = if value.is_a?(Integer)
|
109
|
+
value
|
110
110
|
else
|
111
|
-
|
111
|
+
Severity.label_to_level(value)
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
-
|
115
|
+
alias sev_threshold= level=
|
116
116
|
|
117
117
|
# Set the Lumberjack::Formatter used to format objects for logging as messages.
|
118
118
|
def formatter=(value)
|
@@ -137,7 +137,7 @@ module Lumberjack
|
|
137
137
|
# in an array under the "tagged" tag. So calling `logger.tagged("foo", "bar")` will result
|
138
138
|
# in tags `{"tagged" => ["foo", "bar"]}`.
|
139
139
|
def tagged_logger!
|
140
|
-
|
140
|
+
extend(TaggedLoggerSupport)
|
141
141
|
self
|
142
142
|
end
|
143
143
|
|
@@ -156,10 +156,10 @@ module Lumberjack
|
|
156
156
|
# logger.add_entry(:warn, "Request took a long time")
|
157
157
|
# logger.add_entry(Logger::DEBUG){"Start processing with options #{options.inspect}"}
|
158
158
|
def add_entry(severity, message, progname = nil, tags = nil)
|
159
|
-
begin
|
159
|
+
begin
|
160
160
|
severity = Severity.label_to_level(severity) unless severity.is_a?(Integer)
|
161
161
|
return true unless device && severity && severity >= level
|
162
|
-
|
162
|
+
|
163
163
|
return true if Thread.current[:lumberjack_logging]
|
164
164
|
Thread.current[:lumberjack_logging] = true
|
165
165
|
|
@@ -173,10 +173,10 @@ module Lumberjack
|
|
173
173
|
if current_tags.empty?
|
174
174
|
tags = Tags.stringify_keys(tags) unless tags.nil?
|
175
175
|
else
|
176
|
-
if tags.nil?
|
177
|
-
|
176
|
+
tags = if tags.nil?
|
177
|
+
current_tags.dup
|
178
178
|
else
|
179
|
-
|
179
|
+
current_tags.merge(Tags.stringify_keys(tags))
|
180
180
|
end
|
181
181
|
end
|
182
182
|
tags = Tags.expand_runtime_values(tags)
|
@@ -203,7 +203,7 @@ module Lumberjack
|
|
203
203
|
add_entry(severity, message, progname)
|
204
204
|
end
|
205
205
|
|
206
|
-
|
206
|
+
alias log add
|
207
207
|
|
208
208
|
# Flush the logging device. Messages are not guaranteed to be written until this method is called.
|
209
209
|
def flush
|
@@ -238,6 +238,11 @@ module Lumberjack
|
|
238
238
|
level <= FATAL
|
239
239
|
end
|
240
240
|
|
241
|
+
# Set the log level to fatal.
|
242
|
+
def fatal!
|
243
|
+
self.level = FATAL
|
244
|
+
end
|
245
|
+
|
241
246
|
# Log an +ERROR+ message. The message can be passed in either the +message+ argument or in a block.
|
242
247
|
def error(message_or_progname_or_tags = nil, progname_or_tags = nil, &block)
|
243
248
|
call_add_entry(ERROR, message_or_progname_or_tags, progname_or_tags, &block)
|
@@ -248,6 +253,11 @@ module Lumberjack
|
|
248
253
|
level <= ERROR
|
249
254
|
end
|
250
255
|
|
256
|
+
# Set the log level to error.
|
257
|
+
def error!
|
258
|
+
self.level = ERROR
|
259
|
+
end
|
260
|
+
|
251
261
|
# Log a +WARN+ message. The message can be passed in either the +message+ argument or in a block.
|
252
262
|
def warn(message_or_progname_or_tags = nil, progname_or_tags = nil, &block)
|
253
263
|
call_add_entry(WARN, message_or_progname_or_tags, progname_or_tags, &block)
|
@@ -258,6 +268,11 @@ module Lumberjack
|
|
258
268
|
level <= WARN
|
259
269
|
end
|
260
270
|
|
271
|
+
# Set the log level to warn.
|
272
|
+
def warn!
|
273
|
+
self.level = WARN
|
274
|
+
end
|
275
|
+
|
261
276
|
# Log an +INFO+ message. The message can be passed in either the +message+ argument or in a block.
|
262
277
|
def info(message_or_progname_or_tags = nil, progname_or_tags = nil, &block)
|
263
278
|
call_add_entry(INFO, message_or_progname_or_tags, progname_or_tags, &block)
|
@@ -268,6 +283,11 @@ module Lumberjack
|
|
268
283
|
level <= INFO
|
269
284
|
end
|
270
285
|
|
286
|
+
# Set the log level to info.
|
287
|
+
def info!
|
288
|
+
self.level = INFO
|
289
|
+
end
|
290
|
+
|
271
291
|
# Log a +DEBUG+ message. The message can be passed in either the +message+ argument or in a block.
|
272
292
|
def debug(message_or_progname_or_tags = nil, progname_or_tags = nil, &block)
|
273
293
|
call_add_entry(DEBUG, message_or_progname_or_tags, progname_or_tags, &block)
|
@@ -278,6 +298,11 @@ module Lumberjack
|
|
278
298
|
level <= DEBUG
|
279
299
|
end
|
280
300
|
|
301
|
+
# Set the log level to debug.
|
302
|
+
def debug!
|
303
|
+
self.level = DEBUG
|
304
|
+
end
|
305
|
+
|
281
306
|
# Log a message when the severity is not known. Unknown messages will always appear in the log.
|
282
307
|
# The message can be passed in either the +message+ argument or in a block.
|
283
308
|
def unknown(message_or_progname_or_tags = nil, progname_or_tags = nil, &block)
|
@@ -300,7 +325,7 @@ module Lumberjack
|
|
300
325
|
def silence(temporary_level = ERROR, &block)
|
301
326
|
if silencer
|
302
327
|
unless temporary_level.is_a?(Integer)
|
303
|
-
temporary_level = Severity
|
328
|
+
temporary_level = Severity.label_to_level(temporary_level)
|
304
329
|
end
|
305
330
|
push_thread_local_value(:lumberjack_logger_level, temporary_level, &block)
|
306
331
|
else
|
@@ -324,30 +349,67 @@ module Lumberjack
|
|
324
349
|
end
|
325
350
|
|
326
351
|
# Set a hash of tags on logger. If a block is given, the tags will only be set
|
327
|
-
# for the duration of the block.
|
352
|
+
# for the duration of the block. If this method is called inside such a block,
|
353
|
+
# the tags will only be defined on the tags in that block. When the parent block
|
354
|
+
# exits, all the tags will be reverted. If there is no block, then the tags will
|
355
|
+
# be defined as global and apply to all log statements.
|
328
356
|
def tag(tags, &block)
|
329
357
|
tags = Tags.stringify_keys(tags)
|
358
|
+
thread_tags = thread_local_value(:lumberjack_logger_tags)
|
330
359
|
if block
|
331
|
-
|
332
|
-
|
333
|
-
|
360
|
+
merged_tags = (thread_tags ? thread_tags.merge(tags) : tags.dup)
|
361
|
+
push_thread_local_value(:lumberjack_logger_tags, merged_tags, &block)
|
362
|
+
elsif thread_tags
|
363
|
+
thread_tags.merge!(tags)
|
364
|
+
nil
|
334
365
|
else
|
335
366
|
@tags.merge!(tags)
|
367
|
+
nil
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
# Remove a tag from the current tag context. If this is called inside a block to a
|
372
|
+
# call to `tag`, the tags will only be removed for the duration of that block. Otherwise
|
373
|
+
# they will be removed from the global tags.
|
374
|
+
def remove_tag(*tag_names)
|
375
|
+
thread_tags = thread_local_value(:lumberjack_logger_tags)
|
376
|
+
if thread_tags
|
377
|
+
tag_names.each { |name| thread_tags.delete(name.to_s) }
|
378
|
+
else
|
379
|
+
tag_names.each { |name| @tags.delete(name.to_s) }
|
336
380
|
end
|
337
381
|
end
|
338
382
|
|
339
383
|
# Return all tags in scope on the logger including global tags set on the Lumberjack
|
340
|
-
# context, tags set on the logger, and tags set on the current block for the logger
|
384
|
+
# context, tags set on the logger, and tags set on the current block for the logger.
|
341
385
|
def tags
|
342
386
|
tags = {}
|
343
387
|
context_tags = Lumberjack.context_tags
|
344
388
|
tags.merge!(context_tags) if context_tags && !context_tags.empty?
|
345
|
-
tags.merge!(@tags) if !@tags.empty?
|
389
|
+
tags.merge!(@tags) if !@tags.empty? && !thread_local_value(:lumberjack_logger_untagged)
|
346
390
|
scope_tags = thread_local_value(:lumberjack_logger_tags)
|
347
391
|
tags.merge!(scope_tags) if scope_tags && !scope_tags.empty?
|
348
392
|
tags
|
349
393
|
end
|
350
394
|
|
395
|
+
# Remove all tags on the current logger and logging context within a block.
|
396
|
+
# You can still set new block scoped tags within theuntagged block and provide
|
397
|
+
# tags on individual log methods.
|
398
|
+
def untagged(&block)
|
399
|
+
Lumberjack.use_context(nil) do
|
400
|
+
scope_tags = thread_local_value(:lumberjack_logger_tags)
|
401
|
+
untagged = thread_local_value(:lumberjack_logger_untagged)
|
402
|
+
begin
|
403
|
+
set_thread_local_value(:lumberjack_logger_untagged, true)
|
404
|
+
set_thread_local_value(:lumberjack_logger_tags, nil)
|
405
|
+
tag({}, &block)
|
406
|
+
ensure
|
407
|
+
set_thread_local_value(:lumberjack_logger_untagged, untagged)
|
408
|
+
set_thread_local_value(:lumberjack_logger_tags, scope_tags)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
351
413
|
private
|
352
414
|
|
353
415
|
# Dereference arguments to log calls so we can have methods with compatibility with ::Logger
|
@@ -430,12 +492,12 @@ module Lumberjack
|
|
430
492
|
end
|
431
493
|
|
432
494
|
def write_to_device(entry) #:nodoc:
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
495
|
+
device.write(entry)
|
496
|
+
rescue => e
|
497
|
+
# rubocop:disable Style/StderrPuts
|
498
|
+
$stderr.puts("#{e.class.name}: #{e.message}#{" at " + e.backtrace.first if e.backtrace}")
|
499
|
+
$stderr.puts(entry.to_s)
|
500
|
+
# rubocop:enable Style/StderrPuts
|
439
501
|
end
|
440
502
|
|
441
503
|
# Create a thread that will periodically call flush.
|
@@ -444,12 +506,12 @@ module Lumberjack
|
|
444
506
|
begin
|
445
507
|
logger = self
|
446
508
|
Thread.new do
|
447
|
-
|
509
|
+
until closed?
|
448
510
|
begin
|
449
511
|
sleep(flush_seconds)
|
450
512
|
logger.flush if Time.now - logger.last_flushed_at >= flush_seconds
|
451
513
|
rescue => e
|
452
|
-
|
514
|
+
warn("Error flushing log: #{e.inspect}")
|
453
515
|
end
|
454
516
|
end
|
455
517
|
end
|