lumberjack 1.2.10 → 1.3.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 +52 -0
- data/README.md +146 -57
- data/VERSION +1 -1
- data/lib/lumberjack/context.rb +5 -5
- data/lib/lumberjack/device/rolling_log_file.rb +1 -1
- data/lib/lumberjack/device/writer.rb +12 -8
- data/lib/lumberjack/formatter/date_time_formatter.rb +1 -1
- data/lib/lumberjack/formatter/multiply_formatter.rb +25 -0
- data/lib/lumberjack/formatter/redact_formatter.rb +23 -0
- data/lib/lumberjack/formatter/round_formatter.rb +21 -0
- data/lib/lumberjack/formatter/tagged_message.rb +39 -0
- data/lib/lumberjack/formatter.rb +28 -13
- data/lib/lumberjack/log_entry.rb +58 -16
- data/lib/lumberjack/logger.rb +129 -34
- data/lib/lumberjack/rack/context.rb +20 -1
- data/lib/lumberjack/rack/request_id.rb +6 -2
- data/lib/lumberjack/rack/unit_of_work.rb +5 -1
- data/lib/lumberjack/tag_formatter.rb +102 -27
- data/lib/lumberjack/tagged_logger_support.rb +25 -10
- data/lib/lumberjack/tags.rb +1 -7
- data/lib/lumberjack/template.rb +1 -1
- data/lib/lumberjack/utils.rb +133 -0
- data/lib/lumberjack.rb +10 -5
- data/lumberjack.gemspec +8 -2
- metadata +16 -7
data/lib/lumberjack/logger.rb
CHANGED
@@ -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,31 +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
|
#
|
67
56
|
# @param [Lumberjack::Device, Object, Symbol, String] device The device to log to.
|
68
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.
|
69
67
|
def initialize(device = $stdout, options = {})
|
70
68
|
options = options.dup
|
71
69
|
self.level = options.delete(:level) || INFO
|
72
70
|
self.progname = options.delete(:progname)
|
73
71
|
max_flush_seconds = options.delete(:flush_seconds).to_f
|
74
72
|
|
75
|
-
@
|
73
|
+
@logdev = open_device(device, options) if device
|
76
74
|
self.formatter = (options[:formatter] || Formatter.new)
|
77
|
-
@
|
78
|
-
|
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]
|
79
78
|
self.datetime_format = time_format if time_format
|
80
79
|
@last_flushed_at = Time.now
|
81
80
|
@silencer = true
|
@@ -85,6 +84,21 @@ module Lumberjack
|
|
85
84
|
create_flusher_thread(max_flush_seconds) if max_flush_seconds > 0
|
86
85
|
end
|
87
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
|
+
|
88
102
|
# Get the timestamp format on the device if it has one.
|
89
103
|
#
|
90
104
|
# @return [String, nil] The timestamp format or nil if the device doesn't support it.
|
@@ -194,25 +208,30 @@ module Lumberjack
|
|
194
208
|
Thread.current[:lumberjack_logging] = true
|
195
209
|
|
196
210
|
time = Time.now
|
211
|
+
|
197
212
|
message = message.call if message.is_a?(Proc)
|
198
|
-
|
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
|
+
|
199
225
|
progname ||= self.progname
|
200
226
|
|
201
227
|
current_tags = self.tags
|
202
228
|
tags = nil unless tags.is_a?(Hash)
|
203
|
-
|
204
|
-
|
205
|
-
else
|
206
|
-
tags = if tags.nil?
|
207
|
-
current_tags.dup
|
208
|
-
else
|
209
|
-
current_tags.merge(Tags.stringify_keys(tags))
|
210
|
-
end
|
211
|
-
end
|
229
|
+
tags = merge_tags(current_tags, tags)
|
230
|
+
tags = merge_tags(tags, message_tags) if message_tags
|
212
231
|
tags = Tags.expand_runtime_values(tags)
|
213
232
|
tags = tag_formatter.format(tags) if tag_formatter
|
214
233
|
|
215
|
-
entry = LogEntry.new(time, severity, message, progname,
|
234
|
+
entry = LogEntry.new(time, severity, message, progname, Process.pid, tags)
|
216
235
|
write_to_device(entry)
|
217
236
|
ensure
|
218
237
|
Thread.current[:lumberjack_logging] = nil
|
@@ -441,6 +460,14 @@ module Lumberjack
|
|
441
460
|
end
|
442
461
|
end
|
443
462
|
|
463
|
+
# Provided for compatibility with ActiveSupport::LoggerThreadSafeLevel to temporarily set the log level.
|
464
|
+
#
|
465
|
+
# @param [Integer, String, Symbol] level The log level to use inside the block.
|
466
|
+
# @return [Object] The result of the block.
|
467
|
+
def log_at(level, &block)
|
468
|
+
silence(level, &block)
|
469
|
+
end
|
470
|
+
|
444
471
|
# Set the program name that is associated with log messages. If a block
|
445
472
|
# is given, the program name will be valid only within the block.
|
446
473
|
#
|
@@ -462,10 +489,11 @@ module Lumberjack
|
|
462
489
|
end
|
463
490
|
|
464
491
|
# Set a hash of tags on logger. If a block is given, the tags will only be set
|
465
|
-
# for the duration of the block.
|
466
|
-
#
|
467
|
-
#
|
468
|
-
#
|
492
|
+
# for the duration of the block. Otherwise the tags will be applied on the current
|
493
|
+
# logger context for the duration of that context.
|
494
|
+
#
|
495
|
+
# If there is no block or context, the tags will be applied to the global context.
|
496
|
+
# This behavior is deprecated. Use the `tag_globally` method to set global tags instead.
|
469
497
|
#
|
470
498
|
# @param [Hash] tags The tags to set.
|
471
499
|
# @return [void]
|
@@ -479,11 +507,31 @@ module Lumberjack
|
|
479
507
|
thread_tags.merge!(tags)
|
480
508
|
nil
|
481
509
|
else
|
482
|
-
|
483
|
-
|
510
|
+
Lumberjack::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
|
511
|
+
tag_globally(tags)
|
512
|
+
end
|
484
513
|
end
|
485
514
|
end
|
486
515
|
|
516
|
+
# Set up a context block for the logger. All tags added within the block will be cleared when
|
517
|
+
# the block exits.
|
518
|
+
#
|
519
|
+
def context(&block)
|
520
|
+
thread_tags = thread_local_value(:lumberjack_logger_tags)&.dup
|
521
|
+
thread_tags ||= {}
|
522
|
+
push_thread_local_value(:lumberjack_logger_tags, thread_tags, &block)
|
523
|
+
end
|
524
|
+
|
525
|
+
# Add global tags to the logger that will appear on all log entries.
|
526
|
+
#
|
527
|
+
# @param [Hash] tags The tags to set.
|
528
|
+
# @return [void]
|
529
|
+
def tag_globally(tags)
|
530
|
+
tags = Tags.stringify_keys(tags)
|
531
|
+
@tags.merge!(tags)
|
532
|
+
nil
|
533
|
+
end
|
534
|
+
|
487
535
|
# Remove a tag from the current tag context. If this is called inside a block to a
|
488
536
|
# call to `tag`, the tags will only be removed for the duration of that block. Otherwise
|
489
537
|
# they will be removed from the global tags.
|
@@ -513,6 +561,31 @@ module Lumberjack
|
|
513
561
|
tags
|
514
562
|
end
|
515
563
|
|
564
|
+
# Get the value of a tag by name from the current tag context.
|
565
|
+
#
|
566
|
+
# @param [String, Symbol] name The name of the tag to get.
|
567
|
+
# @return [Object, nil] The value of the tag or nil if the tag does not exist.
|
568
|
+
def tag_value(name)
|
569
|
+
all_tags = tags
|
570
|
+
return nil if tags.empty?
|
571
|
+
|
572
|
+
name = name.join(".") if name.is_a?(Array)
|
573
|
+
name = name.to_s
|
574
|
+
return all_tags[name] if all_tags.include?(name)
|
575
|
+
|
576
|
+
flattened_tags = Lumberjack::Utils.flatten_tags(all_tags)
|
577
|
+
return flattened_tags[name] if flattened_tags.include?(name)
|
578
|
+
|
579
|
+
flattened_tags.keys.select { |key| key.include?(".") }.each do |key|
|
580
|
+
parts = key.split(".")
|
581
|
+
while (subkey = parts.pop)
|
582
|
+
flattened_tags[parts.join(".")] = {subkey => flattened_tags[(parts + [subkey]).join(".")]}
|
583
|
+
end
|
584
|
+
end
|
585
|
+
|
586
|
+
flattened_tags[name]
|
587
|
+
end
|
588
|
+
|
516
589
|
# Remove all tags on the current logger and logging context within a block.
|
517
590
|
# You can still set new block scoped tags within theuntagged block and provide
|
518
591
|
# tags on individual log methods.
|
@@ -533,6 +606,14 @@ module Lumberjack
|
|
533
606
|
end
|
534
607
|
end
|
535
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
|
+
|
536
617
|
private
|
537
618
|
|
538
619
|
# Dereference arguments to log calls so we can have methods with compatibility with ::Logger
|
@@ -560,6 +641,20 @@ module Lumberjack
|
|
560
641
|
add_entry(severity, message, progname, tags)
|
561
642
|
end
|
562
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 = Tags.stringify_keys(tags) unless tags.nil?
|
648
|
+
else
|
649
|
+
tags = if tags.nil?
|
650
|
+
current_tags.dup
|
651
|
+
else
|
652
|
+
current_tags.merge(Tags.stringify_keys(tags))
|
653
|
+
end
|
654
|
+
end
|
655
|
+
tags
|
656
|
+
end
|
657
|
+
|
563
658
|
# Set a local value for a thread tied to this object.
|
564
659
|
def set_thread_local_value(name, value) # :nodoc:
|
565
660
|
values = Thread.current[name]
|
@@ -3,16 +3,35 @@
|
|
3
3
|
module Lumberjack
|
4
4
|
module Rack
|
5
5
|
# Middleware to create a global context for Lumberjack for the scope of a rack request.
|
6
|
+
#
|
7
|
+
# The optional `env_tags` parameter can be used to set up global tags from the request
|
8
|
+
# environment. This is useful for setting tags that are relevant to the entire request
|
9
|
+
# like the request id, host, etc.
|
6
10
|
class Context
|
7
|
-
|
11
|
+
# @param [Object] app The rack application.
|
12
|
+
# @param [Hash] env_tags A hash of tags to set from the request environment. If a tag value is
|
13
|
+
# a Proc, it will be called with the request `env` as an argument to allow dynamic tag values
|
14
|
+
# based on request data.
|
15
|
+
def initialize(app, env_tags = nil)
|
8
16
|
@app = app
|
17
|
+
@env_tags = env_tags
|
9
18
|
end
|
10
19
|
|
11
20
|
def call(env)
|
12
21
|
Lumberjack.context do
|
22
|
+
apply_tags(env) if @env_tags
|
13
23
|
@app.call(env)
|
14
24
|
end
|
15
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def apply_tags(env)
|
30
|
+
tags = @env_tags.transform_values do |value|
|
31
|
+
value.is_a?(Proc) ? value.call(env) : value
|
32
|
+
end
|
33
|
+
Lumberjack.tag(tags)
|
34
|
+
end
|
16
35
|
end
|
17
36
|
end
|
18
37
|
end
|
@@ -5,12 +5,16 @@ module Lumberjack
|
|
5
5
|
# Support for using the Rails ActionDispatch request id in the log.
|
6
6
|
# The format is expected to be a random UUID and only the first chunk is used for terseness
|
7
7
|
# if the abbreviated argument is true.
|
8
|
+
#
|
9
|
+
# @deprecated Use tags instead of request id for unit of work. Will be removed in version 2.0.
|
8
10
|
class RequestId
|
9
11
|
REQUEST_ID = "action_dispatch.request_id"
|
10
12
|
|
11
13
|
def initialize(app, abbreviated = false)
|
12
|
-
|
13
|
-
|
14
|
+
Lumberjack::Utils.deprecated("Lumberjack::Rack::RequestId", "Lumberjack::Rack::RequestId will be removed in version 2.0") do
|
15
|
+
@app = app
|
16
|
+
@abbreviated = abbreviated
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
20
|
def call(env)
|
@@ -2,9 +2,13 @@
|
|
2
2
|
|
3
3
|
module Lumberjack
|
4
4
|
module Rack
|
5
|
+
# @deprecated Use the Lumberjack::Rack::Context middleware instead to set a global tag
|
6
|
+
# with an identifier to tie log entries together in a unit of work. Will be removed in version 2.0.
|
5
7
|
class UnitOfWork
|
6
8
|
def initialize(app)
|
7
|
-
|
9
|
+
Lumberjack::Utils.deprecated("Lumberjack::Rack::UnitOfWork", "Lumberjack::Rack::UnitOfWork will be removed in version 2.0") do
|
10
|
+
@app = app
|
11
|
+
end
|
8
12
|
end
|
9
13
|
|
10
14
|
def call(env)
|
@@ -11,13 +11,14 @@ module Lumberjack
|
|
11
11
|
class TagFormatter
|
12
12
|
def initialize
|
13
13
|
@formatters = {}
|
14
|
+
@class_formatters = {}
|
14
15
|
@default_formatter = nil
|
15
16
|
end
|
16
17
|
|
17
18
|
# Add a default formatter applied to all tag values. This can either be a Lumberjack::Formatter
|
18
19
|
# or an object that responds to `call` or a block.
|
19
20
|
#
|
20
|
-
# @param [Lumberjack::Formatter, #call, nil]
|
21
|
+
# @param formatter [Lumberjack::Formatter, #call, nil] The formatter to use.
|
21
22
|
# If this is nil, then the block will be used as the formatter.
|
22
23
|
# @return [Lumberjack::TagFormatter] self
|
23
24
|
def default(formatter = nil, &block)
|
@@ -35,22 +36,37 @@ module Lumberjack
|
|
35
36
|
self
|
36
37
|
end
|
37
38
|
|
38
|
-
# Add a formatter for specific tag names. This can either be a Lumberjack::Formatter
|
39
|
-
# or an object that responds to `call` or a block. The
|
40
|
-
#
|
39
|
+
# Add a formatter for specific tag names or object classes. This can either be a Lumberjack::Formatter
|
40
|
+
# or an object that responds to `call` or a block. The formatter will be applied if it matches either a tag name
|
41
|
+
# or if the tag value is an instance of a registered class. Tag name formatters will take precedence
|
42
|
+
# over class formatters. The default formatter will not be applied to a value if a tag formatter
|
43
|
+
# is applied to it.
|
41
44
|
#
|
42
|
-
#
|
43
|
-
#
|
45
|
+
# Name formatters can be applied to nested hashes using dot syntax. For example, if you add a formatter
|
46
|
+
# for "foo.bar", it will be applied to the value of the "bar" key in the "foo" tag if that value is a hash.
|
47
|
+
#
|
48
|
+
# Class formatters will be applied recursively to nested hashes and arrays.
|
49
|
+
#
|
50
|
+
# @param names_or_classes [String, Module, Array<String, Module>] The tag names or object classes
|
51
|
+
# to apply the formatter to.
|
52
|
+
# @param formatter [Lumberjack::Formatter, #call, nil] The formatter to use.
|
44
53
|
# If this is nil, then the block will be used as the formatter.
|
45
54
|
# @return [Lumberjack::TagFormatter] self
|
46
|
-
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# tag_formatter.add("password", &:redact)
|
58
|
+
def add(names_or_classes, formatter = nil, &block)
|
47
59
|
formatter ||= block
|
48
60
|
formatter = dereference_formatter(formatter)
|
49
61
|
if formatter.nil?
|
50
62
|
remove(key)
|
51
63
|
else
|
52
|
-
Array(
|
53
|
-
|
64
|
+
Array(names_or_classes).each do |key|
|
65
|
+
if key.is_a?(Module)
|
66
|
+
@class_formatters[key] = formatter
|
67
|
+
else
|
68
|
+
@formatters[key.to_s] = formatter
|
69
|
+
end
|
54
70
|
end
|
55
71
|
end
|
56
72
|
self
|
@@ -58,11 +74,15 @@ module Lumberjack
|
|
58
74
|
|
59
75
|
# Remove formatters for specific tag names. The default formatter will still be applied.
|
60
76
|
#
|
61
|
-
# @param [String, Array<String>]
|
77
|
+
# @param names_or_classes [String, Module, Array<String, Module>] The tag names or classes to remove the formatter from.
|
62
78
|
# @return [Lumberjack::TagFormatter] self
|
63
|
-
def remove(
|
64
|
-
Array(
|
65
|
-
|
79
|
+
def remove(names_or_classes)
|
80
|
+
Array(names_or_classes).each do |key|
|
81
|
+
if key.is_a?(Module)
|
82
|
+
@class_formatters.delete(key)
|
83
|
+
else
|
84
|
+
@formatters.delete(key.to_s)
|
85
|
+
end
|
66
86
|
end
|
67
87
|
self
|
68
88
|
end
|
@@ -78,28 +98,66 @@ module Lumberjack
|
|
78
98
|
|
79
99
|
# Format a hash of tags using the formatters
|
80
100
|
#
|
81
|
-
# @param [Hash]
|
101
|
+
# @param tags [Hash] The tags to format.
|
82
102
|
# @return [Hash] The formatted tags.
|
83
103
|
def format(tags)
|
84
104
|
return nil if tags.nil?
|
85
|
-
if @default_formatter.nil? &&
|
86
|
-
tags
|
105
|
+
if @default_formatter.nil? && @formatters.empty? && @class_formatters.empty?
|
106
|
+
return tags
|
107
|
+
end
|
108
|
+
|
109
|
+
formated_tags(tags)
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def formated_tags(tags, skip_classes: nil, prefix: nil)
|
115
|
+
formatted = {}
|
116
|
+
|
117
|
+
tags.each do |name, value|
|
118
|
+
name = name.to_s
|
119
|
+
formatted[name] = formatted_tag_value(name, value, skip_classes: skip_classes, prefix: prefix)
|
120
|
+
end
|
121
|
+
|
122
|
+
formatted
|
123
|
+
end
|
124
|
+
|
125
|
+
def formatted_tag_value(name, value, skip_classes: nil, prefix: nil)
|
126
|
+
prefixed_name = prefix ? "#{prefix}#{name}" : name
|
127
|
+
using_class_formatter = false
|
128
|
+
|
129
|
+
formatter = @formatters[prefixed_name]
|
130
|
+
if formatter.nil? && (skip_classes.nil? || !skip_classes.include?(value.class))
|
131
|
+
formatter = class_formatter(value.class)
|
132
|
+
using_class_formatter = true if formatter
|
133
|
+
end
|
134
|
+
|
135
|
+
formatter ||= @default_formatter
|
136
|
+
|
137
|
+
formatted_value = if formatter.is_a?(Lumberjack::Formatter)
|
138
|
+
formatter.format(value)
|
139
|
+
elsif formatter.respond_to?(:call)
|
140
|
+
formatter.call(value)
|
87
141
|
else
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
142
|
+
value
|
143
|
+
end
|
144
|
+
|
145
|
+
if formatted_value.is_a?(Enumerable)
|
146
|
+
skip_classes ||= []
|
147
|
+
skip_classes << value.class if using_class_formatter
|
148
|
+
sub_prefix = "#{prefixed_name}."
|
149
|
+
|
150
|
+
formatted_value = if formatted_value.is_a?(Hash)
|
151
|
+
formated_tags(formatted_value, skip_classes: skip_classes, prefix: sub_prefix)
|
152
|
+
else
|
153
|
+
formatted_value.collect do |item|
|
154
|
+
formatted_tag_value(nil, item, skip_classes: skip_classes, prefix: sub_prefix)
|
95
155
|
end
|
96
|
-
formatted[name.to_s] = value
|
97
156
|
end
|
98
|
-
formatted
|
99
157
|
end
|
100
|
-
end
|
101
158
|
|
102
|
-
|
159
|
+
formatted_value
|
160
|
+
end
|
103
161
|
|
104
162
|
def dereference_formatter(formatter)
|
105
163
|
if formatter.is_a?(TaggedLoggerSupport::Formatter)
|
@@ -111,5 +169,22 @@ module Lumberjack
|
|
111
169
|
formatter
|
112
170
|
end
|
113
171
|
end
|
172
|
+
|
173
|
+
def class_formatter(klass)
|
174
|
+
formatter = @class_formatters[klass]
|
175
|
+
return formatter if formatter
|
176
|
+
|
177
|
+
formatters = @class_formatters.select { |k, _| klass <= k }
|
178
|
+
return formatters.values.first if formatters.length <= 1
|
179
|
+
|
180
|
+
superclass = klass.superclass
|
181
|
+
while superclass
|
182
|
+
formatter = formatters[superclass]
|
183
|
+
return formatter if formatter
|
184
|
+
superclass = superclass.superclass
|
185
|
+
end
|
186
|
+
|
187
|
+
formatters.values.first
|
188
|
+
end
|
114
189
|
end
|
115
190
|
end
|
@@ -38,15 +38,19 @@ module Lumberjack
|
|
38
38
|
end
|
39
39
|
|
40
40
|
# Compatibility with ActiveSupport::TaggedLogging which only supports adding tags as strings.
|
41
|
-
#
|
42
|
-
# Otherwise it will be appended to a list named "tagged".
|
41
|
+
# Tags will be added to the "tagged" key in the logger's tags hash as an array.
|
43
42
|
def tagged(*tags, &block)
|
44
|
-
|
45
|
-
tags.flatten.
|
46
|
-
|
47
|
-
|
43
|
+
tagged_values = Array(tag_value("tagged"))
|
44
|
+
flattened_tags = tags.flatten.collect(&:to_s).reject do |tag|
|
45
|
+
tag.respond_to?(:blank?) ? tag.blank? : tag.empty?
|
46
|
+
end
|
47
|
+
tagged_values += flattened_tags unless flattened_tags.empty?
|
48
|
+
|
49
|
+
if block || in_tag_context?
|
50
|
+
tag("tagged" => tagged_values, &block)
|
51
|
+
else
|
52
|
+
tag_globally("tagged" => tagged_values)
|
48
53
|
end
|
49
|
-
tag(tag_hash, &block)
|
50
54
|
end
|
51
55
|
|
52
56
|
def push_tags(*tags)
|
@@ -54,13 +58,24 @@ module Lumberjack
|
|
54
58
|
end
|
55
59
|
|
56
60
|
def pop_tags(size = 1)
|
57
|
-
tagged_values =
|
61
|
+
tagged_values = tag_value("tagged")
|
62
|
+
return unless tagged_values.is_a?(Array)
|
63
|
+
|
58
64
|
tagged_values = ((tagged_values.size > size) ? tagged_values[0, tagged_values.size - size] : nil)
|
59
|
-
|
65
|
+
|
66
|
+
if in_tag_context?
|
67
|
+
tag("tagged" => tagged_values)
|
68
|
+
else
|
69
|
+
tag_globally("tagged" => tagged_values)
|
70
|
+
end
|
60
71
|
end
|
61
72
|
|
62
73
|
def clear_tags!
|
63
|
-
|
74
|
+
if in_tag_context?
|
75
|
+
tag("tagged" => nil)
|
76
|
+
else
|
77
|
+
tag_globally("tagged" => nil)
|
78
|
+
end
|
64
79
|
end
|
65
80
|
end
|
66
81
|
end
|
data/lib/lumberjack/tags.rb
CHANGED
@@ -12,14 +12,8 @@ module Lumberjack
|
|
12
12
|
return nil if hash.nil?
|
13
13
|
if hash.keys.all? { |key| key.is_a?(String) }
|
14
14
|
hash
|
15
|
-
elsif hash.respond_to?(:transform_keys)
|
16
|
-
hash.transform_keys(&:to_s)
|
17
15
|
else
|
18
|
-
|
19
|
-
hash.each do |key, value|
|
20
|
-
copy[key.to_s] = value
|
21
|
-
end
|
22
|
-
copy
|
16
|
+
hash.transform_keys(&:to_s)
|
23
17
|
end
|
24
18
|
end
|
25
19
|
|
data/lib/lumberjack/template.rb
CHANGED
@@ -99,7 +99,7 @@ module Lumberjack
|
|
99
99
|
return [nil] * (tag_vars.size + 1) if tags.nil? || tags.size == 0
|
100
100
|
|
101
101
|
tags_string = +""
|
102
|
-
tags.each do |name, value|
|
102
|
+
Lumberjack::Utils.flatten_tags(tags).each do |name, value|
|
103
103
|
unless value.nil? || tag_vars.include?(name)
|
104
104
|
value = value.to_s
|
105
105
|
value = value.gsub(Lumberjack::LINE_SEPARATOR, " ") if value.include?(Lumberjack::LINE_SEPARATOR)
|