lumberjack 1.2.10 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5ab13ef762e8cdcb989ce1937c117fdbf938edc723c48f338b74edcd5d8e776
4
- data.tar.gz: a003d08ef71531551083e4794807d3469fd9691abdc0686e5cc36e6859199922
3
+ metadata.gz: c72bca9355bd37fb691a06a4cea4a341b6905b7b5c15429d41061b2b0afd3813
4
+ data.tar.gz: 49a18195fadf1de9b2cf43e3ce95c1f5e49d3d81dd4384a722e8f685187f6bbc
5
5
  SHA512:
6
- metadata.gz: b0b527513bd37ca507bfe63c83cd00831f544a9ecdcedc13aeb566a3e74ae4ff0469eefed220da79c7cbeb385aa0fcff249b2480d74c95a1ff21899a8e723afb
7
- data.tar.gz: 109411706ed4976f9711d6fcc17dd93bd7700cf72e01f40eaadba5701284e4175aa3791a311a19ab78eaedc34270ff9b16cd4ca394bb01a90b6c29d8e295f8e0
6
+ metadata.gz: 5d58e6244cad6396bf702759c05a130e279d4def0d7bee491817b373fbee79420fa0df776264485e7387657a7dd28bab7e4690b7b0a677d878b98f611432a7f7
7
+ data.tar.gz: d2c2c8f1765230b39df298c68c89bad1db520acbaabfee7da7381d75336de91ff9c3f709e501683fb2502f6b5f7b61eef89c8814f13fda6c2235c3ac43ef5959
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,6 +4,90 @@ 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.4.0
8
+
9
+ ### Changed
10
+
11
+ - Tags are consistently flattened internally to dot notation keys. This makes tag handling more consistent when using nested hashes as tag values. This changes how nested tags are merged, though. Now when new nested tags are set they will be merged into the existing tags rather than replacing them entirely. So `logger.tag(foo: {bar: "baz"})` will now merge the `foo.bar` tag into the existing tags rather than replacing the entire `foo` tag.
12
+ - The `Lumberjack::Logger#context` method can now be called without a block. When called with a block it sets up a new tag context for the block. When called without a block, it returns the current tag context in a `Lumberjack::TagContext` object which can be used to add tags to the current context.
13
+ - Tags in `Lumberjack::LogEntry` are now always stored as a hash of flattened keys. This means that when tags are set on a log entry, they will be automatically flattened to dot notation keys. The `tag` method will return a hash of sub-tags if the tag name is a tag prefix.
14
+
15
+ ### Added
16
+
17
+ - Added `Lumberjack::LogEntry#nested_tags` method to return the tags as a nested hash structure.
18
+
19
+ ## 1.3.4
20
+
21
+ ### Added
22
+
23
+ - Added `Lumberjack::Logger#with_progname` alias for `set_progname` to match the naming convention used for setting temporary levels.
24
+
25
+ ### Fixed
26
+
27
+ - Ensure that the safety check for circular calls to `Lumberjack::Logger#add_entry` cannot lose state.
28
+
29
+ ## 1.3.3
30
+
31
+ ### Added
32
+
33
+ - Added `Lumberjack::Utils#expand_tags` method to expand a hash of tags that may contain nested hashes or dot notation keys.
34
+
35
+ ### Changed
36
+
37
+ - Updated `Lumberjack::Utils#flatten_tags` to convert all keys to strings.
38
+
39
+ ## 1.3.2
40
+
41
+ ### Fixed
42
+
43
+ - Fixed `NoMethodError` when setting the device via the `Lumberjack::Logger#device=` method.
44
+
45
+ ## 1.3.1
46
+
47
+ ### Added
48
+
49
+ - Added `Lumberjack::Logger#context` method to set up a context block for the logger. This is the same as calling `Lumberjack::Logger#tag` with an empty hash.
50
+ - Log entries now remove empty tag values so they don't have to be removed downstream.
51
+
52
+ ### Fixed
53
+
54
+ - ActiveSupport::TaggedLogger now calls `Lumberjack::Logger#tag_globally` to prevent deprecation warnings.
55
+
56
+ ## 1.3.0
57
+
58
+ ### Added
59
+
60
+ - Added `Lumberjack::Formatter::TaggedMessage` to allow extracting tags from log messages via a formatter in order to better support structured logging of objects.
61
+ - Added built in `:round` formatter to round numbers to a specified number of decimal places.
62
+ - Added built in `:redact` formatter to redact sensitive information from log tags.
63
+ - Added support in `Lumberjack::TagFormatter` for class formatters. Class formatters will be applied to any tag values that match the class.
64
+ - Apply formatters to enumerable values in tags. Name formatters are applied using dot syntax when a tag value contains a hash.
65
+ - Added support for a dedicated message formatter that can override the default formatter on the log message.
66
+ - Added support for setting tags from the request environment in `Lumberjack::Rack::Context` middleware.
67
+ - Added helper methods to generate global PID's and thread ids.
68
+ - Added `Lumberjack::Logger#tag_globally` to explicitly set a global tag for all loggers.
69
+ - Added `Lumberjack::Logger#tag_value` to get the value of a tag by name from the current tag context.
70
+ - Added `Lumberjack::Utils.hostname` to get the hostname in UTF-8 encoding.
71
+ - Added `Lumberjack::Utils.global_pid` to get a global process id in a consistent format.
72
+ - Added `Lumberjack::Utils.global_thread_id` to get a thread id in a consistent format.
73
+ - Added `Lumberjack::Utils.thread_name` to get a thread name in a consistent format.
74
+ - Added support for `ActiveSupport::Logging.logger_outputs_to?` to check if a logger is outputting to a specific IO stream.
75
+ - Added `Lumberjack::Logger#log_at` method to temporarily set the log level for a block of code for compatibility with ActiveSupport loggers.
76
+
77
+ ### Changed
78
+
79
+ - Default date/time format for log entries is now ISO-8601 with microsecond precision.
80
+ - Tags that are set to hash values will now be flattened into dot-separated keys in templates.
81
+
82
+ ### Removed
83
+
84
+ - Removed support for Ruby versions < 2.5.
85
+
86
+ ### Deprecated
87
+
88
+ - 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.
89
+ - Calling `Lumberjack::Logger#tag` without a block is deprecated. Use `Lumberjack::Logger#tag_globally` instead.
90
+
7
91
  ## 1.2.10
8
92
 
9
93
  ### Added