lumberjack 1.2.9 → 1.3.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/ARCHITECTURE.md +244 -0
  3. data/CHANGELOG.md +78 -2
  4. data/README.md +176 -58
  5. data/VERSION +1 -1
  6. data/lib/lumberjack/context.rb +5 -5
  7. data/lib/lumberjack/device/date_rolling_log_file.rb +1 -1
  8. data/lib/lumberjack/device/log_file.rb +1 -1
  9. data/lib/lumberjack/device/multi.rb +1 -1
  10. data/lib/lumberjack/device/null.rb +1 -1
  11. data/lib/lumberjack/device/rolling_log_file.rb +2 -2
  12. data/lib/lumberjack/device/size_rolling_log_file.rb +1 -1
  13. data/lib/lumberjack/device/writer.rb +13 -9
  14. data/lib/lumberjack/device.rb +1 -1
  15. data/lib/lumberjack/formatter/date_time_formatter.rb +2 -2
  16. data/lib/lumberjack/formatter/exception_formatter.rb +2 -2
  17. data/lib/lumberjack/formatter/id_formatter.rb +1 -1
  18. data/lib/lumberjack/formatter/inspect_formatter.rb +1 -1
  19. data/lib/lumberjack/formatter/multiply_formatter.rb +25 -0
  20. data/lib/lumberjack/formatter/object_formatter.rb +1 -1
  21. data/lib/lumberjack/formatter/pretty_print_formatter.rb +1 -1
  22. data/lib/lumberjack/formatter/redact_formatter.rb +23 -0
  23. data/lib/lumberjack/formatter/round_formatter.rb +21 -0
  24. data/lib/lumberjack/formatter/string_formatter.rb +1 -1
  25. data/lib/lumberjack/formatter/strip_formatter.rb +1 -1
  26. data/lib/lumberjack/formatter/structured_formatter.rb +1 -1
  27. data/lib/lumberjack/formatter/tagged_message.rb +39 -0
  28. data/lib/lumberjack/formatter/truncate_formatter.rb +1 -1
  29. data/lib/lumberjack/formatter.rb +29 -14
  30. data/lib/lumberjack/log_entry.rb +25 -15
  31. data/lib/lumberjack/logger.rb +132 -40
  32. data/lib/lumberjack/rack/context.rb +21 -2
  33. data/lib/lumberjack/rack/request_id.rb +7 -3
  34. data/lib/lumberjack/rack/unit_of_work.rb +6 -2
  35. data/lib/lumberjack/rack.rb +1 -1
  36. data/lib/lumberjack/severity.rb +13 -1
  37. data/lib/lumberjack/tag_formatter.rb +102 -27
  38. data/lib/lumberjack/tagged_logger_support.rb +6 -1
  39. data/lib/lumberjack/tags.rb +1 -7
  40. data/lib/lumberjack/template.rb +3 -3
  41. data/lib/lumberjack/utils.rb +133 -0
  42. data/lib/lumberjack.rb +12 -6
  43. data/lumberjack.gemspec +2 -2
  44. metadata +12 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d05405664f1f85b1a68eb24c21a89d3b57ea8caf09513a348a138d53f1870b0
4
- data.tar.gz: 1ccc42fdd657ab4acf89bab8bfd7fb5e7d69d3825367483c49ee10c5c6e037d1
3
+ metadata.gz: a69bd8640229dc5e150255f601f1280dfe4fb325cee8879aa202114cd335512f
4
+ data.tar.gz: b2cd71293d94653f03ed04df094d69587d76e2b544d8a46149d139d7e952c0fc
5
5
  SHA512:
