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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/ARCHITECTURE.md +524 -176
  3. data/CHANGELOG.md +89 -0
  4. data/README.md +604 -211
  5. data/UPGRADE_GUIDE.md +80 -0
  6. data/VERSION +1 -1
  7. data/lib/lumberjack/attribute_formatter.rb +451 -0
  8. data/lib/lumberjack/attributes_helper.rb +100 -0
  9. data/lib/lumberjack/context.rb +120 -23
  10. data/lib/lumberjack/context_logger.rb +620 -0
  11. data/lib/lumberjack/device/buffer.rb +209 -0
  12. data/lib/lumberjack/device/date_rolling_log_file.rb +10 -62
  13. data/lib/lumberjack/device/log_file.rb +76 -29
  14. data/lib/lumberjack/device/logger_wrapper.rb +137 -0
  15. data/lib/lumberjack/device/multi.rb +92 -30
  16. data/lib/lumberjack/device/null.rb +26 -8
  17. data/lib/lumberjack/device/size_rolling_log_file.rb +13 -54
  18. data/lib/lumberjack/device/test.rb +337 -0
  19. data/lib/lumberjack/device/writer.rb +184 -176
  20. data/lib/lumberjack/device.rb +134 -15
  21. data/lib/lumberjack/device_registry.rb +90 -0
  22. data/lib/lumberjack/entry_formatter.rb +357 -0
  23. data/lib/lumberjack/fiber_locals.rb +55 -0
  24. data/lib/lumberjack/forked_logger.rb +143 -0
  25. data/lib/lumberjack/formatter/date_time_formatter.rb +14 -3
  26. data/lib/lumberjack/formatter/exception_formatter.rb +12 -2
  27. data/lib/lumberjack/formatter/id_formatter.rb +13 -1
  28. data/lib/lumberjack/formatter/inspect_formatter.rb +14 -1
  29. data/lib/lumberjack/formatter/multiply_formatter.rb +10 -0
  30. data/lib/lumberjack/formatter/object_formatter.rb +13 -1
  31. data/lib/lumberjack/formatter/pretty_print_formatter.rb +15 -2
  32. data/lib/lumberjack/formatter/redact_formatter.rb +18 -3
  33. data/lib/lumberjack/formatter/round_formatter.rb +12 -0
  34. data/lib/lumberjack/formatter/string_formatter.rb +9 -1
  35. data/lib/lumberjack/formatter/strip_formatter.rb +13 -1
  36. data/lib/lumberjack/formatter/structured_formatter.rb +18 -2
  37. data/lib/lumberjack/formatter/tagged_message.rb +10 -32
  38. data/lib/lumberjack/formatter/tags_formatter.rb +32 -0
  39. data/lib/lumberjack/formatter/truncate_formatter.rb +8 -1
  40. data/lib/lumberjack/formatter.rb +271 -141
  41. data/lib/lumberjack/formatter_registry.rb +84 -0
  42. data/lib/lumberjack/io_compatibility.rb +133 -0
  43. data/lib/lumberjack/local_log_template.rb +209 -0
  44. data/lib/lumberjack/log_entry.rb +154 -79
  45. data/lib/lumberjack/log_entry_matcher/score.rb +276 -0
  46. data/lib/lumberjack/log_entry_matcher.rb +126 -0
  47. data/lib/lumberjack/logger.rb +328 -556
  48. data/lib/lumberjack/message_attributes.rb +38 -0
  49. data/lib/lumberjack/rack/context.rb +66 -15
  50. data/lib/lumberjack/rack.rb +0 -2
  51. data/lib/lumberjack/remap_attribute.rb +24 -0
  52. data/lib/lumberjack/severity.rb +52 -15
  53. data/lib/lumberjack/tag_context.rb +8 -71
  54. data/lib/lumberjack/tag_formatter.rb +22 -188
  55. data/lib/lumberjack/tags.rb +15 -21
  56. data/lib/lumberjack/template.rb +252 -62
  57. data/lib/lumberjack/template_registry.rb +60 -0
  58. data/lib/lumberjack/utils.rb +198 -48
  59. data/lib/lumberjack.rb +167 -59
  60. data/lumberjack.gemspec +4 -2
  61. metadata +41 -15
  62. data/lib/lumberjack/device/rolling_log_file.rb +0 -145
  63. data/lib/lumberjack/rack/request_id.rb +0 -31
  64. data/lib/lumberjack/rack/unit_of_work.rb +0 -21
  65. data/lib/lumberjack/tagged_logger_support.rb +0 -81
  66. 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
