lumberjack 1.4.2 → 2.0.0
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 +524 -176
- data/CHANGELOG.md +89 -0
- data/README.md +604 -211
- data/UPGRADE_GUIDE.md +80 -0
- data/VERSION +1 -1
- data/lib/lumberjack/attribute_formatter.rb +451 -0
- data/lib/lumberjack/attributes_helper.rb +100 -0
- data/lib/lumberjack/context.rb +120 -23
- data/lib/lumberjack/context_logger.rb +620 -0
- data/lib/lumberjack/device/buffer.rb +209 -0
- data/lib/lumberjack/device/date_rolling_log_file.rb +10 -62
- data/lib/lumberjack/device/log_file.rb +76 -29
- data/lib/lumberjack/device/logger_wrapper.rb +137 -0
- data/lib/lumberjack/device/multi.rb +92 -30
- data/lib/lumberjack/device/null.rb +26 -8
- data/lib/lumberjack/device/size_rolling_log_file.rb +13 -54
- data/lib/lumberjack/device/test.rb +337 -0
- data/lib/lumberjack/device/writer.rb +184 -176
- data/lib/lumberjack/device.rb +134 -15
- data/lib/lumberjack/device_registry.rb +90 -0
- data/lib/lumberjack/entry_formatter.rb +357 -0
- data/lib/lumberjack/fiber_locals.rb +55 -0
- data/lib/lumberjack/forked_logger.rb +143 -0
- data/lib/lumberjack/formatter/date_time_formatter.rb +14 -3
- data/lib/lumberjack/formatter/exception_formatter.rb +12 -2
- data/lib/lumberjack/formatter/id_formatter.rb +13 -1
- data/lib/lumberjack/formatter/inspect_formatter.rb +14 -1
- data/lib/lumberjack/formatter/multiply_formatter.rb +10 -0
- data/lib/lumberjack/formatter/object_formatter.rb +13 -1
- data/lib/lumberjack/formatter/pretty_print_formatter.rb +15 -2
- data/lib/lumberjack/formatter/redact_formatter.rb +18 -3
- data/lib/lumberjack/formatter/round_formatter.rb +12 -0
- data/lib/lumberjack/formatter/string_formatter.rb +9 -1
- data/lib/lumberjack/formatter/strip_formatter.rb +13 -1
- data/lib/lumberjack/formatter/structured_formatter.rb +18 -2
- data/lib/lumberjack/formatter/tagged_message.rb +10 -32
- data/lib/lumberjack/formatter/tags_formatter.rb +32 -0
- data/lib/lumberjack/formatter/truncate_formatter.rb +8 -1
- data/lib/lumberjack/formatter.rb +271 -141
- data/lib/lumberjack/formatter_registry.rb +84 -0
- data/lib/lumberjack/io_compatibility.rb +133 -0
- data/lib/lumberjack/local_log_template.rb +209 -0
- data/lib/lumberjack/log_entry.rb +154 -79
- data/lib/lumberjack/log_entry_matcher/score.rb +276 -0
- data/lib/lumberjack/log_entry_matcher.rb +126 -0
- data/lib/lumberjack/logger.rb +328 -556
- data/lib/lumberjack/message_attributes.rb +38 -0
- data/lib/lumberjack/rack/context.rb +66 -15
- data/lib/lumberjack/rack.rb +0 -2
- data/lib/lumberjack/remap_attribute.rb +24 -0
- data/lib/lumberjack/severity.rb +52 -15
- data/lib/lumberjack/tag_context.rb +8 -71
- data/lib/lumberjack/tag_formatter.rb +22 -188
- data/lib/lumberjack/tags.rb +15 -21
- data/lib/lumberjack/template.rb +252 -62
- data/lib/lumberjack/template_registry.rb +60 -0
- data/lib/lumberjack/utils.rb +198 -48
- data/lib/lumberjack.rb +167 -59
- data/lumberjack.gemspec +4 -2
- metadata +41 -15
- data/lib/lumberjack/device/rolling_log_file.rb +0 -145
- data/lib/lumberjack/rack/request_id.rb +0 -31
- data/lib/lumberjack/rack/unit_of_work.rb +0 -21
- data/lib/lumberjack/tagged_logger_support.rb +0 -81
- data/lib/lumberjack/tagged_logging.rb +0 -29
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lumberjack
|
4
|
+
# This class can be used as the return value from a formatter +call+ method to
|
5
|
+
# extract additional attributes from an object being logged. This can be useful when there
|
6
|
+
# using structured logging to include important metadata in the log entry in addition
|
7
|
+
# to the message.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # Automatically add attributes with error details when logging an exception.
|
11
|
+
# logger.add_formatter(Exception, ->(e) {
|
12
|
+
# Lumberjack::MessageAttributes.new(e.inspect, {
|
13
|
+
# error: {
|
14
|
+
# message: e.message,
|
15
|
+
# class: e.class.name,
|
16
|
+
# stack: e.backtrace
|
17
|
+
# }
|
18
|
+
# })
|
19
|
+
# })
|
20
|
+
class MessageAttributes
|
21
|
+
attr_reader :message, :attributes
|
22
|
+
|
23
|
+
# @param message [Object] The message to be logged.
|
24
|
+
# @param attributes [Hash] The attributes to be associated with the message.
|
25
|
+
def initialize(message, attributes)
|
26
|
+
@message = message
|
27
|
+
@attributes = attributes || {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
inspect
|
32
|
+
end
|
33
|
+
|
34
|
+
def inspect
|
35
|
+
{message: @message, attributes: @attributes}.inspect
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -2,35 +2,86 @@
|
|
2
2
|
|
3
3
|
module Lumberjack
|
4
4
|
module Rack
|
5
|
-
#
|
5
|
+
# Rack middleware ensures that a global Lumberjack context exists for
|
6
|
+
# the duration of each HTTP request. This middleware creates an isolated
|
7
|
+
# logging context that automatically cleans up after the request completes,
|
8
|
+
# ensuring that request-specific attributes don't leak between requests.
|
6
9
|
#
|
7
|
-
# The
|
8
|
-
#
|
9
|
-
#
|
10
|
+
# The middleware supports dynamic attribute extraction from the Rack environment,
|
11
|
+
# allowing automatic tagging of log entries with request-specific information
|
12
|
+
# such as request IDs, user agents, IP addresses, or any other data available
|
13
|
+
# in the Rack environment.
|
14
|
+
#
|
15
|
+
# This is particularly useful in web applications where you want to correlate
|
16
|
+
# all log entries within a single request with common identifying information,
|
17
|
+
# making it easier to trace request flows and debug issues.
|
18
|
+
#
|
19
|
+
# @example Basic usage in a Rack application
|
20
|
+
# use Lumberjack::Rack::Context
|
21
|
+
#
|
22
|
+
# @example With static attributes
|
23
|
+
# use Lumberjack::Rack::Context, {
|
24
|
+
# app_name: "MyWebApp",
|
25
|
+
# version: "1.2.3"
|
26
|
+
# }
|
27
|
+
#
|
28
|
+
# @example With dynamic attributes from request environment
|
29
|
+
# use Lumberjack::Rack::Context, {
|
30
|
+
# request_id: ->(env) { env["HTTP_X_REQUEST_ID"] },
|
31
|
+
# user_agent: ->(env) { env["HTTP_USER_AGENT"] },
|
32
|
+
# remote_ip: ->(env) { env["REMOTE_ADDR"] },
|
33
|
+
# method: ->(env) { env["REQUEST_METHOD"] },
|
34
|
+
# path: ->(env) { env["PATH_INFO"] }
|
35
|
+
# }
|
36
|
+
#
|
37
|
+
# @example Rails integration
|
38
|
+
# # In config/application.rb
|
39
|
+
# config.middleware.use Lumberjack::Rack::Context, {
|
40
|
+
# request_id: ->(env) { env["action_dispatch.request_id"] },
|
41
|
+
# session_id: ->(env) { env["rack.session"]&.id },
|
42
|
+
# user_id: ->(env) { env["warden"]&.user&.id }
|
43
|
+
# }
|
44
|
+
#
|
45
|
+
# @see Lumberjack.context
|
46
|
+
# @see Lumberjack.tag
|
10
47
|
class Context
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
48
|
+
# Initialize the middleware with the Rack application and optional environment
|
49
|
+
# attribute configuration. The middleware will create a scoped logging context
|
50
|
+
# for each request and automatically apply the specified attributes.
|
51
|
+
#
|
52
|
+
# @param app [Object] The next Rack application in the middleware stack
|
53
|
+
# @param env_attributes [Hash, nil] Optional hash defining attributes to extract
|
54
|
+
# from the request environment. Values can be:
|
55
|
+
# - Static values: Applied directly to all requests
|
56
|
+
# - Proc objects: Called with the Rack env hash to generate dynamic values
|
57
|
+
# - Any callable: Invoked with env to produce request-specific attributes
|
58
|
+
def initialize(app, env_attributes = nil)
|
16
59
|
@app = app
|
17
|
-
@
|
60
|
+
@env_attributes = env_attributes
|
18
61
|
end
|
19
62
|
|
63
|
+
# Process a Rack request within a scoped Lumberjack logging context.
|
64
|
+
#
|
65
|
+
# @param env [Hash] The Rack environment hash containing request information
|
66
|
+
# @return [Array] The standard Rack response array [status, headers, body]
|
20
67
|
def call(env)
|
21
|
-
Lumberjack.
|
22
|
-
|
68
|
+
Lumberjack.ensure_context do
|
69
|
+
apply_attributes(env) if @env_attributes
|
23
70
|
@app.call(env)
|
24
71
|
end
|
25
72
|
end
|
26
73
|
|
27
74
|
private
|
28
75
|
|
29
|
-
|
30
|
-
|
76
|
+
# Apply configured environment attributes to the current logging context.
|
77
|
+
#
|
78
|
+
# @param env [Hash] The Rack environment hash
|
79
|
+
# @return [void]
|
80
|
+
def apply_attributes(env)
|
81
|
+
attributes = @env_attributes.transform_values do |value|
|
31
82
|
value.is_a?(Proc) ? value.call(env) : value
|
32
83
|
end
|
33
|
-
Lumberjack.tag(
|
84
|
+
Lumberjack.tag(attributes)
|
34
85
|
end
|
35
86
|
end
|
36
87
|
end
|
data/lib/lumberjack/rack.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lumberjack
|
4
|
+
# This class can be used as a return value from an AttributeFormatter to indicate that the
|
5
|
+
# value should be remapped to a new attribute name.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# # Transform duration_millis and duration_micros to seconds and move to
|
9
|
+
# # the duration attribute.
|
10
|
+
# logger.formatter.format_attribute_name("duration_ms") do |value|
|
11
|
+
# Lumberjack::RemapAttribute.new("duration" => value.to_f / 1000)
|
12
|
+
# end
|
13
|
+
# logger.formatter.format_attribute_name("duration_micros") do |value|
|
14
|
+
# Lumberjack::RemapAttribute.new("duration" => value.to_f / 1_000_000)
|
15
|
+
# end
|
16
|
+
class RemapAttribute
|
17
|
+
attr_reader :attributes
|
18
|
+
|
19
|
+
# @param remapped_attributes [Hash] The remapped attribute with the new names.
|
20
|
+
def initialize(remapped_attributes)
|
21
|
+
@attributes = Lumberjack::Utils.flatten_attributes(remapped_attributes)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/lumberjack/severity.rb
CHANGED
@@ -3,44 +3,81 @@
|
|
3
3
|
module Lumberjack
|
4
4
|
# The standard severity levels for logging messages.
|
5
5
|
module Severity
|
6
|
-
#
|
7
|
-
|
8
|
-
INFO = ::Logger::Severity::INFO
|
9
|
-
WARN = ::Logger::Severity::WARN
|
10
|
-
ERROR = ::Logger::Severity::ERROR
|
11
|
-
FATAL = ::Logger::Severity::FATAL
|
12
|
-
UNKNOWN = ::Logger::Severity::UNKNOWN
|
6
|
+
# Custom severity level for trace messages, lower than DEBUG.
|
7
|
+
TRACE = -1
|
13
8
|
|
14
|
-
|
9
|
+
DEBUG = Logger::Severity::DEBUG
|
10
|
+
INFO = Logger::Severity::INFO
|
11
|
+
WARN = Logger::Severity::WARN
|
12
|
+
ERROR = Logger::Severity::ERROR
|
13
|
+
FATAL = Logger::Severity::FATAL
|
14
|
+
UNKNOWN = Logger::Severity::UNKNOWN
|
15
|
+
|
16
|
+
SEVERITY_LABELS = %w[TRACE DEBUG INFO WARN ERROR FATAL ANY].freeze
|
17
|
+
private_constant :SEVERITY_LABELS
|
18
|
+
|
19
|
+
# Data object for severity levels that includes variations on the label.
|
20
|
+
class Data
|
21
|
+
attr_reader :level, :label, :padded_label, :char, :emoji, :terminal_color
|
22
|
+
|
23
|
+
def initialize(level, label, emoji, terminal_color)
|
24
|
+
@level = level
|
25
|
+
@label = label.freeze
|
26
|
+
@padded_label = label.ljust(5).freeze
|
27
|
+
@char = label[0].freeze
|
28
|
+
@emoji = emoji.freeze
|
29
|
+
@terminal_color = "\e[38;5;#{terminal_color}m"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
SEVERITIES = [
|
34
|
+
Data.new(TRACE, "TRACE", "🔍", 247).freeze,
|
35
|
+
Data.new(DEBUG, "DEBUG", "🔧", 244).freeze,
|
36
|
+
Data.new(INFO, "INFO", "🔵", 33).freeze,
|
37
|
+
Data.new(WARN, "WARN", "🟡", 208).freeze,
|
38
|
+
Data.new(ERROR, "ERROR", "❌", 9).freeze,
|
39
|
+
Data.new(FATAL, "FATAL", "🔥", 160).freeze,
|
40
|
+
Data.new(UNKNOWN, "ANY", "❓", 129).freeze
|
41
|
+
].freeze
|
42
|
+
private_constant :SEVERITIES
|
15
43
|
|
16
44
|
class << self
|
17
45
|
# Convert a severity level to a label.
|
18
46
|
#
|
19
|
-
# @param [Integer]
|
47
|
+
# @param severity [Integer] The severity level to convert.
|
20
48
|
# @return [String] The severity label.
|
21
49
|
def level_to_label(severity)
|
22
|
-
|
50
|
+
SEVERITIES[severity + 1]&.label || SEVERITIES.last.label
|
23
51
|
end
|
24
52
|
|
25
53
|
# Convert a severity label to a level.
|
26
54
|
#
|
27
|
-
# @param [String, Symbol]
|
55
|
+
# @param label [String, Symbol] The severity label to convert.
|
28
56
|
# @return [Integer] The severity level.
|
29
57
|
def label_to_level(label)
|
30
|
-
|
58
|
+
label = label.to_s.upcase
|
59
|
+
(SEVERITY_LABELS.index(label) || UNKNOWN + 1) - 1
|
31
60
|
end
|
32
61
|
|
33
62
|
# Coerce a value to a severity level.
|
34
63
|
#
|
35
|
-
# @param [Integer, String, Symbol]
|
64
|
+
# @param value [Integer, String, Symbol] The value to coerce.
|
36
65
|
# @return [Integer] The severity level.
|
37
66
|
def coerce(value)
|
38
|
-
if value.is_a?(
|
39
|
-
value
|
67
|
+
if value.is_a?(Numeric)
|
68
|
+
value.to_i
|
40
69
|
else
|
41
70
|
label_to_level(value)
|
42
71
|
end
|
43
72
|
end
|
73
|
+
|
74
|
+
# Return a data object that maps the severity level to variations on the label.
|
75
|
+
#
|
76
|
+
# @param level [Integer, String, Symbol] The severity level.
|
77
|
+
# @return [SeverityData] The severity data object.
|
78
|
+
def data(level)
|
79
|
+
SEVERITIES[coerce(level) + 1] || SEVERITIES.last
|
80
|
+
end
|
44
81
|
end
|
45
82
|
end
|
46
83
|
end
|
@@ -1,78 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Lumberjack
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
# If a block is given, then the tags will only be added for the duration of the block.
|
14
|
-
#
|
15
|
-
# @param tags [Hash] The tags to set.
|
16
|
-
# @return [void]
|
17
|
-
def tag(tags)
|
18
|
-
@tags.merge!(Utils.flatten_tags(tags))
|
19
|
-
end
|
20
|
-
|
21
|
-
# Get a tag value.
|
22
|
-
#
|
23
|
-
# @param name [String, Symbol] The tag key.
|
24
|
-
# @return [Object] The tag value.
|
25
|
-
def [](name)
|
26
|
-
return nil if @tags.empty?
|
27
|
-
|
28
|
-
name = name.to_s
|
29
|
-
return @tags[name] if @tags.include?(name)
|
30
|
-
|
31
|
-
# Check for partial matches in dot notation and return the hash representing the partial match.
|
32
|
-
prefix_key = "#{name}."
|
33
|
-
matching_tags = {}
|
34
|
-
@tags.each do |key, value|
|
35
|
-
if key.start_with?(prefix_key)
|
36
|
-
# Remove the prefix to get the relative key
|
37
|
-
relative_key = key[prefix_key.length..-1]
|
38
|
-
matching_tags[relative_key] = value
|
39
|
-
end
|
4
|
+
# This class was renamed to Lumberjack::AttributesHelper. This class is provided for
|
5
|
+
# backward compatibility with the version 1.x API and will eventually be removed.
|
6
|
+
#
|
7
|
+
# @deprecated Use Lumberjack::AttributesHelper instead.
|
8
|
+
class TagContext < AttributesHelper
|
9
|
+
def initialize
|
10
|
+
Utils.deprecated("Lumberjack::TagContext", "Use Lumberjack::AttributesHelper instead.") do
|
11
|
+
super
|
40
12
|
end
|
41
|
-
|
42
|
-
return nil if matching_tags.empty?
|
43
|
-
matching_tags
|
44
|
-
end
|
45
|
-
|
46
|
-
# Set a tag value.
|
47
|
-
#
|
48
|
-
# @param name [String, Symbol] The tag name.
|
49
|
-
# @param value [Object] The tag value.
|
50
|
-
# @return [void]
|
51
|
-
def []=(name, value)
|
52
|
-
if value.is_a?(Hash)
|
53
|
-
@tags.merge!(Utils.flatten_tags(name => value))
|
54
|
-
else
|
55
|
-
@tags[name.to_s] = value
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# Remove tags from the context.
|
60
|
-
#
|
61
|
-
# @param names [Array<String, Symbol>] The tag names to remove.
|
62
|
-
# @return [void]
|
63
|
-
def delete(*names)
|
64
|
-
names.each do |name|
|
65
|
-
prefix_key = "#{name}."
|
66
|
-
@tags.delete_if { |k, _| k == name.to_s || k.start_with?(prefix_key) }
|
67
|
-
end
|
68
|
-
nil
|
69
|
-
end
|
70
|
-
|
71
|
-
# Return a copy of the tags as a hash.
|
72
|
-
#
|
73
|
-
# @return [Hash]
|
74
|
-
def to_h
|
75
|
-
@tags.dup
|
76
13
|
end
|
77
14
|
end
|
78
15
|
end
|
@@ -1,197 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Lumberjack
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
4
|
+
# TagFormatter has been renamed to {AttributeFormatter} as part of the transition from
|
5
|
+
# "tags" to "attributes" terminology in Lumberjack 2.0. This class exists solely for
|
6
|
+
# backward compatibility with the 1.x API and will be removed in a future version.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
#
|
22
|
-
#
|
23
|
-
# @return [Lumberjack::TagFormatter] self
|
24
|
-
def default(formatter = nil, &block)
|
25
|
-
formatter ||= block
|
26
|
-
formatter = dereference_formatter(formatter)
|
27
|
-
@default_formatter = formatter
|
28
|
-
self
|
29
|
-
end
|
30
|
-
|
31
|
-
# Remove the default formatter.
|
32
|
-
#
|
33
|
-
# @return [Lumberjack::TagFormatter] self
|
34
|
-
def remove_default
|
35
|
-
@default_formatter = nil
|
36
|
-
self
|
37
|
-
end
|
38
|
-
|
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.
|
44
|
-
#
|
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.
|
53
|
-
# If this is nil, then the block will be used as the formatter.
|
54
|
-
# @return [Lumberjack::TagFormatter] self
|
55
|
-
#
|
56
|
-
# @example
|
57
|
-
# tag_formatter.add("password", &:redact)
|
58
|
-
def add(names_or_classes, formatter = nil, &block)
|
59
|
-
formatter ||= block
|
60
|
-
formatter = dereference_formatter(formatter)
|
61
|
-
if formatter.nil?
|
62
|
-
remove(key)
|
63
|
-
else
|
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
|
70
|
-
end
|
71
|
-
end
|
72
|
-
self
|
73
|
-
end
|
74
|
-
|
75
|
-
# Remove formatters for specific tag names. The default formatter will still be applied.
|
76
|
-
#
|
77
|
-
# @param names_or_classes [String, Module, Array<String, Module>] The tag names or classes to remove the formatter from.
|
78
|
-
# @return [Lumberjack::TagFormatter] self
|
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
|
86
|
-
end
|
87
|
-
self
|
88
|
-
end
|
89
|
-
|
90
|
-
# Remove all formatters.
|
91
|
-
#
|
92
|
-
# @return [Lumberjack::TagFormatter] self
|
93
|
-
def clear
|
94
|
-
@default_formatter = nil
|
95
|
-
@formatters.clear
|
96
|
-
self
|
97
|
-
end
|
98
|
-
|
99
|
-
# Format a hash of tags using the formatters
|
8
|
+
# All functionality has been moved to {AttributeFormatter} with no changes to the API.
|
9
|
+
# Simply replace +TagFormatter+ with +AttributeFormatter+ in your code.
|
10
|
+
#
|
11
|
+
# @deprecated Use {Lumberjack::AttributeFormatter} instead.
|
12
|
+
# @see Lumberjack::AttributeFormatter
|
13
|
+
#
|
14
|
+
# @example Migration
|
15
|
+
# # Old code (deprecated)
|
16
|
+
# formatter = Lumberjack::TagFormatter.new
|
17
|
+
#
|
18
|
+
# # New code
|
19
|
+
# formatter = Lumberjack::AttributeFormatter.new
|
20
|
+
class TagFormatter < AttributeFormatter
|
21
|
+
# Create a new TagFormatter instance. Issues a deprecation warning and delegates
|
22
|
+
# to {AttributeFormatter}.
|
100
23
|
#
|
101
|
-
# @
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
if @default_formatter.nil? && @formatters.empty? && @class_formatters.empty?
|
106
|
-
return tags
|
107
|
-
end
|
108
|
-
|
109
|
-
formatted_tags(tags)
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def formatted_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 = begin
|
138
|
-
if formatter.is_a?(Lumberjack::Formatter)
|
139
|
-
formatter.format(value)
|
140
|
-
elsif formatter.respond_to?(:call)
|
141
|
-
formatter.call(value)
|
142
|
-
else
|
143
|
-
value
|
144
|
-
end
|
145
|
-
rescue SystemStackError, StandardError => e
|
146
|
-
error_message = e.class.name
|
147
|
-
error_message = "#{error_message} #{e.message}" if e.message && e.message != ""
|
148
|
-
warn("<Error formatting #{value.class.name}: #{error_message}>")
|
149
|
-
"<Error formatting #{value.class.name}: #{error_message}>"
|
150
|
-
end
|
151
|
-
|
152
|
-
if formatted_value.is_a?(Enumerable)
|
153
|
-
skip_classes ||= []
|
154
|
-
skip_classes << value.class if using_class_formatter
|
155
|
-
sub_prefix = "#{prefixed_name}."
|
156
|
-
|
157
|
-
formatted_value = if formatted_value.is_a?(Hash)
|
158
|
-
formatted_tags(formatted_value, skip_classes: skip_classes, prefix: sub_prefix)
|
159
|
-
else
|
160
|
-
formatted_value.collect do |item|
|
161
|
-
formatted_tag_value(nil, item, skip_classes: skip_classes, prefix: sub_prefix)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
formatted_value
|
167
|
-
end
|
168
|
-
|
169
|
-
def dereference_formatter(formatter)
|
170
|
-
if formatter.is_a?(TaggedLoggerSupport::Formatter)
|
171
|
-
formatter.__formatter
|
172
|
-
elsif formatter.is_a?(Symbol)
|
173
|
-
formatter_class_name = "#{formatter.to_s.gsub(/(^|_)([a-z])/) { |m| $~[2].upcase }}Formatter"
|
174
|
-
Formatter.const_get(formatter_class_name).new
|
175
|
-
else
|
176
|
-
formatter
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def class_formatter(klass)
|
181
|
-
formatter = @class_formatters[klass]
|
182
|
-
return formatter if formatter
|
183
|
-
|
184
|
-
formatters = @class_formatters.select { |k, _| klass <= k }
|
185
|
-
return formatters.values.first if formatters.length <= 1
|
186
|
-
|
187
|
-
superclass = klass.superclass
|
188
|
-
while superclass
|
189
|
-
formatter = formatters[superclass]
|
190
|
-
return formatter if formatter
|
191
|
-
superclass = superclass.superclass
|
24
|
+
# @deprecated Use {Lumberjack::AttributeFormatter.new} instead.
|
25
|
+
def initialize
|
26
|
+
Utils.deprecated("Lumberjack::TagFormatter", "Use Lumberjack::AttributeFormatter instead.") do
|
27
|
+
super
|
192
28
|
end
|
193
|
-
|
194
|
-
formatters.values.first
|
195
29
|
end
|
196
30
|
end
|
197
31
|
end
|
data/lib/lumberjack/tags.rb
CHANGED
@@ -6,36 +6,30 @@ module Lumberjack
|
|
6
6
|
# Transform hash keys to strings. This method exists for optimization and backward compatibility.
|
7
7
|
# If a hash already has string keys, it will be returned as is.
|
8
8
|
#
|
9
|
-
# @param [Hash]
|
9
|
+
# @param hash [Hash] The hash to transform.
|
10
10
|
# @return [Hash] The hash with string keys.
|
11
|
+
# @deprecated No longer supported
|
11
12
|
def stringify_keys(hash)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
Utils.deprecated("Lumberjack::Tags.stringify_keys", "Lumberjack::Tags.stringify_keys is no longer supported and will be removed in version 2.1") do
|
14
|
+
return nil if hash.nil?
|
15
|
+
|
16
|
+
if hash.keys.all? { |key| key.is_a?(String) }
|
17
|
+
hash
|
18
|
+
else
|
19
|
+
hash.transform_keys(&:to_s)
|
20
|
+
end
|
17
21
|
end
|
18
22
|
end
|
19
23
|
|
20
|
-
#
|
21
|
-
# the value with the result. This allows setting global tags with runtime values.
|
24
|
+
# Alias to AttributesHelper.expand_runtime_values
|
22
25
|
#
|
23
|
-
# @param [Hash]
|
26
|
+
# @param hash [Hash] The hash to transform.
|
24
27
|
# @return [Hash] The hash with string keys and expanded values.
|
28
|
+
# @deprecated Use {Lumberjack::AttributesHelper.expand_runtime_values} instead.
|
25
29
|
def expand_runtime_values(hash)
|
26
|
-
|
27
|
-
|
28
|
-
return hash
|
29
|
-
end
|
30
|
-
|
31
|
-
copy = {}
|
32
|
-
hash.each do |key, value|
|
33
|
-
if value.is_a?(Proc) && (value.arity == 0 || value.arity == -1)
|
34
|
-
value = value.call
|
35
|
-
end
|
36
|
-
copy[key.to_s] = value
|
30
|
+
Utils.deprecated("Lumberjack::Tags.expand_runtime_values", "Lumberjack::Tags.expand_runtime_values is deprecated and will be removed in version 2.1; use Lumberjack::AttributesHelper.expand_runtime_values instead.") do
|
31
|
+
AttributesHelper.expand_runtime_values(hash)
|
37
32
|
end
|
38
|
-
copy
|
39
33
|
end
|
40
34
|
end
|
41
35
|
end
|