6
- metadata.gz: b48a0035d1adf22768071e6025692f001a8d13b931314ab0b6ea9131696bcb38d321db5fc1246bf2c49623cad26770bfdb32fe0e8e169ae455322e2693dad8e8
7
- data.tar.gz: f80ae18348c1a3e5261aa27051d4cf3e087550e0d57d3a13459da6f7641e0ea270382478108127f03f6b7596faab27d8d3f92488fbbb2cb0c50c4d247ac61910
6
+ metadata.gz: 484530ed54b537da178e956fc654ddcfc81fa74cfed495ba94ca04e1e350d1e29089198da6d77bb700cc227a5ee49949ac8d40c09c152e7e2ffc3ab7a7f6e7a5
7
+ data.tar.gz: f0025936e20a24d8da09d2dd9cd863aaface259ce2b1b21eff590f7bbb22daa7fcd5a67f192c0abe428131ab145ab0cd271143ab01b7f6b665db69ebcb63becf
data/ARCHITECTURE.md ADDED
@@ -0,0 +1,244 @@
1
+ # Lumberjack Gem Architecture
2
+
3
+ Lumberjack is a simple, powerful, and fast logging implementation in Ruby. It uses nearly the same API as the Logger class in the Ruby standard library and as ActiveSupport::BufferedLogger in Rails. The gem is designed with structured logging in mind, but can be used for simple text logging as well.
4
+
5
+ ## Overview
6
+
7
+ The Lumberjack architecture follows a clean separation of concerns with the following main components:
8
+
9
+ - **Logger**: The main interface for creating log entries
10
+ - **LogEntry**: Data structure that captures log messages and metadata
11
+ - **Device**: Abstraction for different output destinations
12
+ - **Formatter**: Handles message formatting and transformation
13
+ - **TagFormatter**: Specialized formatting for tags
14
+ - **Template**: Template engine for customizing log output format
15
+ - **Context**: Thread-local context for managing tags across log entries
16
+ - **Severity**: Log level management and filtering
17
+
18
+ ## Core Architecture
19
+
20
+ ```mermaid
21
+ classDiagram
22
+ class Logger {
23
+ +Device device
24
+ +Formatter formatter
25
+ +TagFormatter tag_formatter
26
+ +Integer level
27
+ +String progname
28
+ +Hash tags
29
+ +initialize(device, options)
30
+ +debug(message, progname, tags)
31
+ +info(message, progname, tags)
32
+ +warn(message, progname, tags)
33
+ +error(message, progname, tags)
34
+ +fatal(message, progname, tags)
35
+ +add_entry(severity, message, progname, tags)
36
+ +tag(tags_hash)
37
+ +flush()
38
+ +close()
39
+ }
40
+
41
+ class LogEntry {
42
+ +Time time
43
+ +Integer severity
44
+ +Object message
45
+ +String progname
46
+ +Integer pid
47
+ +Hash tags
48
+ +initialize(time, severity, message, progname, pid, tags)
49
+ +severity_label()
50
+ +tag(name)
51
+ +to_s()
52
+ }
53
+
54
+ class Device {
55
+ <<abstract>>
56
+ +write(entry)*
57
+ +flush()
58
+ +close()
59
+ +reopen()
60
+ +datetime_format()
61
+ +datetime_format=(format)
62
+ }
63
+
64
+ class Formatter {
65
+ +Hash class_formatters
66
+ +Hash module_formatters
67
+ +add(classes, formatter)
68
+ +remove(classes)
69
+ +format(message)
70
+ +clear()
71
+ }
72
+
73
+ class TagFormatter {
74
+ +Hash formatters
75
+ +Object default_formatter
76
+ +default(formatter)
77
+ +add(names, formatter)
78
+ +remove(names)
79
+ +format(tags)
80
+ +clear()
81
+ }
82
+
83
+ class Template {
84
+ +String first_line_template
85
+ +String additional_line_template
86
+ +String datetime_format
87
+ +compile(template)
88
+ +call(entry)
89
+ +datetime_format=(format)
90
+ }
91
+
92
+ class Context {
93
+ +Hash tags
94
+ +initialize(parent_context)
95
+ +tag(tags)
96
+ +\[](key)
97
+ +\[]=(key, value)
98
+ +reset()
99
+ }
100
+
101
+ class Severity {
102
+ <<module>>
103
+ +level_to_label(severity)
104
+ +label_to_level(label)
105
+ +coerce(value)
106
+ }
107
+
108
+ Logger --> LogEntry : creates
109
+ Logger --> Device : writes to
110
+ Logger --> Formatter : uses
111
+ Logger --> TagFormatter : uses
112
+ Logger --> Severity : includes
113
+ Device --> Template : may use
114
+ Formatter --> LogEntry : formats message
115
+ TagFormatter --> LogEntry : formats tags
116
+ Logger <-- Context : provides tags
117
+ ```
118
+
119
+ ## Device Hierarchy
120
+
121
+ The Device system provides a pluggable architecture for different output destinations:
122
+
123
+ ```mermaid
124
+ classDiagram
125
+ class Device {
126
+ <<abstract>>
127
+ +write(entry)*
128
+ +flush()
129
+ +close()
130
+ +reopen()
131
+ }
132
+
133
+ class Writer {
134
+ +IO stream
135
+ +Template template
136
+ +Buffer buffer
137
+ +Integer buffer_size
138
+ +write(entry)
139
+ +flush()
140
+ +before_flush()
141
+ }
142
+
143
+ class LogFile {
144
+ +String file_path
145
+ +write(entry)
146
+ +reopen(file_path)
147
+ +close()
148
+ }
149
+
150
+ class RollingLogFile {
151
+ <<abstract>>
152
+ +roll_file?()
153
+ +roll_file!()
154
+ +archive_file_suffix()
155
+ }
156
+
157
+ class DateRollingLogFile {
158
+ +String roll
159
+ +roll_file?()
160
+ +archive_file_suffix()
161
+ }
162
+
163
+ class SizeRollingLogFile {
164
+ +Integer max_size
165
+ +Integer keep
166
+ +roll_file?()
167
+ +archive_file_suffix()
168
+ }
169
+
170
+ class Multi {
171
+ +Array~Device~ devices
172
+ +write(entry)
173
+ +flush()
174
+ +close()
175
+ }
176
+
177
+ class Null {
178
+ +write(entry)
179
+ }
180
+
181
+ Device <|-- Writer
182
+ Device <|-- Multi
183
+ Device <|-- Null
184
+ Writer <|-- LogFile
185
+ LogFile <|-- RollingLogFile
186
+ RollingLogFile <|-- DateRollingLogFile
187
+ RollingLogFile <|-- SizeRollingLogFile
188
+ Multi --> Device : contains multiple
189
+ ```
190
+
191
+ ## Data Flow
192
+
193
+ The logging process follows this flow:
194
+
195
+ ```mermaid
196
+ sequenceDiagram
197
+ participant Client
198
+ participant Logger
199
+ participant Formatter
200
+ participant TagFormatter
201
+ participant LogEntry
202
+ participant Device
203
+ participant Template
204
+
205
+ Client->>Logger: info("message", tags: {key: value})
206
+ Logger->>Logger: Check severity level
207
+ Logger->>Formatter: format(message)
208
+ Formatter-->>Logger: formatted_message
209
+ Logger->>TagFormatter: format(tags)
210
+ TagFormatter-->>Logger: formatted_tags
211
+ Logger->>LogEntry: new(time, severity, message, progname, pid, tags)
212
+ LogEntry-->>Logger: log_entry
213
+ Logger->>Device: write(log_entry)
214
+ Device->>Template: call(log_entry) [if Writer device]
215
+ Template-->>Device: formatted_string
216
+ Device->>Device: Write to output destination
217
+ ```
218
+
219
+ ## Key Features
220
+
221
+ ### Thread Safety
222
+ - Logger operations are thread-safe
223
+ - Context provides thread-local tag storage
224
+ - Devices handle concurrent writes appropriately
225
+
226
+ ### Structured Logging
227
+ - LogEntry captures structured data beyond just the message
228
+ - Tags provide key-value metadata
229
+ - Formatters can handle complex object serialization
230
+
231
+ ### Pluggable Architecture
232
+ - Device abstraction allows custom output destinations
233
+ - Formatter system enables custom message transformation
234
+ - TagFormatter provides specialized tag handling
235
+
236
+ ### Performance Optimization
237
+ - Buffered writing in Writer devices
238
+ - Lazy evaluation of expensive operations
239
+ - Configurable flush intervals
240
+
241
+ ### ActiveSupport Compatibility
242
+ - TaggedLoggerSupport module provides Rails compatibility
243
+ - Compatible API with standard library Logger
244
+ - Supports ActiveSupport::TaggedLogging interface
data/CHANGELOG.md CHANGED
@@ -4,9 +4,55 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 1.3.0
8
+
9
+ ### Added
10
+
11
+ - Added `Lumberjack::Formatter::TaggedMessage` to allow extracting tags from log messages via a formatter in order to better support structured logging of objects.
12
+ - Added built in `:round` formatter to round numbers to a specified number of decimal places.
13
+ - Added built in `:redact` formatter to redact sensitive information from log tags.
14
+ - Added support in `Lumberjack::TagFormatter` for class formatters. Class formatters will be applied to any tag values that match the class.
15
+ - Apply formatters to enumerable values in tags. Name formatters are applied using dot syntax when a tag value contains a hash.
16
+ - Added support for a dedicated message formatter that can override the default formatter on the log message.
17
+ - Added support for setting tags from the request environment in `Lumberjack::Rack::Context` middleware.
18
+ - Added helper methods to generate global PID's and thread ids.
19
+ - Added `Lumberjack::Logger#tag_globally` to explicitly set a global tag for all loggers.
20
+ - Added `Lumberjack::Logger#tag_value` to get the value of a tag by name from the current tag context.
21
+ - Added `Lumberjack::Utils.hostname` to get the hostname in UTF-8 encoding.
22
+ - Added `Lumberjack::Utils.global_pid` to get a global process id in a consistent format.
23
+ - Added `Lumberjack::Utils.global_thread_id` to get a thread id in a consistent format.
24
+ - Added `Lumberjack::Utils.thread_name` to get a thread name in a consistent format.
25
+ - Added support for `ActiveSupport::Logging.logger_outputs_to?` to check if a logger is outputting to a specific IO stream.
26
+ - Added `Lumberjack::Logger#log_at` method to temporarily set the log level for a block of code for compatibility with ActiveSupport loggers.
27
+
28
+ ### Changed
29
+
30
+ - Default date/time format for log entries is now ISO-8601 with microsecond precision.
31
+ - Tags that are set to hash values will now be flattened into dot-separated keys in templates.
32
+
33
+ ### Removed
34
+
35
+ - Removed support for Ruby versions < 2.5.
36
+
37
+ ### Deprecated
38
+
39
+ - All unit of work related functionality from version 1.0 has been officially deprecated and will be removed in version 2.0. Use tags instead to set a global context for log entries.
40
+ - Calling `Lumberjack::Logger#tag` without a block is deprecated. Use `Lumberjack::Logger#tag_globally` instead.
41
+
42
+ ## 1.2.10
43
+
44
+ ### Added
45
+
46
+ - Added `with_level` method for compatibility with the latest standard library logger gem.
47
+
48
+ ### Fixed
49
+
50
+ - Fixed typo in magic frozen string literal comments. (thanks @andyw8 and @steveclarke)
51
+
7
52
  ## 1.2.9
