lumberjack 1.2.7 → 1.4.2
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/ARCHITECTURE.md +244 -0
- data/CHANGELOG.md +251 -56
- data/README.md +197 -62
- data/VERSION +1 -1
- data/lib/lumberjack/context.rb +25 -5
- data/lib/lumberjack/device/date_rolling_log_file.rb +17 -8
- data/lib/lumberjack/device/log_file.rb +14 -7
- data/lib/lumberjack/device/multi.rb +8 -7
- data/lib/lumberjack/device/null.rb +2 -2
- data/lib/lumberjack/device/rolling_log_file.rb +46 -22
- data/lib/lumberjack/device/size_rolling_log_file.rb +10 -10
- data/lib/lumberjack/device/writer.rb +45 -21
- data/lib/lumberjack/device.rb +28 -13
- data/lib/lumberjack/formatter/date_time_formatter.rb +5 -5
- data/lib/lumberjack/formatter/exception_formatter.rb +4 -4
- data/lib/lumberjack/formatter/id_formatter.rb +4 -3
- data/lib/lumberjack/formatter/inspect_formatter.rb +1 -1
- data/lib/lumberjack/formatter/multiply_formatter.rb +25 -0
- data/lib/lumberjack/formatter/object_formatter.rb +1 -1
- data/lib/lumberjack/formatter/pretty_print_formatter.rb +7 -5
- data/lib/lumberjack/formatter/redact_formatter.rb +23 -0
- data/lib/lumberjack/formatter/round_formatter.rb +21 -0
- data/lib/lumberjack/formatter/string_formatter.rb +1 -1
- data/lib/lumberjack/formatter/strip_formatter.rb +1 -1
- data/lib/lumberjack/formatter/structured_formatter.rb +3 -1
- data/lib/lumberjack/formatter/tagged_message.rb +39 -0
- data/lib/lumberjack/formatter/truncate_formatter.rb +27 -0
- data/lib/lumberjack/formatter.rb +96 -28
- data/lib/lumberjack/log_entry.rb +90 -19
- data/lib/lumberjack/logger.rb +318 -86
- data/lib/lumberjack/rack/context.rb +21 -2
- data/lib/lumberjack/rack/request_id.rb +8 -4
- data/lib/lumberjack/rack/unit_of_work.rb +7 -3
- data/lib/lumberjack/rack.rb +4 -4
- data/lib/lumberjack/severity.rb +22 -3
- data/lib/lumberjack/tag_context.rb +78 -0
- data/lib/lumberjack/tag_formatter.rb +124 -25
- data/lib/lumberjack/tagged_logger_support.rb +26 -12
- data/lib/lumberjack/tagged_logging.rb +1 -1
- data/lib/lumberjack/tags.rb +8 -8
- data/lib/lumberjack/template.rb +17 -5
- data/lib/lumberjack/utils.rb +182 -0
- data/lib/lumberjack.rb +64 -35
- data/lumberjack.gemspec +18 -15
- metadata +23 -54
data/lib/lumberjack/logger.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Lumberjack
|
|
4
4
|
# Logger is a thread safe logging object. It has a compatible API with the Ruby
|
|
@@ -21,7 +21,7 @@ module Lumberjack
|
|
|
21
21
|
# monitoring thread, but its use is highly recommended.
|
|
22
22
|
#
|
|
23
23
|
# Each log entry records the log message and severity along with the time it was logged, the
|
|
24
|
-
# program name, process id, and
|
|
24
|
+
# program name, process id, and an optional hash of tags. The message will be converted to a string, but
|
|
25
25
|
# otherwise, it is up to the device how these values are recorded. Messages are converted to strings
|
|
26
26
|
# using a Formatter associated with the logger.
|
|
27
27
|
class Logger
|
|
@@ -36,8 +36,8 @@ module Lumberjack
|
|
|
36
36
|
# Set the name of the program to attach to log entries.
|
|
37
37
|
attr_writer :progname
|
|
38
38
|
|
|
39
|
-
# The
|
|
40
|
-
attr_accessor :
|
|
39
|
+
# The Formatter used only for log entry messages.
|
|
40
|
+
attr_accessor :message_formatter
|
|
41
41
|
|
|
42
42
|
# The TagFormatter used for formatting tags for output
|
|
43
43
|
attr_accessor :tag_formatter
|
|
@@ -51,28 +51,30 @@ module Lumberjack
|
|
|
51
51
|
# If it is :null, it will be a Null device that won't record any output.
|
|
52
52
|
# Otherwise, it will be assumed to be file path and wrapped in a Device::LogFile class.
|
|
53
53
|
#
|
|
54
|
-
# This method can take the following options:
|
|
55
|
-
#
|
|
56
|
-
# * :level - The logging level below which messages will be ignored.
|
|
57
|
-
# * :formatter - The formatter to use for outputting messages to the log.
|
|
58
|
-
# * :datetime_format - The format to use for log timestamps.
|
|
59
|
-
# * :tag_formatter - The TagFormatter to use for formatting tags.
|
|
60
|
-
# * :progname - The name of the program that will be recorded with each log entry.
|
|
61
|
-
# * :flush_seconds - The maximum number of seconds between flush calls.
|
|
62
|
-
# * :roll - If the log device is a file path, it will be a Device::DateRollingLogFile if this is set.
|
|
63
|
-
# * :max_size - If the log device is a file path, it will be a Device::SizeRollingLogFile if this is set.
|
|
64
|
-
#
|
|
65
54
|
# All other options are passed to the device constuctor.
|
|
66
|
-
|
|
55
|
+
#
|
|
56
|
+
# @param [Lumberjack::Device, Object, Symbol, String] device The device to log to.
|
|
57
|
+
# @param [Hash] options The options for the logger.
|
|
58
|
+
# @option options [Integer, Symbol, String] :level The logging level below which messages will be ignored.
|
|
59
|
+
# @option options [Lumberjack::Formatter] :formatter The formatter to use for outputting messages to the log.
|
|
60
|
+
# @option options [String] :datetime_format The format to use for log timestamps.
|
|
61
|
+
# @option options [Lumberjack::Formatter] :message_formatter The MessageFormatter to use for formatting log messages.
|
|
62
|
+
# @option options [Lumberjack::TagFormatter] :tag_formatter The TagFormatter to use for formatting tags.
|
|
63
|
+
# @option options [String] :progname The name of the program that will be recorded with each log entry.
|
|
64
|
+
# @option options [Numeric] :flush_seconds The maximum number of seconds between flush calls.
|
|
65
|
+
# @option options [Boolean] :roll If the log device is a file path, it will be a Device::DateRollingLogFile if this is set.
|
|
66
|
+
# @option options [Integer] :max_size If the log device is a file path, it will be a Device::SizeRollingLogFile if this is set.
|
|
67
|
+
def initialize(device = $stdout, options = {})
|
|
67
68
|
options = options.dup
|
|
68
69
|
self.level = options.delete(:level) || INFO
|
|
69
70
|
self.progname = options.delete(:progname)
|
|
70
71
|
max_flush_seconds = options.delete(:flush_seconds).to_f
|
|
71
72
|
|
|
72
|
-
@
|
|
73
|
+
@logdev = open_device(device, options) if device
|
|
73
74
|
self.formatter = (options[:formatter] || Formatter.new)
|
|
74
|
-
@
|
|
75
|
-
|
|
75
|
+
@message_formatter = options[:message_formatter] || Formatter.empty
|
|
76
|
+
@tag_formatter = options[:tag_formatter] || TagFormatter.new
|
|
77
|
+
time_format = options[:datetime_format] || options[:time_format]
|
|
76
78
|
self.datetime_format = time_format if time_format
|
|
77
79
|
@last_flushed_at = Time.now
|
|
78
80
|
@silencer = true
|
|
@@ -82,12 +84,32 @@ module Lumberjack
|
|
|
82
84
|
create_flusher_thread(max_flush_seconds) if max_flush_seconds > 0
|
|
83
85
|
end
|
|
84
86
|
|
|
87
|
+
# Get the logging device that is used to write log entries.
|
|
88
|
+
#
|
|
89
|
+
# @return [Lumberjack::Device] The logging device.
|
|
90
|
+
def device
|
|
91
|
+
@logdev
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Set the logging device to a new device.
|
|
95
|
+
#
|
|
96
|
+
# @param [Lumberjack::Device] device The new logging device.
|
|
97
|
+
# @return [void]
|
|
98
|
+
def device=(device)
|
|
99
|
+
@logdev = device.nil? ? nil : open_device(device, {})
|
|
100
|
+
end
|
|
101
|
+
|
|
85
102
|
# Get the timestamp format on the device if it has one.
|
|
103
|
+
#
|
|
104
|
+
# @return [String, nil] The timestamp format or nil if the device doesn't support it.
|
|
86
105
|
def datetime_format
|
|
87
106
|
device.datetime_format if device.respond_to?(:datetime_format)
|
|
88
107
|
end
|
|
89
108
|
|
|
90
109
|
# Set the timestamp format on the device if it is supported.
|
|
110
|
+
#
|
|
111
|
+
# @param [String] format The timestamp format.
|
|
112
|
+
# @return [void]
|
|
91
113
|
def datetime_format=(format)
|
|
92
114
|
if device.respond_to?(:datetime_format=)
|
|
93
115
|
device.datetime_format = format
|
|
@@ -96,6 +118,8 @@ module Lumberjack
|
|
|
96
118
|
|
|
97
119
|
# Get the level of severity of entries that are logged. Entries with a lower
|
|
98
120
|
# severity level will be ignored.
|
|
121
|
+
#
|
|
122
|
+
# @return [Integer] The severity level.
|
|
99
123
|
def level
|
|
100
124
|
thread_local_value(:lumberjack_logger_level) || @level
|
|
101
125
|
end
|
|
@@ -104,22 +128,34 @@ module Lumberjack
|
|
|
104
128
|
|
|
105
129
|
# Set the log level using either an integer level like Logger::INFO or a label like
|
|
106
130
|
# :info or "info"
|
|
131
|
+
#
|
|
132
|
+
# @param [Integer, Symbol, String] value The severity level.
|
|
133
|
+
# @return [void]
|
|
107
134
|
def level=(value)
|
|
108
|
-
|
|
109
|
-
@level = value
|
|
110
|
-
else
|
|
111
|
-
@level = Severity::label_to_level(value)
|
|
112
|
-
end
|
|
135
|
+
@level = Severity.coerce(value)
|
|
113
136
|
end
|
|
114
137
|
|
|
115
138
|
alias_method :sev_threshold=, :level=
|
|
116
139
|
|
|
140
|
+
# Adjust the log level during the block execution for the current Fiber only.
|
|
141
|
+
#
|
|
142
|
+
# @param [Integer, Symbol, String] severity The severity level.
|
|
143
|
+
# @return [Object] The result of the block.
|
|
144
|
+
def with_level(severity, &block)
|
|
145
|
+
push_thread_local_value(:lumberjack_logger_level, Severity.coerce(severity), &block)
|
|
146
|
+
end
|
|
147
|
+
|
|
117
148
|
# Set the Lumberjack::Formatter used to format objects for logging as messages.
|
|
149
|
+
#
|
|
150
|
+
# @param [Lumberjack::Formatter, Object] value The formatter to use.
|
|
151
|
+
# @return [void]
|
|
118
152
|
def formatter=(value)
|
|
119
153
|
@_formatter = (value.is_a?(TaggedLoggerSupport::Formatter) ? value.__formatter : value)
|
|
120
154
|
end
|
|
121
155
|
|
|
122
156
|
# Get the Lumberjack::Formatter used to format objects for logging as messages.
|
|
157
|
+
#
|
|
158
|
+
# @return [Lumberjack::Formatter] The formatter.
|
|
123
159
|
def formatter
|
|
124
160
|
if respond_to?(:tagged)
|
|
125
161
|
# Wrap in an object that supports ActiveSupport::TaggedLogger API
|
|
@@ -136,8 +172,10 @@ module Lumberjack
|
|
|
136
172
|
# The tags added with this method are just strings so they are stored in the logger tags
|
|
137
173
|
# in an array under the "tagged" tag. So calling `logger.tagged("foo", "bar")` will result
|
|
138
174
|
# in tags `{"tagged" => ["foo", "bar"]}`.
|
|
175
|
+
#
|
|
176
|
+
# @return [Lumberjack::Logger] self.
|
|
139
177
|
def tagged_logger!
|
|
140
|
-
|
|
178
|
+
extend(TaggedLoggerSupport)
|
|
141
179
|
self
|
|
142
180
|
end
|
|
143
181
|
|
|
@@ -149,40 +187,52 @@ module Lumberjack
|
|
|
149
187
|
# The severity can be passed in either as one of the Severity constants,
|
|
150
188
|
# or as a Severity label.
|
|
151
189
|
#
|
|
152
|
-
#
|
|
190
|
+
# @param [Integer, Symbol, String] severity The severity of the message.
|
|
191
|
+
# @param [Object] message The message to log.
|
|
192
|
+
# @param [String] progname The name of the program that is logging the message.
|
|
193
|
+
# @param [Hash] tags The tags to add to the log entry.
|
|
194
|
+
# @return [void]
|
|
195
|
+
#
|
|
196
|
+
# @example
|
|
153
197
|
#
|
|
154
198
|
# logger.add_entry(Logger::ERROR, exception)
|
|
155
199
|
# logger.add_entry(Logger::INFO, "Request completed")
|
|
156
200
|
# logger.add_entry(:warn, "Request took a long time")
|
|
157
201
|
# logger.add_entry(Logger::DEBUG){"Start processing with options #{options.inspect}"}
|
|
158
202
|
def add_entry(severity, message, progname = nil, tags = nil)
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
203
|
+
severity = Severity.label_to_level(severity) unless severity.is_a?(Integer)
|
|
204
|
+
return true unless device && severity && severity >= level
|
|
205
|
+
return true if Thread.current[:lumberjack_logging]
|
|
162
206
|
|
|
163
|
-
|
|
164
|
-
Thread.current[:lumberjack_logging] = true
|
|
207
|
+
begin
|
|
208
|
+
Thread.current[:lumberjack_logging] = true # Prevent circular calls to add_entry
|
|
165
209
|
|
|
166
210
|
time = Time.now
|
|
211
|
+
|
|
167
212
|
message = message.call if message.is_a?(Proc)
|
|
168
|
-
|
|
213
|
+
msg_class_formatter = message_formatter&.formatter_for(message.class)
|
|
214
|
+
if msg_class_formatter
|
|
215
|
+
message = msg_class_formatter.call(message)
|
|
216
|
+
elsif formatter
|
|
217
|
+
message = formatter.format(message)
|
|
218
|
+
end
|
|
219
|
+
message_tags = nil
|
|
220
|
+
if message.is_a?(Formatter::TaggedMessage)
|
|
221
|
+
message_tags = message.tags
|
|
222
|
+
message = message.message
|
|
223
|
+
end
|
|
224
|
+
|
|
169
225
|
progname ||= self.progname
|
|
226
|
+
message_tags = Utils.flatten_tags(message_tags) if message_tags
|
|
170
227
|
|
|
171
228
|
current_tags = self.tags
|
|
172
229
|
tags = nil unless tags.is_a?(Hash)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
else
|
|
176
|
-
if tags.nil?
|
|
177
|
-
tags = current_tags.dup
|
|
178
|
-
else
|
|
179
|
-
tags = current_tags.merge(Tags.stringify_keys(tags))
|
|
180
|
-
end
|
|
181
|
-
end
|
|
230
|
+
tags = merge_tags(current_tags, tags)
|
|
231
|
+
tags = merge_tags(tags, message_tags) if message_tags
|
|
182
232
|
tags = Tags.expand_runtime_values(tags)
|
|
183
233
|
tags = tag_formatter.format(tags) if tag_formatter
|
|
184
234
|
|
|
185
|
-
entry = LogEntry.new(time, severity, message, progname,
|
|
235
|
+
entry = LogEntry.new(time, severity, message, progname, Process.pid, tags)
|
|
186
236
|
write_to_device(entry)
|
|
187
237
|
ensure
|
|
188
238
|
Thread.current[:lumberjack_logging] = nil
|
|
@@ -191,6 +241,11 @@ module Lumberjack
|
|
|
191
241
|
end
|
|
192
242
|
|
|
193
243
|
# ::Logger compatible method to add a log entry.
|
|
244
|
+
#
|
|
245
|
+
# @param [Integer, Symbol, String] severity The severity of the message.
|
|
246
|
+
# @param [Object] message The message to log.
|
|
247
|
+
# @param [String] progname The name of the program that is logging the message.
|
|
248
|
+
# @return [void]
|
|
194
249
|
def add(severity, message = nil, progname = nil, &block)
|
|
195
250
|
if message.nil?
|
|
196
251
|
if block
|
|
@@ -206,6 +261,8 @@ module Lumberjack
|
|
|
206
261
|
alias_method :log, :add
|
|
207
262
|
|
|
208
263
|
# Flush the logging device. Messages are not guaranteed to be written until this method is called.
|
|
264
|
+
#
|
|
265
|
+
# @return [void]
|
|
209
266
|
def flush
|
|
210
267
|
device.flush
|
|
211
268
|
@last_flushed_at = Time.now
|
|
@@ -213,102 +270,170 @@ module Lumberjack
|
|
|
213
270
|
end
|
|
214
271
|
|
|
215
272
|
# Close the logging device.
|
|
273
|
+
#
|
|
274
|
+
# @return [void]
|
|
216
275
|
def close
|
|
217
276
|
flush
|
|
218
277
|
device.close if device.respond_to?(:close)
|
|
219
278
|
@closed = true
|
|
220
279
|
end
|
|
221
280
|
|
|
281
|
+
# Returns +true+ if the logging device is closed.
|
|
282
|
+
#
|
|
283
|
+
# @return [Boolean] +true+ if the logging device is closed.
|
|
222
284
|
def closed?
|
|
223
285
|
@closed
|
|
224
286
|
end
|
|
225
287
|
|
|
288
|
+
# Reopen the logging device.
|
|
289
|
+
#
|
|
290
|
+
# @param [Object] logdev passed through to the logging device.
|
|
226
291
|
def reopen(logdev = nil)
|
|
227
292
|
@closed = false
|
|
228
293
|
device.reopen(logdev) if device.respond_to?(:reopen)
|
|
229
294
|
end
|
|
230
295
|
|
|
231
296
|
# Log a +FATAL+ message. The message can be passed in either the +message+ argument or in a block.
|
|
297
|
+
#
|
|
298
|
+
# @param [Object] message_or_progname_or_tags The message to log or progname
|
|
299
|
+
# if the message is passed in a block.
|
|
300
|
+
# @param [String, Hash] progname_or_tags The name of the program that is logging the message or tags
|
|
301
|
+
# if the message is passed in a block.
|
|
302
|
+
# @return [void]
|
|
232
303
|
def fatal(message_or_progname_or_tags = nil, progname_or_tags = nil, &block)
|
|
233
304
|
call_add_entry(FATAL, message_or_progname_or_tags, progname_or_tags, &block)
|
|
234
305
|
end
|
|
235
306
|
|
|
236
307
|
# Return +true+ if +FATAL+ messages are being logged.
|
|
308
|
+
#
|
|
309
|
+
# @return [Boolean]
|
|
237
310
|
def fatal?
|
|
238
311
|
level <= FATAL
|
|
239
312
|
end
|
|
240
313
|
|
|
241
314
|
# Set the log level to fatal.
|
|
315
|
+
#
|
|
316
|
+
# @return [void]
|
|
242
317
|
def fatal!
|
|
243
318
|
self.level = FATAL
|
|
244
319
|
end
|
|
245
320
|
|
|
246
321
|
# Log an +ERROR+ message. The message can be passed in either the +message+ argument or in a block.
|
|
322
|
+
#
|
|
323
|
+
# @param [Object] message_or_progname_or_tags The message to log or progname
|
|
324
|
+
# if the message is passed in a block.
|
|
325
|
+
# @param [String, Hash] progname_or_tags The name of the program that is logging the message or tags
|
|
326
|
+
# if the message is passed in a block.
|
|
327
|
+
# @return [void]
|
|
247
328
|
def error(message_or_progname_or_tags = nil, progname_or_tags = nil, &block)
|
|
248
329
|
call_add_entry(ERROR, message_or_progname_or_tags, progname_or_tags, &block)
|
|
249
330
|
end
|
|
250
331
|
|
|
251
332
|
# Return +true+ if +ERROR+ messages are being logged.
|
|
333
|
+
#
|
|
334
|
+
# @return [Boolean]
|
|
252
335
|
def error?
|
|
253
336
|
level <= ERROR
|
|
254
337
|
end
|
|
255
338
|
|
|
256
339
|
# Set the log level to error.
|
|
340
|
+
#
|
|
341
|
+
# @return [void]
|
|
257
342
|
def error!
|
|
258
343
|
self.level = ERROR
|
|
259
344
|
end
|
|
260
345
|
|
|
261
346
|
# Log a +WARN+ message. The message can be passed in either the +message+ argument or in a block.
|
|
347
|
+
#
|
|
348
|
+
# @param [Object] message_or_progname_or_tags The message to log or progname
|
|
349
|
+
# if the message is passed in a block.
|
|
350
|
+
# @param [String, Hash] progname_or_tags The name of the program that is logging the message or tags
|
|
351
|
+
# if the message is passed in a block.
|
|
352
|
+
# @return [void]
|
|
262
353
|
def warn(message_or_progname_or_tags = nil, progname_or_tags = nil, &block)
|
|
263
354
|
call_add_entry(WARN, message_or_progname_or_tags, progname_or_tags, &block)
|
|
264
355
|
end
|
|
265
356
|
|
|
266
357
|
# Return +true+ if +WARN+ messages are being logged.
|
|
358
|
+
#
|
|
359
|
+
# @return [Boolean]
|
|
267
360
|
def warn?
|
|
268
361
|
level <= WARN
|
|
269
362
|
end
|
|
270
363
|
|
|
271
364
|
# Set the log level to warn.
|
|
365
|
+
#
|
|
366
|
+
# @return [void]
|
|
272
367
|
def warn!
|
|
273
368
|
self.level = WARN
|
|
274
369
|
end
|
|
275
370
|
|
|
276
371
|
# Log an +INFO+ message. The message can be passed in either the +message+ argument or in a block.
|
|
372
|
+
#
|
|
373
|
+
# @param [Object] message_or_progname_or_tags The message to log or progname
|
|
374
|
+
# if the message is passed in a block.
|
|
375
|
+
# @param [String] progname_or_tags The name of the program that is logging the message or tags
|
|
376
|
+
# if the message is passed in a block.
|
|
377
|
+
# @return [void]
|
|
277
378
|
def info(message_or_progname_or_tags = nil, progname_or_tags = nil, &block)
|
|
278
379
|
call_add_entry(INFO, message_or_progname_or_tags, progname_or_tags, &block)
|
|
279
380
|
end
|
|
280
381
|
|
|
281
382
|
# Return +true+ if +INFO+ messages are being logged.
|
|
383
|
+
#
|
|
384
|
+
# @return [Boolean]
|
|
282
385
|
def info?
|
|
283
386
|
level <= INFO
|
|
284
387
|
end
|
|
285
388
|
|
|
286
389
|
# Set the log level to info.
|
|
390
|
+
#
|
|
391
|
+
# @return [void]
|
|
287
392
|
def info!
|
|
288
393
|
self.level = INFO
|
|
289
394
|
end
|
|
290
395
|
|
|
291
396
|
# Log a +DEBUG+ message. The message can be passed in either the +message+ argument or in a block.
|
|
397
|
+
#
|
|
398
|
+
# @param [Object] message_or_progname_or_tags The message to log or progname
|
|
399
|
+
# if the message is passed in a block.
|
|
400
|
+
# @param [String, Hash] progname_or_tags The name of the program that is logging the message or tags
|
|
401
|
+
# if the message is passed in a block.
|
|
402
|
+
# @return [void]
|
|
292
403
|
def debug(message_or_progname_or_tags = nil, progname_or_tags = nil, &block)
|
|
293
404
|
call_add_entry(DEBUG, message_or_progname_or_tags, progname_or_tags, &block)
|
|
294
405
|
end
|
|
295
406
|
|
|
296
407
|
# Return +true+ if +DEBUG+ messages are being logged.
|
|
408
|
+
#
|
|
409
|
+
# @return [Boolean]
|
|
297
410
|
def debug?
|
|
298
411
|
level <= DEBUG
|
|
299
412
|
end
|
|
300
413
|
|
|
301
414
|
# Set the log level to debug.
|
|
415
|
+
#
|
|
416
|
+
# @return [void]
|
|
302
417
|
def debug!
|
|
303
418
|
self.level = DEBUG
|
|
304
419
|
end
|
|
305
420
|
|
|
306
421
|
# Log a message when the severity is not known. Unknown messages will always appear in the log.
|
|
307
422
|
# The message can be passed in either the +message+ argument or in a block.
|
|
423
|
+
#
|
|
424
|
+
# @param [Object] message_or_progname_or_tags The message to log or progname
|
|
425
|
+
# if the message is passed in a block.
|
|
426
|
+
# @param [String, Hash] progname_or_tags The name of the program that is logging the message or tags
|
|
427
|
+
# if the message is passed in a block.
|
|
428
|
+
# @return [void]
|
|
308
429
|
def unknown(message_or_progname_or_tags = nil, progname_or_tags = nil, &block)
|
|
309
430
|
call_add_entry(UNKNOWN, message_or_progname_or_tags, progname_or_tags, &block)
|
|
310
431
|
end
|
|
311
432
|
|
|
433
|
+
# Add a message when the severity is not known.
|
|
434
|
+
#
|
|
435
|
+
# @param [Object] msg The message to log.
|
|
436
|
+
# @return [void]
|
|
312
437
|
def <<(msg)
|
|
313
438
|
add_entry(UNKNOWN, msg)
|
|
314
439
|
end
|
|
@@ -316,7 +441,10 @@ module Lumberjack
|
|
|
316
441
|
# Silence the logger by setting a new log level inside a block. By default, only +ERROR+ or +FATAL+
|
|
317
442
|
# messages will be logged.
|
|
318
443
|
#
|
|
319
|
-
#
|
|
444
|
+
# @param [Integer, String, Symbol] temporary_level The log level to use inside the block.
|
|
445
|
+
# @return [Object] The result of the block.
|
|
446
|
+
#
|
|
447
|
+
# @example
|
|
320
448
|
#
|
|
321
449
|
# logger.level = Logger::INFO
|
|
322
450
|
# logger.silence do
|
|
@@ -325,7 +453,7 @@ module Lumberjack
|
|
|
325
453
|
def silence(temporary_level = ERROR, &block)
|
|
326
454
|
if silencer
|
|
327
455
|
unless temporary_level.is_a?(Integer)
|
|
328
|
-
temporary_level = Severity
|
|
456
|
+
temporary_level = Severity.label_to_level(temporary_level)
|
|
329
457
|
end
|
|
330
458
|
push_thread_local_value(:lumberjack_logger_level, temporary_level, &block)
|
|
331
459
|
else
|
|
@@ -333,8 +461,19 @@ module Lumberjack
|
|
|
333
461
|
end
|
|
334
462
|
end
|
|
335
463
|
|
|
464
|
+
# Provided for compatibility with ActiveSupport::LoggerThreadSafeLevel to temporarily set the log level.
|
|
465
|
+
#
|
|
466
|
+
# @param [Integer, String, Symbol] level The log level to use inside the block.
|
|
467
|
+
# @return [Object] The result of the block.
|
|
468
|
+
def log_at(level, &block)
|
|
469
|
+
with_level(level, &block)
|
|
470
|
+
end
|
|
471
|
+
|
|
336
472
|
# Set the program name that is associated with log messages. If a block
|
|
337
473
|
# is given, the program name will be valid only within the block.
|
|
474
|
+
#
|
|
475
|
+
# @param [String] value The program name to use.
|
|
476
|
+
# @return [void]
|
|
338
477
|
def set_progname(value, &block)
|
|
339
478
|
if block
|
|
340
479
|
push_thread_local_value(:lumberjack_logger_progname, value, &block)
|
|
@@ -343,58 +482,142 @@ module Lumberjack
|
|
|
343
482
|
end
|
|
344
483
|
end
|
|
345
484
|
|
|
485
|
+
# Set the logger progname for the duration of the block.
|
|
486
|
+
#
|
|
487
|
+
# @yield [Object] The block to execute with the program name set.
|
|
488
|
+
# @param [String] value The program name to use.
|
|
489
|
+
# @return [Object] The result of the block.
|
|
490
|
+
def with_progname(value, &block)
|
|
491
|
+
set_progname(value, &block)
|
|
492
|
+
end
|
|
493
|
+
|
|
346
494
|
# Get the program name associated with log messages.
|
|
495
|
+
#
|
|
496
|
+
# @return [String]
|
|
347
497
|
def progname
|
|
348
498
|
thread_local_value(:lumberjack_logger_progname) || @progname
|
|
349
499
|
end
|
|
350
500
|
|
|
351
501
|
# Set a hash of tags on logger. If a block is given, the tags will only be set
|
|
352
|
-
# for the duration of the block.
|
|
353
|
-
#
|
|
354
|
-
#
|
|
355
|
-
#
|
|
502
|
+
# for the duration of the block. Otherwise the tags will be applied on the current
|
|
503
|
+
# logger context for the duration of that context.
|
|
504
|
+
#
|
|
505
|
+
# If there is no block or context, the tags will be applied to the global context.
|
|
506
|
+
# This behavior is deprecated. Use the `tag_globally` method to set global tags instead.
|
|
507
|
+
#
|
|
508
|
+
# @param [Hash] tags The tags to set.
|
|
509
|
+
# @return [void]
|
|
356
510
|
def tag(tags, &block)
|
|
357
|
-
tags = Tags.stringify_keys(tags)
|
|
358
511
|
thread_tags = thread_local_value(:lumberjack_logger_tags)
|
|
359
512
|
if block
|
|
360
|
-
merged_tags = (thread_tags ? thread_tags.
|
|
513
|
+
merged_tags = (thread_tags ? thread_tags.dup : {})
|
|
514
|
+
TagContext.new(merged_tags).tag(tags)
|
|
361
515
|
push_thread_local_value(:lumberjack_logger_tags, merged_tags, &block)
|
|
362
516
|
elsif thread_tags
|
|
363
|
-
thread_tags.
|
|
517
|
+
TagContext.new(thread_tags).tag(tags)
|
|
518
|
+
nil
|
|
364
519
|
else
|
|
365
|
-
|
|
520
|
+
Utils.deprecated("Lumberjack::Logger#tag", "Lumberjack::Logger#tag must be called with a block or inside a context block. In version 2.0 it will no longer be used for setting global tags. Use Lumberjack::Logger#tag_globally instead.") do
|
|
521
|
+
tag_globally(tags)
|
|
522
|
+
end
|
|
366
523
|
end
|
|
367
|
-
nil
|
|
368
524
|
end
|
|
369
525
|
|
|
370
|
-
#
|
|
371
|
-
#
|
|
372
|
-
#
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
526
|
+
# Set up a context block for the logger. All tags added within the block will be cleared when
|
|
527
|
+
# the block exits.
|
|
528
|
+
#
|
|
529
|
+
# @param [Proc] block The block to execute with the tag context.
|
|
530
|
+
# @return [TagContext] If no block is passed, then a Lumberjack::TagContext is returned that can be used
|
|
531
|
+
# to interact with the tags (add, remove, etc.).
|
|
532
|
+
# @yield [TagContext] If a block is passed, it will be yielded a TagContext object that can be used to
|
|
533
|
+
# add or remove tags within the context.
|
|
534
|
+
def context(&block)
|
|
535
|
+
if block
|
|
536
|
+
thread_tags = thread_local_value(:lumberjack_logger_tags)&.dup
|
|
537
|
+
thread_tags ||= {}
|
|
538
|
+
push_thread_local_value(:lumberjack_logger_tags, thread_tags) do
|
|
539
|
+
block.call(TagContext.new(thread_tags))
|
|
540
|
+
end
|
|
377
541
|
else
|
|
378
|
-
|
|
542
|
+
TagContext.new(thread_local_value(:lumberjack_logger_tags) || {})
|
|
379
543
|
end
|
|
380
544
|
end
|
|
381
545
|
|
|
546
|
+
# Add global tags to the logger that will appear on all log entries.
|
|
547
|
+
#
|
|
548
|
+
# @param [Hash] tags The tags to set.
|
|
549
|
+
# @return [void]
|
|
550
|
+
def tag_globally(tags)
|
|
551
|
+
TagContext.new(@tags).tag(tags)
|
|
552
|
+
nil
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
# Remove a tag from the current tag context. If this is called inside a tag context,
|
|
556
|
+
# the tags will only be removed for the duration of that block. Otherwise they will be removed
|
|
557
|
+
# from the global tags.
|
|
558
|
+
#
|
|
559
|
+
# @param [Array<String, Symbol>] tag_names The tags to remove.
|
|
560
|
+
# @return [void]
|
|
561
|
+
def remove_tag(*tag_names)
|
|
562
|
+
tags = thread_local_value(:lumberjack_logger_tags) || @tags
|
|
563
|
+
TagContext.new(tags).delete(*tag_names)
|
|
564
|
+
end
|
|
565
|
+
|
|
382
566
|
# Return all tags in scope on the logger including global tags set on the Lumberjack
|
|
383
|
-
# context, tags set on the logger, and tags set on the current block for the logger
|
|
567
|
+
# context, tags set on the logger, and tags set on the current block for the logger.
|
|
568
|
+
#
|
|
569
|
+
# @return [Hash]
|
|
384
570
|
def tags
|
|
385
571
|
tags = {}
|
|
386
572
|
context_tags = Lumberjack.context_tags
|
|
387
573
|
tags.merge!(context_tags) if context_tags && !context_tags.empty?
|
|
388
|
-
tags.merge!(@tags) if !@tags.empty?
|
|
574
|
+
tags.merge!(@tags) if !@tags.empty? && !thread_local_value(:lumberjack_logger_untagged)
|
|
389
575
|
scope_tags = thread_local_value(:lumberjack_logger_tags)
|
|
390
576
|
tags.merge!(scope_tags) if scope_tags && !scope_tags.empty?
|
|
391
577
|
tags
|
|
392
578
|
end
|
|
393
579
|
|
|
580
|
+
# Get the value of a tag by name from the current tag context.
|
|
581
|
+
#
|
|
582
|
+
# @param [String, Symbol] name The name of the tag to get.
|
|
583
|
+
# @return [Object, nil] The value of the tag or nil if the tag does not exist.
|
|
584
|
+
def tag_value(name)
|
|
585
|
+
name = name.join(".") if name.is_a?(Array)
|
|
586
|
+
TagContext.new(tags)[name]
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
# Remove all tags on the current logger and logging context within a block.
|
|
590
|
+
# You can still set new block scoped tags within theuntagged block and provide
|
|
591
|
+
# tags on individual log methods.
|
|
592
|
+
#
|
|
593
|
+
# @return [void]
|
|
594
|
+
def untagged(&block)
|
|
595
|
+
Lumberjack.use_context(nil) do
|
|
596
|
+
scope_tags = thread_local_value(:lumberjack_logger_tags)
|
|
597
|
+
untagged = thread_local_value(:lumberjack_logger_untagged)
|
|
598
|
+
begin
|
|
599
|
+
set_thread_local_value(:lumberjack_logger_untagged, true)
|
|
600
|
+
set_thread_local_value(:lumberjack_logger_tags, nil)
|
|
601
|
+
tag({}, &block)
|
|
602
|
+
ensure
|
|
603
|
+
set_thread_local_value(:lumberjack_logger_untagged, untagged)
|
|
604
|
+
set_thread_local_value(:lumberjack_logger_tags, scope_tags)
|
|
605
|
+
end
|
|
606
|
+
end
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
# Return true if the thread is currently in a Lumberjack::Context block.
|
|
610
|
+
# When the logger is in a context block, tagging will only apply to that block.
|
|
611
|
+
#
|
|
612
|
+
# @return [Boolean]
|
|
613
|
+
def in_tag_context?
|
|
614
|
+
!!thread_local_value(:lumberjack_logger_tags)
|
|
615
|
+
end
|
|
616
|
+
|
|
394
617
|
private
|
|
395
618
|
|
|
396
619
|
# Dereference arguments to log calls so we can have methods with compatibility with ::Logger
|
|
397
|
-
def call_add_entry(severity, message_or_progname_or_tags, progname_or_tags, &block)
|
|
620
|
+
def call_add_entry(severity, message_or_progname_or_tags, progname_or_tags, &block) # :nodoc:
|
|
398
621
|
message = nil
|
|
399
622
|
progname = nil
|
|
400
623
|
tags = nil
|
|
@@ -418,8 +641,19 @@ module Lumberjack
|
|
|
418
641
|
add_entry(severity, message, progname, tags)
|
|
419
642
|
end
|
|
420
643
|
|
|
644
|
+
# Merge a tags hash into an existing tags hash.
|
|
645
|
+
def merge_tags(current_tags, tags)
|
|
646
|
+
if current_tags.nil? || current_tags.empty?
|
|
647
|
+
tags
|
|
648
|
+
elsif tags.nil?
|
|
649
|
+
current_tags
|
|
650
|
+
else
|
|
651
|
+
current_tags.merge(tags)
|
|
652
|
+
end
|
|
653
|
+
end
|
|
654
|
+
|
|
421
655
|
# Set a local value for a thread tied to this object.
|
|
422
|
-
def set_thread_local_value(name, value)
|
|
656
|
+
def set_thread_local_value(name, value) # :nodoc:
|
|
423
657
|
values = Thread.current[name]
|
|
424
658
|
unless values
|
|
425
659
|
values = {}
|
|
@@ -434,13 +668,13 @@ module Lumberjack
|
|
|
434
668
|
end
|
|
435
669
|
|
|
436
670
|
# Get a local value for a thread tied to this object.
|
|
437
|
-
def thread_local_value(name)
|
|
671
|
+
def thread_local_value(name) # :nodoc:
|
|
438
672
|
values = Thread.current[name]
|
|
439
673
|
values[self] if values
|
|
440
674
|
end
|
|
441
675
|
|
|
442
676
|
# Set a local value for a thread tied to this object within a block.
|
|
443
|
-
def push_thread_local_value(name, value)
|
|
677
|
+
def push_thread_local_value(name, value) # :nodoc:
|
|
444
678
|
save_val = thread_local_value(name)
|
|
445
679
|
set_thread_local_value(name, value)
|
|
446
680
|
begin
|
|
@@ -451,7 +685,7 @@ module Lumberjack
|
|
|
451
685
|
end
|
|
452
686
|
|
|
453
687
|
# Open a logging device.
|
|
454
|
-
def open_device(device, options)
|
|
688
|
+
def open_device(device, options) # :nodoc:
|
|
455
689
|
if device.nil?
|
|
456
690
|
nil
|
|
457
691
|
elsif device.is_a?(Device)
|
|
@@ -472,28 +706,26 @@ module Lumberjack
|
|
|
472
706
|
end
|
|
473
707
|
end
|
|
474
708
|
|
|
475
|
-
def write_to_device(entry)
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
709
|
+
def write_to_device(entry) # :nodoc:
|
|
710
|
+
device.write(entry)
|
|
711
|
+
rescue => e
|
|
712
|
+
# rubocop:disable Style/StderrPuts
|
|
713
|
+
$stderr.puts("#{e.class.name}: #{e.message}#{" at " + e.backtrace.first if e.backtrace}")
|
|
714
|
+
$stderr.puts(entry.to_s)
|
|
715
|
+
# rubocop:enable Style/StderrPuts
|
|
482
716
|
end
|
|
483
717
|
|
|
484
718
|
# Create a thread that will periodically call flush.
|
|
485
|
-
def create_flusher_thread(flush_seconds)
|
|
719
|
+
def create_flusher_thread(flush_seconds) # :nodoc:
|
|
486
720
|
if flush_seconds > 0
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
$stderr.puts("Error flushing log: #{e.inspect}")
|
|
496
|
-
end
|
|
721
|
+
logger = self
|
|
722
|
+
Thread.new do
|
|
723
|
+
until closed?
|
|
724
|
+
begin
|
|
725
|
+
sleep(flush_seconds)
|
|
726
|
+
logger.flush if Time.now - logger.last_flushed_at >= flush_seconds
|
|
727
|
+
rescue => e
|
|
728
|
+
warn("Error flushing log: #{e.inspect}")
|
|
497
729
|
end
|
|
498
730
|
end
|
|
499
731
|
end
|