- # Middleware to create a global context for Lumberjack for the scope of a rack request.
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 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.
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
- # @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)
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
- @env_tags = env_tags
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.context do
22
- apply_tags(env) if @env_tags
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
- def apply_tags(env)
30
- tags = @env_tags.transform_values do |value|
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(tags)
84
+ Lumberjack.tag(attributes)
34
85
  end
35
86
  end
36
87
  end
@@ -2,8 +2,6 @@
2
2
 
3
3
  module Lumberjack
4
4
  module Rack
5
- require_relative "rack/unit_of_work"
6
- require_relative "rack/request_id"
7
5
  require_relative "rack/context"
8
6
  end
9
7
  end
@@ -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
@@ -3,44 +3,81 @@
3
3
  module Lumberjack
4
4
  # The standard severity levels for logging messages.
5
5
  module Severity
6
- # Backward compatibilty with 1.0 API
7
- DEBUG = ::Logger::Severity::DEBUG
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
- SEVERITY_LABELS = %w[DEBUG INFO WARN ERROR FATAL UNKNOWN].freeze
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] severity The severity level to convert.
47
+ # @param severity [Integer] The severity level to convert.
20
48
  # @return [String] The severity label.
21
49
  def level_to_label(severity)
22
- SEVERITY_LABELS[severity] || SEVERITY_LABELS.last
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] label The severity label to convert.
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
- SEVERITY_LABELS.index(label.to_s.upcase) || UNKNOWN
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] value The value to coerce.
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?(Integer)
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
- # A tag context provides an interface for manipulating a tag hash.
5
- class TagContext
6
- def initialize(tags)
7
- @tags = tags
8
- end
9
-
10
- # Merge new tags into the context tags. Tag values will be flattened using dot notation
11
- # on the keys. So `{ a: { b: 'c' } }` will become `{ 'a.b' => 'c' }`.
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
- # Class for formatting tags. You can register a default formatter and tag
5
- # name specific formatters. Formatters can be either `Lumberjack::Formatter`
6
- # objects or any object that responds to `call`.
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
- # tag_formatter = Lumberjack::TagFormatter.new.default(Lumberjack::Formatter.new)
9
- # tag_formatter.add(["password", "email"]) { |value| "***" }
10
- # tag_formatter.add("finished_at", Lumberjack::Formatter::DateTimeFormatter.new("%Y-%m-%dT%H:%m:%S%z"))
11
- class TagFormatter
12
- def initialize
13
- @formatters = {}
14
- @class_formatters = {}
15
- @default_formatter = nil
16
- end
17
-
18
- # Add a default formatter applied to all tag values. This can either be a Lumberjack::Formatter
19
- # or an object that responds to `call` or a block.
20
- #
21
- # @param formatter [Lumberjack::Formatter, #call, nil] The formatter to use.
22
- # If this is nil, then the block will be used as the formatter.
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
- # @param tags [Hash] The tags to format.
102
- # @return [Hash] The formatted tags.
103
- def format(tags)
104
- return nil if tags.nil?
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
@@ -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] hash The hash to transform.
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
- return nil if hash.nil?
13
- if hash.keys.all? { |key| key.is_a?(String) }
14
- hash
15
- else
16
- hash.transform_keys(&:to_s)
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
- # Ensure keys are strings and expand any values in a hash that are Proc's by calling them and replacing
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] hash The hash to transform.
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
- return nil if hash.nil?
27
- if hash.all? { |key, value| key.is_a?(String) && !value.is_a?(Proc) }
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