8
53
 
9
54
  ### Added
55
+
10
56
  - Allow passing in formatters as class names when adding them.
11
57
  - Allow passing in formatters initialization arguments when adding them.
12
58
  - Add truncate formatter for capping the length of log messages.
@@ -14,54 +60,65 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
14
60
  ## 1.2.8
15
61
 
16
62
  ### Added
63
+
17
64
  - Add `Logger#untagged` to remove previously set logging tags from a block.
18
65
  - Return result of the block when a block is passed to `Logger#tag`.
19
66
 
20
67
  ## 1.2.7
21
68
 
22
69
  ### Fixed
70
+
23
71
  - Allow passing frozen hashes to `Logger#tag`. Tags passed to this method are now duplicated so the logger maintains it's own copy of the hash.
24
72
 
25
73
  ## 1.2.6
26
74
 
27
75
  ### Added
76
+
28
77
  - Add Logger#remove_tag
29
78
 
30
79
  ### Fixed
80
+
31
81
  - Fix `Logger#tag` so it only ads to the current block's logger tags instead of the global tags if called inside a `Logger#tag` block.
32
82
 
33
83
 
34
84
  ## 1.2.5
35
85
 
36
86
  ### Added
87
+
37
88
  - Add support for bang methods (error!) for setting the log level.
