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
metadata CHANGED
@@ -1,15 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lumberjack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.2
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Durand
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-09-12 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: logger
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
13
26
  - !ruby/object:Gem::Dependency
14
27
  name: bundler
15
28
  requirement: !ruby/object:Gem::Requirement
@@ -24,7 +37,6 @@ dependencies:
24
37
  - - ">="
25
38
  - !ruby/object:Gem::Version
26
39
  version: '0'
27
- description:
28
40
  email:
29
41
  - bbdurand@gmail.com
30
42
  executables: []
@@ -35,17 +47,27 @@ files:
35
47
  - CHANGELOG.md
36
48
  - MIT_LICENSE.txt
37
49
  - README.md
50
+ - UPGRADE_GUIDE.md
38
51
  - VERSION
39
52
  - lib/lumberjack.rb
53
+ - lib/lumberjack/attribute_formatter.rb
54
+ - lib/lumberjack/attributes_helper.rb
40
55
  - lib/lumberjack/context.rb
56
+ - lib/lumberjack/context_logger.rb
41
57
  - lib/lumberjack/device.rb
58
+ - lib/lumberjack/device/buffer.rb
42
59
  - lib/lumberjack/device/date_rolling_log_file.rb
43
60
  - lib/lumberjack/device/log_file.rb
61
+ - lib/lumberjack/device/logger_wrapper.rb
44
62
  - lib/lumberjack/device/multi.rb
45
63
  - lib/lumberjack/device/null.rb
46
- - lib/lumberjack/device/rolling_log_file.rb
47
64
  - lib/lumberjack/device/size_rolling_log_file.rb
65
+ - lib/lumberjack/device/test.rb
48
66
  - lib/lumberjack/device/writer.rb
67
+ - lib/lumberjack/device_registry.rb
68
+ - lib/lumberjack/entry_formatter.rb
69
+ - lib/lumberjack/fiber_locals.rb
70
+ - lib/lumberjack/forked_logger.rb
49
71
  - lib/lumberjack/formatter.rb
50
72
  - lib/lumberjack/formatter/date_time_formatter.rb
51
73
  - lib/lumberjack/formatter/exception_formatter.rb
@@ -60,20 +82,25 @@ files:
60
82
  - lib/lumberjack/formatter/strip_formatter.rb
61
83
  - lib/lumberjack/formatter/structured_formatter.rb
62
84
  - lib/lumberjack/formatter/tagged_message.rb
85
+ - lib/lumberjack/formatter/tags_formatter.rb
63
86
  - lib/lumberjack/formatter/truncate_formatter.rb
87
+ - lib/lumberjack/formatter_registry.rb
88
+ - lib/lumberjack/io_compatibility.rb
89
+ - lib/lumberjack/local_log_template.rb
64
90
  - lib/lumberjack/log_entry.rb
91
+ - lib/lumberjack/log_entry_matcher.rb
92
+ - lib/lumberjack/log_entry_matcher/score.rb
65
93
  - lib/lumberjack/logger.rb
94
+ - lib/lumberjack/message_attributes.rb
66
95
  - lib/lumberjack/rack.rb
67
96
  - lib/lumberjack/rack/context.rb
68
- - lib/lumberjack/rack/request_id.rb
69
- - lib/lumberjack/rack/unit_of_work.rb
97
+ - lib/lumberjack/remap_attribute.rb
70
98
  - lib/lumberjack/severity.rb
71
99
  - lib/lumberjack/tag_context.rb
72
100
  - lib/lumberjack/tag_formatter.rb
73
- - lib/lumberjack/tagged_logger_support.rb
74
- - lib/lumberjack/tagged_logging.rb
75
101
  - lib/lumberjack/tags.rb
76
102
  - lib/lumberjack/template.rb
103
+ - lib/lumberjack/template_registry.rb
77
104
  - lib/lumberjack/utils.rb
78
105
  - lumberjack.gemspec
79
106
  homepage: https://github.com/bdurand/lumberjack
@@ -83,7 +110,6 @@ metadata:
83
110
  homepage_uri: https://github.com/bdurand/lumberjack
84
111
  source_code_uri: https://github.com/bdurand/lumberjack
85
112
  changelog_uri: https://github.com/bdurand/lumberjack/blob/main/CHANGELOG.md
86
- post_install_message:
87
113
  rdoc_options: []
88
114
  require_paths:
89
115
  - lib
@@ -91,16 +117,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
117
  requirements:
92
118
  - - ">="
93
119
  - !ruby/object:Gem::Version
94
- version: 2.5.0
120
+ version: '2.7'
95
121
  required_rubygems_version: !ruby/object:Gem::Requirement
