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
@@ -4,7 +4,12 @@ module Lumberjack
|
|
4
4
|
class Formatter
|
5
5
|
# This formatter can be used to multiply a numeric value by a specified multiplier and
|
6
6
|
# optionally round to a specified number of decimal places.
|
7
|
+
#
|
8
|
+
# This is useful for unit conversions (e.g., converting seconds to milliseconds)
|
9
|
+
# or scaling values for display purposes. Non-numeric values are passed through unchanged.
|
7
10
|
class MultiplyFormatter
|
11
|
+
FormatterRegistry.add(:multiply, self)
|
12
|
+
|
8
13
|
# @param multiplier [Numeric] The multiplier to apply to the value.
|
9
14
|
# @param decimals [Integer, nil] The number of decimal places to round the result to.
|
10
15
|
# If nil, no rounding is applied.
|
@@ -13,6 +18,11 @@ module Lumberjack
|
|
13
18
|
@decimals = decimals
|
14
19
|
end
|
15
20
|
|
21
|
+
# Multiply a numeric value by the configured multiplier and optionally round.
|
22
|
+
#
|
23
|
+
# @param value [Object] The value to format. Only numeric values are processed.
|
24
|
+
# @return [Numeric, Object] The multiplied (and optionally rounded) value if numeric,
|
25
|
+
# otherwise returns the original value unchanged.
|
16
26
|
def call(value)
|
17
27
|
return value unless value.is_a?(Numeric)
|
18
28
|
|
@@ -2,8 +2,20 @@
|
|
2
2
|
|
3
3
|
module Lumberjack
|
4
4
|
class Formatter
|
5
|
-
# No-op formatter that
|
5
|
+
# No-op formatter that returns the object unchanged. This formatter is useful
|
6
|
+
# as a default or fallback formatter when you want to preserve the original
|
7
|
+
# object without any transformation.
|
8
|
+
#
|
9
|
+
# The ObjectFormatter is commonly used in scenarios where you want to maintain
|
10
|
+
# the original data structure and let downstream components handle the actual
|
11
|
+
# formatting, or when you need a placeholder formatter in the formatter chain.
|
6
12
|
class ObjectFormatter
|
13
|
+
FormatterRegistry.add(:object, self)
|
14
|
+
|
15
|
+
# Return the object unchanged.
|
16
|
+
#
|
17
|
+
# @param obj [Object] The object to format.
|
18
|
+
# @return [Object] The original object without any modifications.
|
7
19
|
def call(obj)
|
8
20
|
obj
|
9
21
|
end
|
@@ -5,18 +5,31 @@ require "stringio"
|
|
5
5
|
|
6
6
|
module Lumberjack
|
7
7
|
class Formatter
|
8
|
-
# Format an object with
|
8
|
+
# Format an object with its pretty print method. This formatter provides multi-line,
|
9
|
+
# indented output that makes complex data structures easier to read and debug.
|
10
|
+
# It's particularly useful for logging hashes, arrays, and other nested objects.
|
11
|
+
#
|
12
|
+
# The formatter uses Ruby's built-in PP (Pretty Print) library to generate
|
13
|
+
# well-formatted output with appropriate indentation and line breaks.
|
9
14
|
class PrettyPrintFormatter
|
15
|
+
FormatterRegistry.add(:pretty_print, self)
|
16
|
+
|
17
|
+
# @!attribute [rw] width
|
18
|
+
# @return [Integer] The maximum width of the message.
|
10
19
|
attr_accessor :width
|
11
20
|
|
12
21
|
# Create a new formatter. The maximum width of the message can be specified with the width
|
13
22
|
# parameter (defaults to 79 characters).
|
14
23
|
#
|
15
|
-
# @param [Integer]
|
24
|
+
# @param width [Integer] The maximum width of the message.
|
16
25
|
def initialize(width = 79)
|
17
26
|
@width = width
|
18
27
|
end
|
19
28
|
|
29
|
+
# Format an object using pretty print with the configured width.
|
30
|
+
#
|
31
|
+
# @param obj [Object] The object to format.
|
32
|
+
# @return [String] The pretty-printed representation of the object.
|
20
33
|
def call(obj)
|
21
34
|
s = StringIO.new
|
22
35
|
PP.pp(obj, s)
|
@@ -2,16 +2,31 @@
|
|
2
2
|
|
3
3
|
module Lumberjack
|
4
4
|
class Formatter
|
5
|
-
# Log sensitive information in a redacted format showing the
|
5
|
+
# Log sensitive information in a redacted format showing the first and last
|
6
6
|
# characters of the value, with the rest replaced by asterisks. The number of
|
7
|
-
# characters shown is dependent
|
7
|
+
# characters shown is dependent on the length of the value; short values will
|
8
8
|
# not show any characters in order to avoid revealing too much information.
|
9
|
+
#
|
10
|
+
# This formatter is useful for logging sensitive data while still providing
|
11
|
+
# enough context to distinguish between different values during debugging.
|
9
12
|
class RedactFormatter
|
13
|
+
FormatterRegistry.add(:redact, self)
|
14
|
+
|
15
|
+
# Redact a string value by showing only the first and last characters.
|
16
|
+
#
|
17
|
+
# @param obj [Object] The object to format. Only strings are redacted.
|
18
|
+
# @return [String, Object] The redacted string if the object is a string,
|
19
|
+
# otherwise returns the object unchanged.
|
20
|
+
#
|
21
|
+
# @example Different string lengths
|
22
|
+
# formatter.call("password123") # => "pa*******23"
|
23
|
+
# formatter.call("secret") # => "s****t"
|
24
|
+
# formatter.call("abc") # => "*****"
|
10
25
|
def call(obj)
|
11
26
|
return obj unless obj.is_a?(String)
|
12
27
|
|
13
28
|
if obj.length > 8
|
14
|
-
"#{obj[0..1]}#{"*" * (obj.length - 4)}#{obj[-2
|
29
|
+
"#{obj[0..1]}#{"*" * (obj.length - 4)}#{obj[-2..]}"
|
15
30
|
elsif obj.length > 5
|
16
31
|
"#{obj[0]}#{"*" * (obj.length - 2)}#{obj[-1]}"
|
17
32
|
else
|
@@ -4,11 +4,23 @@ module Lumberjack
|
|
4
4
|
class Formatter
|
5
5
|
# Round numeric values to a set number of decimal places. This is useful when logging
|
6
6
|
# floating point numbers to reduce noise and rounding errors in the logs.
|
7
|
+
#
|
8
|
+
# The formatter only affects numeric values, leaving other object types unchanged.
|
9
|
+
# This makes it safe to use as a general-purpose formatter for attributes that
|
10
|
+
# might contain various data types.
|
7
11
|
class RoundFormatter
|
12
|
+
FormatterRegistry.add(:round, self)
|
13
|
+
|
14
|
+
# @param precision [Integer] The number of decimal places to round to (defaults to 3).
|
8
15
|
def initialize(precision = 3)
|
9
16
|
@precision = precision
|
10
17
|
end
|
11
18
|
|
19
|
+
# Round a numeric value to the configured precision.
|
20
|
+
#
|
21
|
+
# @param obj [Object] The object to format. Only numeric values are rounded.
|
22
|
+
# @return [Numeric, Object] The rounded number if the object is numeric,
|
23
|
+
# otherwise returns the object unchanged.
|
12
24
|
def call(obj)
|
13
25
|
if obj.is_a?(Numeric)
|
14
26
|
obj.round(@precision)
|
@@ -2,8 +2,16 @@
|
|
2
2
|
|
3
3
|
module Lumberjack
|
4
4
|
class Formatter
|
5
|
-
# Format an object by calling
|
5
|
+
# Format an object by calling +to_s+ on it. This is the simplest formatter
|
6
|
+
# implementation and is commonly used as a fallback for objects that don't
|
7
|
+
# have specialized formatters.
|
6
8
|
class StringFormatter
|
9
|
+
FormatterRegistry.add(:string, self)
|
10
|
+
|
11
|
+
# Convert an object to its string representation.
|
12
|
+
#
|
13
|
+
# @param obj [Object] The object to format.
|
14
|
+
# @return [String] The string representation of the object.
|
7
15
|
def call(obj)
|
8
16
|
obj.to_s
|
9
17
|
end
|
@@ -2,8 +2,20 @@
|
|
2
2
|
|
3
3
|
module Lumberjack
|
4
4
|
class Formatter
|
5
|
-
# Format an object by calling
|
5
|
+
# Format an object by calling +to_s+ on it and stripping leading and trailing whitespace.
|
6
|
+
# This formatter is useful for cleaning up string values that may have unwanted whitespace
|
7
|
+
# from user input, file processing, or other sources.
|
8
|
+
#
|
9
|
+
# The StripFormatter combines string conversion with whitespace normalization,
|
10
|
+
# making it ideal for attribute values that should be clean and consistent
|
11
|
+
# in log output.
|
6
12
|
class StripFormatter
|
13
|
+
FormatterRegistry.add(:strip, self)
|
14
|
+
|
15
|
+
# Convert an object to a string and remove leading and trailing whitespace.
|
16
|
+
#
|
17
|
+
# @param obj [Object] The object to format.
|
18
|
+
# @return [String] The string representation with whitespace stripped.
|
7
19
|
def call(obj)
|
8
20
|
obj.to_s.strip
|
9
21
|
end
|
@@ -5,16 +5,31 @@ require "set"
|
|
5
5
|
module Lumberjack
|
6
6
|
class Formatter
|
7
7
|
# Dereference arrays and hashes and recursively call formatters on each element.
|
8
|
+
# This formatter provides deep traversal of nested data structures, applying
|
9
|
+
# formatting to all contained elements while handling circular references safely.
|
10
|
+
#
|
11
|
+
# The StructuredFormatter is essential for formatting complex nested objects
|
12
|
+
# like configuration hashes, API responses, or any hierarchical data structures
|
13
|
+
# that need consistent formatting throughout their entire structure.
|
8
14
|
class StructuredFormatter
|
15
|
+
FormatterRegistry.add(:structured, self)
|
16
|
+
|
17
|
+
# Exception raised when a circular reference is detected during traversal.
|
18
|
+
# This prevents infinite recursion when formatting objects that reference themselves.
|
9
19
|
class RecusiveReferenceError < StandardError
|
10
20
|
end
|
11
21
|
|
12
|
-
# @param [Formatter]
|
13
|
-
# in the structure.
|
22
|
+
# @param formatter [Formatter, nil] The formatter to call on each element
|
23
|
+
# in the structure. If nil, elements are returned unchanged.
|
14
24
|
def initialize(formatter = nil)
|
15
25
|
@formatter = formatter
|
16
26
|
end
|
17
27
|
|
28
|
+
# Format a structured object by recursively processing all nested elements.
|
29
|
+
#
|
30
|
+
# @param obj [Object] The object to format. Arrays and hashes are traversed
|
31
|
+
# recursively, while other objects are passed to the configured formatter.
|
32
|
+
# @return [Object] The formatted structure with all nested elements processed.
|
18
33
|
def call(obj)
|
19
34
|
call_with_references(obj, Set.new)
|
20
35
|
end
|
@@ -50,6 +65,7 @@ module Lumberjack
|
|
50
65
|
def with_object_reference(obj, references)
|
51
66
|
if obj.is_a?(Enumerable)
|
52
67
|
return RecusiveReferenceError.new if references.include?(obj.object_id)
|
68
|
+
|
53
69
|
references << obj.object_id
|
54
70
|
begin
|
55
71
|
yield
|
@@ -1,38 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
class Formatter
|
5
|
-
# This class can be used as the return value from a formatter `call` method to
|
6
|
-
# extract additional tags from an object being logged. This can be useful when there
|
7
|
-
# using structured logging to include important metadata in the log message.
|
8
|
-
#
|
9
|
-
# @example
|
10
|
-
# # Automatically add tags with error details when logging an exception.
|
11
|
-
# logger.add_formatter(Exception, ->(e) {
|
12
|
-
# Lumberjack::Formatter::TaggedMessage.new(e.message, {
|
13
|
-
# error: {
|
14
|
-
# message: e.message,
|
15
|
-
# class: e.class.name,
|
16
|
-
# trace: e.backtrace
|
17
|
-
# }
|
18
|
-
# })
|
19
|
-
# })
|
20
|
-
class TaggedMessage
|
21
|
-
attr_reader :message, :tags
|
22
|
-
|
23
|
-
# @param [Formatter] formatter The formatter to apply the transformation to.
|
24
|
-
# @param [Proc] transform The transformation function to apply to the formatted string.
|
25
|
-
def initialize(message, tags)
|
26
|
-
@message = message
|
27
|
-
@tags = tags || {}
|
28
|
-
end
|
3
|
+
require_relative "../message_attributes"
|
29
4
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
5
|
+
module Lumberjack
|
6
|
+
# This is a deprecated alias for Lumberjack::MessageAttributes.
|
7
|
+
#
|
8
|
+
# @deprecated Use Lumberjack::MessageAttributes instead.
|
9
|
+
# @see MessageAttributes
|
10
|
+
class Formatter::TaggedMessage < MessageAttributes
|
11
|
+
def initialize(message, attributes)
|
12
|
+
Utils.deprecated("Lumberjack::Formatter::TaggedMessage", "Use Lumberjack::MessageAttributes instead.") do
|
13
|
+
super
|
36
14
|
end
|
37
15
|
end
|
38
16
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lumberjack
|
4
|
+
# This formatter is designed to output tags in a specific format.
|
5
|
+
#
|
6
|
+
# - Simple values will be formatted as "[value]"
|
7
|
+
# - Arrays will be formatted as "[value1] [value2] [value3]"
|
8
|
+
# - Hashes will be formatted as "[key1=value1] [key2=value2]"
|
9
|
+
# - Hashes in arrays will be formatted as "[key=value]"
|
10
|
+
class Formatter::TagsFormatter
|
11
|
+
FormatterRegistry.add(:tags, self)
|
12
|
+
|
13
|
+
def call(tags)
|
14
|
+
tags = tags.collect { |key, value| "#{key}=#{value}" } if tags.is_a?(Hash)
|
15
|
+
if tags.is_a?(Array)
|
16
|
+
tags.collect { |tag| format_tag(tag) }.join(" ") unless tags.empty?
|
17
|
+
else
|
18
|
+
format_tag(tags)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def format_tag(tag)
|
25
|
+
if tag.is_a?(Hash)
|
26
|
+
tag.collect { |key, value| "[#{key}=#{value.strip}]" }.join(" ")
|
27
|
+
else
|
28
|
+
"[#{tag.strip}]"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -10,11 +10,18 @@ module Lumberjack
|
|
10
10
|
# When a string is truncated, it will have a unicode ellipsis
|
11
11
|
# character (U+2026) appended to the end of the string.
|
12
12
|
class TruncateFormatter
|
13
|
-
|
13
|
+
FormatterRegistry.add(:truncate, self)
|
14
|
+
|
15
|
+
# @param length [Integer] The maximum length of the string (defaults to 32K).
|
14
16
|
def initialize(length = 32768)
|
15
17
|
@length = length
|
16
18
|
end
|
17
19
|
|
20
|
+
# Truncate a string if it exceeds the maximum length.
|
21
|
+
#
|
22
|
+
# @param obj [Object] The object to format. If it's a string longer than the maximum
|
23
|
+
# length, it will be truncated. Other objects are returned unchanged.
|
24
|
+
# @return [String, Object] The truncated string or original object.
|
18
25
|
def call(obj)
|
19
26
|
if obj.is_a?(String) && obj.length > @length
|
20
27
|
"#{obj[0, @length - 1]}…"
|