38
89
 
39
90
  ### Fixed
91
+
40
92
  - Fixed logic with recursive reference guard in StructuredFormatter so it only suppresses Enumerable references.
41
93
 
42
94
  ## 1.2.4
43
95
 
44
96
  ### Added
97
+
45
98
  - Enhance `ActiveSupport::TaggedLogging` support so code that Lumberjack loggers can be wrapped with a tagged logger.
46
99
 
47
100
  ## 1.2.3
48
101
 
49
102
  ### Fixed
103
+
50
104
  - Fix structured formatter so no-recursive, duplicate references are allowed.
51
105
 
52
106
  ## 1.2.2
53
107
 
54
108
  ### Fixed
109
+
55
110
  - Prevent infinite loops in the structured formatter where objects have backreferences to each other.
56
111
 
57
112
  ## 1.2.1
58
113
 
59
114
  ### Fixed
115
+
60
116
  - Prevent infinite loops where logging a statement triggers the logger.
61
117
 
62
118
  ## 1.2.0
63
119
 
64
120
  ### Added
121
+
65
122
  - Enable compatibility with `ActiveSupport::TaggedLogger` by calling `tagged_logger!` on a logger.
66
123
  - Add `tag_formatter` to logger to specify formatting of tags for output.
67
124
  - Allow adding and removing classes by name to formatters.