96
122
  requirements:
97
123
  - - ">="
98
124
  - !ruby/object:Gem::Version
99
125
  version: '0'
100
126
  requirements: []
101
- rubygems_version: 3.4.10
102
- signing_key:
127
+ rubygems_version: 3.6.9
103
128
  specification_version: 4
104
- summary: A simple, powerful, and fast logging utility with excellent structured logging
105
- support that can be a drop in replacement for the standard library Logger.
129
+ summary: Extension of Ruby’s standard Logger for advanced, structured logging. Includes
130
+ log entry attributes, context isolation, customizable formatters, flexible output
131
+ devices, and testing tools.
106
132
  test_files: []
@@ -1,145 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lumberjack
4
- class Device
5
- # This is an abstract class for a device that appends entries to a file and periodically archives
6
- # the existing file and starts a one. Subclasses must implement the roll_file? and archive_file_suffix
7
- # methods.
8
- #
9
- # The :keep option can be used to specify a maximum number of rolled log files to keep.
10
- # Older files will be deleted based on the time they were created. The default is to keep all files.
11
- #
12
- # The :min_roll_check option can be used to specify the number of seconds between checking
13
- # the file to determine if it needs to be rolled. The default is to check at most once per second.
14
- class RollingLogFile < LogFile
15
- attr_reader :path
16
- attr_accessor :keep
17
-
18
- def initialize(path, options = {})
19
- @path = File.expand_path(path)
20
- @keep = options[:keep]
21
- super
22
- @file_inode = begin
23
- stream.lstat.ino
24
- rescue
25
- nil
26
- end
27
- @@rolls = []
28
- @next_stat_check = Time.now.to_f
29
- @min_roll_check = (options[:min_roll_check] || 1.0).to_f
30
- end
31
-
32
- # Returns a suffix that will be appended to the file name when it is archived.. The suffix should
33
- # change after it is time to roll the file. The log file will be renamed when it is rolled.
34
- def archive_file_suffix
35
- raise NotImplementedError
36
- end
37
-
38
- # Return +true+ if the file should be rolled.
39
- def roll_file?
40
- raise NotImplementedError
41
- end
42
-
43
- # Roll the log file by renaming it to the archive file name and then re-opening a stream to the log
44
- # file path. Rolling a file is safe in multi-threaded or multi-process environments.
45
- def roll_file! # :nodoc:
46
- do_once(stream) do
47
- archive_file = "#{path}.#{archive_file_suffix}"
48
- stream.flush
49
- current_inode = begin
50
- File.stat(path).ino
51
- rescue
52
- nil
53
- end
54
- if @file_inode && current_inode == @file_inode && !File.exist?(archive_file) && File.exist?(path)
55
- begin
56
- File.rename(path, archive_file)
57
- after_roll
58
- cleanup_files!
59
- rescue SystemCallError
60
- # Ignore rename errors since it indicates the file was already rolled
61
- end
62
- end
63
- reopen_file
64
- end
65
- rescue => e
66
- $stderr.write("Failed to roll file #{path}: #{e.inspect}\n#{e.backtrace.join("\n")}\n")
67
- end
68
-
69
- protected
70
-
71
- # This method will be called after a file has been rolled. Subclasses can
72
- # implement code to reset the state of the device. This method is thread safe.
73
- def after_roll
74
- end
75
-
76
- # Handle rolling the file before flushing.
77
- def before_flush # :nodoc:
78
- if @min_roll_check <= 0.0 || Time.now.to_f >= @next_stat_check
79
- @next_stat_check += @min_roll_check
80
- path_inode = begin
81
- File.lstat(path).ino
82
- rescue
83
- nil
84
- end
85
- if path_inode != @file_inode
86
- @file_inode = path_inode
87
- reopen_file
88
- elsif roll_file?
89
- roll_file!
90
- end
91
- end
92
- end
93
-
94
- private
95
-
96
- def reopen_file
97
- old_stream = stream
98
- new_stream = File.open(path, "a", encoding: EXTERNAL_ENCODING)
99
- new_stream.sync = true if buffer_size > 0
100
- @file_inode = begin
101
- new_stream.lstat.ino
102
- rescue
103
- nil
104
- end
105
- self.stream = new_stream
106
- old_stream.close
107
- end
108
- end
109
-
110
- def cleanup_files!
111
- if keep
112
- files = Dir.glob("#{path}.*").collect { |f| [f, File.ctime(f)] }.sort { |a, b| b.last <=> a.last }.collect { |a| a.first }
113
- if files.size > keep
114
- files[keep, files.length].each do |f|
115
- File.delete(f)
116
- end
117
- end
118
- end
119
- end
120
-
121
- def do_once(file)
122
- begin
123
- file.flock(File::LOCK_EX)
124
- rescue SystemCallError
125
- # Most likely can't lock file because the stream is closed
126
- return
127
- end
128
- begin
129
- verify = begin
130
- file.lstat
131
- rescue
132
- nil
133
- end
134
- # Execute only if the file we locked is still the same one that needed to be rolled
135
- yield if verify && verify.ino == @file_inode && verify.size > 0
136
- ensure
137
- begin
138
- file.flock(File::LOCK_UN)
139
- rescue
140
- nil
141
- end
142
- end
143
- end
144
- end
145
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lumberjack
4
- module Rack
5
- # Support for using the Rails ActionDispatch request id in the log.
6
- # The format is expected to be a random UUID and only the first chunk is used for terseness
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.
10
- class RequestId
11
- REQUEST_ID = "action_dispatch.request_id"
12
-
13
- def initialize(app, abbreviated = false)
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
18
- end
19
-
20
- def call(env)
21
- request_id = env[REQUEST_ID]
22
- if request_id && @abbreviated
23
- request_id = request_id.split("-", 2).first
24
- end
25
- Lumberjack.unit_of_work(request_id) do
26
- @app.call(env)
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lumberjack
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.
7
- class UnitOfWork
8
- def initialize(app)
9
- Lumberjack::Utils.deprecated("Lumberjack::Rack::UnitOfWork", "Lumberjack::Rack::UnitOfWork will be removed in version 2.0") do
10
- @app = app
11
- end
12
- end
13
-
14
- def call(env)
15
- Lumberjack.unit_of_work do
16
- @app.call(env)
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "delegate"
4
- require "forwardable"
5
-
6
- module Lumberjack
7
- # Methods to make Lumberjack::Logger API compatible with ActiveSupport::TaggedLogger.
8
- module TaggedLoggerSupport
9
- class Formatter < DelegateClass(Lumberjack::Formatter)
10
- extend Forwardable
11
- def_delegators :@logger, :tagged, :push_tags, :pop_tags, :clear_tags!
12
-
13
- def initialize(formatter:, logger:)
14
- @logger = logger
15
- @formatter = formatter
16
- super(formatter)
17
- end
18
-
19
- def current_tags
20
- tags = @logger.instance_variable_get(:@tags)
21
- if tags.is_a?(Hash)
22
- Array(tags["tagged"])
23
- else
24
- []
25
- end
26
- end
27
-
28
- def tags_text
29
- tags = current_tags
30
- if tags.any?
31
- tags.collect { |tag| "[#{tag}] " }.join
32
- end
33
- end
34
-
35
- def __formatter
36
- @formatter
37
- end
38
- end
39
-
40
- # Compatibility with ActiveSupport::TaggedLogging which only supports adding tags as strings.
41
- # Tags will be added to the "tagged" key in the logger's tags hash as an array.
42
- def tagged(*tags, &block)
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)
53
- end
54
- end
55
-
56
- def push_tags(*tags)
57
- tagged(*tags)
58
- end
59
-
60
- def pop_tags(size = 1)
61
- tagged_values = tag_value("tagged")
62
- return unless tagged_values.is_a?(Array)
63
-
64
- tagged_values = ((tagged_values.size > size) ? tagged_values[0, tagged_values.size - size] : nil)
65
-
66
- if in_tag_context?
67
- tag("tagged" => tagged_values)
68
- else
69
- tag_globally("tagged" => tagged_values)
70
- end
71
- end
72
-
73
- def clear_tags!
74
- if in_tag_context?
75
- tag("tagged" => nil)
76
- else
77
- tag_globally("tagged" => nil)
78
- end
79
- end
80
- end
81
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lumberjack
4
- # Monkey patch for ActiveSupport::TaggedLogger so it doesn't blow up when
5
- # a Lumberjack logger is trying to be wrapped. This module will be automatically
6
- # included in ActiveSupport::TaggedLogger if activesupport is already loaded.
7
- module TaggedLogging
8
- class << self
9
- def included(base)
10
- base.singleton_class.send(:prepend, ClassMethods)
11
- end
12
- end
13
-
14
- module ClassMethods
15
- def new(logger)
16
- if logger.is_a?(Lumberjack::Logger)
17
- logger = logger.tagged_logger! unless logger.respond_to?(:tagged)
18
- logger
19
- else
20
- super
21
- end
22
- end
23
- end
24
- end
25
- end
26
-
27
- if defined?(ActiveSupport::TaggedLogging)
28
- ActiveSupport::TaggedLogging.include(Lumberjack::TaggedLogging)
29
- end