@@ -78,11 +135,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
78
135
  ## 1.1.1
79
136
 
80
137
  ### Added
138
+
81
139
  - Replace Procs in tag values with the value of calling the Proc in log entries.
82
140
 
83
141
  ## 1.1.0
84
142
 
85
143
  ### Added
144
+
86
145
  - Change `Lumberjack::Logger` to inherit from ::Logger
87
146
  - Add support for tags on log messages
88
147
  - Add global tag context for all loggers
@@ -96,59 +155,71 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
96
155
  - Add support for modules in formatters
97
156
 
98
157
  ### Removed
158
+
99
159
  - End support for ruby versions < 2.3
100
160
 
101
161
  ## 1.0.13
102
162
 
103
163
  ### Added
164
+
104
165
  - Added `:min_roll_check` option to `Lumberjack::Device::RollingLogFile` to reduce file system checks. Default is now to only check if a file needs to be rolled at most once per second.
105
166
  - Force immutable strings for Ruby versions that support them.
106
167
 
107
168
  ### Changed
169
+
108
170
  - Reduce amount of code executed inside a mutex lock when writing to the logger stream.
109
171
 
110
172
  ## 1.0.12
111
173
 
112
174
  ### Added
175
+
113
176
  - Add support for `ActionDispatch` request id for better Rails compatibility.
114
177
 
115
178
  ## 1.0.11
116
179
 
117
180
  ### Fixed
118
- - Fix Ruby 2.4 deprecation warning on Fixnum (thanks koic).
119
- - Fix gemspec files to be flat array (thanks e2).
181
+
182
+ - Fix Ruby 2.4 deprecation warning on Fixnum (thanks @koic).
183
+ - Fix gemspec files to be flat array (thanks @e2).
120
184
 
121
185
  ## 1.0.10
122
186
 
123
187
  ### Added
188
+
124
189
  - Expose option to manually roll log files.
125
190
 
126
191
  ### Changed
192
+
127
193
  - Minor code cleanup.
128
194
 
129
195
  ## 1.0.9
130
196
 
131
197
  ### Added
198
+
132
199
  - Add method so Formatter is compatible with `ActiveSupport` logging extensions.
133
200
 
134
201
  ## 1.0.8
135
202
 
136
203
  ### Fixed
204
+
137
205
  - Fix another internal variable name conflict with `ActiveSupport` logging extensions.
138
206
 
139
207
  ## 1.0.7
140
208
 
141
209
  ### Fixed
210
+
142
211
  - Fix broken formatter attribute method.
143
212
 
144
213
  ## 1.0.6
145
214
 
146
215
  ### Fixed
216
+
147
217
  - Fix internal variable name conflict with `ActiveSupport` logging extensions.
148
218
 
149
219
  ## 1.0.5
150
220
 
151
221
  ### Changed
222
+
152
223
  - Update docs.
153
224
  - Remove autoload calls to make thread safe.
154
225
  - Make compatible with Ruby 2.1.1 Pathname.
@@ -157,26 +228,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
157
228
  ## 1.0.4
158
229
 
159
230
  ### Added
231
+
160
232
  - Add ability to supply a unit of work id for a block instead of having one generated every time.
161
233
 
162
234
  ## 1.0.3
163
235
 
164
236
  ### Fixed
237
+
165
238
  - Change log file output format to binary to avoid encoding warnings.
166
239
  - Fixed bug in log file rolling that left the file locked.
167
240
 
168
241
  ## 1.0.2
169
242
 
170
243
  ### Fixed
244
+
171
245
  - Remove deprecation warnings under ruby 1.9.3.
172
246
  - Add more error checking around file rolling.
173
247
 
174
248
  ## 1.0.1
175
249
 
176
250
  ### Fixed
251
+
177
252
  - Writes are no longer buffered by default.
178
253
 
179
254
  ## 1.0.0
180
255
 
181
256
  ### Added
257
+
182
258
  - Initial release