lumberjack 1.0.13 → 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +129 -0
  3. data/{MIT_LICENSE → MIT_LICENSE.txt} +0 -0
  4. data/README.md +142 -23
  5. data/VERSION +1 -1
  6. data/lib/lumberjack.rb +70 -22
  7. data/lib/lumberjack/context.rb +35 -0
  8. data/lib/lumberjack/device.rb +22 -8
  9. data/lib/lumberjack/device/date_rolling_log_file.rb +9 -9
  10. data/lib/lumberjack/device/log_file.rb +14 -3
  11. data/lib/lumberjack/device/multi.rb +46 -0
  12. data/lib/lumberjack/device/null.rb +1 -3
  13. data/lib/lumberjack/device/rolling_log_file.rb +45 -21
  14. data/lib/lumberjack/device/size_rolling_log_file.rb +10 -10
  15. data/lib/lumberjack/device/writer.rb +92 -61
  16. data/lib/lumberjack/formatter.rb +97 -28
  17. data/lib/lumberjack/formatter/date_time_formatter.rb +25 -0
  18. data/lib/lumberjack/formatter/exception_formatter.rb +25 -2
  19. data/lib/lumberjack/formatter/id_formatter.rb +23 -0
  20. data/lib/lumberjack/formatter/object_formatter.rb +12 -0
  21. data/lib/lumberjack/formatter/pretty_print_formatter.rb +4 -4
  22. data/lib/lumberjack/formatter/string_formatter.rb +1 -1
  23. data/lib/lumberjack/formatter/strip_formatter.rb +12 -0
  24. data/lib/lumberjack/formatter/structured_formatter.rb +63 -0
  25. data/lib/lumberjack/log_entry.rb +44 -16
  26. data/lib/lumberjack/logger.rb +275 -69
  27. data/lib/lumberjack/rack.rb +3 -2
  28. data/lib/lumberjack/rack/context.rb +18 -0
  29. data/lib/lumberjack/rack/request_id.rb +4 -4
  30. data/lib/lumberjack/rack/unit_of_work.rb +1 -1
  31. data/lib/lumberjack/severity.rb +11 -10
  32. data/lib/lumberjack/tag_formatter.rb +96 -0
  33. data/lib/lumberjack/tagged_logger_support.rb +66 -0
  34. data/lib/lumberjack/tagged_logging.rb +29 -0
  35. data/lib/lumberjack/tags.rb +42 -0
  36. data/lib/lumberjack/template.rb +81 -33
  37. data/lumberjack.gemspec +31 -0
  38. metadata +26 -53
  39. data/Rakefile +0 -40
  40. data/spec/device/date_rolling_log_file_spec.rb +0 -73
  41. data/spec/device/log_file_spec.rb +0 -48
  42. data/spec/device/null_spec.rb +0 -12
  43. data/spec/device/rolling_log_file_spec.rb +0 -151
  44. data/spec/device/size_rolling_log_file_spec.rb +0 -58
  45. data/spec/device/writer_spec.rb +0 -118
  46. data/spec/formatter/exception_formatter_spec.rb +0 -20
  47. data/spec/formatter/inspect_formatter_spec.rb +0 -13
  48. data/spec/formatter/pretty_print_formatter_spec.rb +0 -14
  49. data/spec/formatter/string_formatter_spec.rb +0 -12
  50. data/spec/formatter_spec.rb +0 -45
  51. data/spec/log_entry_spec.rb +0 -69
  52. data/spec/logger_spec.rb +0 -411
  53. data/spec/lumberjack_spec.rb +0 -29
  54. data/spec/rack/request_id_spec.rb +0 -48
  55. data/spec/rack/unit_of_work_spec.rb +0 -26
  56. data/spec/severity_spec.rb +0 -23
  57. data/spec/spec_helper.rb +0 -32
  58. data/spec/template_spec.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: aafe117d91082b575618e962e3d66a0b6d3c81b4
4
- data.tar.gz: a4d32d48a82b15e8d67e0e00ab3b3637a63b7e99
2
+ SHA256:
3
+ metadata.gz: c7912cf1bfe32dcaa911a6a65a0b755fb3051eebc2a7e4a65ff5d422f2f61ad7
4
+ data.tar.gz: b4077d2ef97be7169ed0e7bca7d107ec3f42372dde45cae1e7cdcedae1fb4e61
5
5
  SHA512:
6
- metadata.gz: 33d8f2e2e386edad724394264f76c33c17e3df6d9dd394b3444a7abebe12d5e93d3ce8a88726e8b67fcfb2c279615741a9e55b9112d5ec45e50e0c139f481a36
7
- data.tar.gz: 129825a3150dad02aecde16130974c2add346fe27d6455e0ea22d6616d6e766306af8c7123ef10ec7e51ca81f06e7a6f1d0cd573abd7566f07b1b15efeed415a
6
+ metadata.gz: a092775aec0c7670eda8ff4959a7cc928a57b0934ecc8a1190efe395b437bc0a681bdbd2f3455b98f3cf757904f5f39b31c96e24e9c8bcd7a481b806027e92c8
7
+ data.tar.gz: 885f76da2738f3f6236a363d9a7dea68f83a80a03e123a3c52c578984f963e959de6fd60d0fd222d9a9933c22ed959181538abb4118163c8fd6528292e88673c
@@ -0,0 +1,129 @@
1
+ ## 1.2.8
2
+
3
+ * Add `Logger#untagged` to remove previously set logging tags from a block.
4
+ * Return result of the block when a block is passed to `Logger#tag`.
5
+
6
+ ## 1.2.7
7
+
8
+ * 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.
9
+
10
+ ## 1.2.6
11
+
12
+ * 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.
13
+ * Add Logger#remove_tag
14
+
15
+ ## 1.2.5
16
+
17
+ * Fix logic with recursive reference guard in StructuredFormatter so it only suppresses Enumerable references.
18
+ * Add support for bang methods (error!) for setting the log level.
19
+
20
+ ## 1.2.4
21
+
22
+ * Enhance `ActiveSupport::TaggedLogging` support so code that Lumberjack loggers can be wrapped with a tagged logger.
23
+
24
+ ## 1.2.3
25
+
26
+ * Fix structured formatter so no-recursive, duplicate references are allowed.
27
+
28
+ ## 1.2.2
29
+
30
+ * Prevent infinite loops in the structured formatter where objects have backreferences to each other.
31
+
32
+ ## 1.2.1
33
+
34
+ * Prevent infinite loops where logging a statement triggers the logger.
35
+
36
+ ## 1.2.0
37
+
38
+ * Enable compatibility with `ActiveSupport::TaggedLogger` by calling `tagged_logger!` on a logger.
39
+ * Add `tag_formatter` to logger to specify formatting of tags for output.
40
+ * Allow adding and removing classes by name to formatters.
41
+ * Allow adding and removing multiple classes in a single call to a formatter.
42
+ * Allow using symbols and strings as log level for silencing a logger.
43
+ * Ensure flusher thread gets stopped when logger is closed.
44
+ * Add writer for logger device attribute.
45
+ * Handle passing an array of devices to a multi device.
46
+ * Helper method to get a tag with a specified name.
47
+ * Add strip formatter to strip whitespace from strings.
48
+ * Support non-alpha numeric characters in template variables.
49
+ * Add backtrace cleaner to ExceptionFormatter.
50
+
51
+ ## 1.1.1
52
+
53
+ * Replace Procs in tag values with the value of calling the Proc in log entries.
54
+
55
+ ## 1.1.0
56
+
57
+ * Change `Lumberjack::Logger` to inherit from ::Logger
58
+ * Add support for tags on log messages
59
+ * Add global tag context for all loggers
60
+ * Add per logger tags and tag contexts
61
+ * Reimplement unit of work id as a tag on log entries
62
+ * Add support for setting datetime format on log devices
63
+ * Performance optimizations
64
+ * Add Multi device to output to multiple devices
65
+ * Add `DateTimeFormatter`, `IdFormatter`, `ObjectFormatter`, and `StructuredFormatter`
66
+ * Add rack `Context` middleware for setting thread global context
67
+ * End support for ruby versions < 2.3
68
+ * Add support for modules in formatters
69
+
70
+ ## 1.0.13
71
+
72
+ * Reduce amount of code executed inside a mutex lock when writing to the logger stream.
73
+ * 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.
74
+ * Force immutable strings for Ruby versions that support them.
75
+
76
+ ## 1.0.12
77
+
78
+ * Add support for `ActionDispatch` request id for better Rails compatibility.
79
+
80
+ ## 1.0.11
81
+
82
+ * Fix Ruby 2.4 deprecation warning on Fixnum (thanks koic).
83
+ * Fix gemspec files to be flat array (thanks e2).
84
+
85
+ ## 1.0.10
86
+
87
+ * Expose option to manually roll log files.
88
+ * Minor code cleanup.
89
+
90
+ ## 1.0.9
91
+
92
+ * Add method so Formatter is compatible with `ActiveSupport` logging extensions.
93
+
94
+ ## 1.0.8
95
+
96
+ * Fix another internal variable name conflict with `ActiveSupport` logging extensions.
97
+
98
+ ## 1.0.7
99
+
100
+ * Fix broken formatter attribute method.
101
+
102
+ ## 1.0.6
103
+
104
+ * Fix internal variable name conflict with `ActiveSupport` logging extensions.
105
+
106
+ ## 1.0.5
107
+
108
+ * Update docs.
109
+ * Remove autoload calls to make thread safe.
110
+ * Make compatible with Ruby 2.1.1 Pathname.
111
+ * Make compatible with standard library Logger's use of progname as default message.
112
+
113
+ ## 1.0.4
114
+
115
+ * Add ability to supply a unit of work id for a block instead of having one generated every time.
116
+
117
+ ## 1.0.3
118
+
119
+ * Change log file output format to binary to avoid encoding warnings.
120
+ * Fixed bug in log file rolling that left the file locked.
121
+
122
+ ## 1.0.2
123
+
124
+ * Remove deprecation warnings under ruby 1.9.3.
125
+ * Add more error checking around file rolling.
126
+
127
+ ## 1.0.1
128
+
129
+ * Writes are no longer buffered by default.
File without changes
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ ![Continuous Integration](https://github.com/bdurand/lumberjack/workflows/Continuous%20Integration/badge.svg)
2
+ [![Maintainability](https://api.codeclimate.com/v1/badges/a0abc03721fff9b0cde1/maintainability)](https://codeclimate.com/github/bdurand/lumberjack/maintainability)
3
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
4
+
1
5
  # Lumberjack
2
6
 
3
7
  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.
@@ -33,21 +37,77 @@ The following information is recorded for each message:
33
37
  * time - The time at which the message was recorded.
34
38
  * program name - The name of the program logging the message. This can be either set for all messages or customized with each message.
35
39
  * process id - The process id (pid) of the process that logged the message.
36
- * unit of work id - The unique 12 byte hexadecimal number generated for a unit of work.
40
+ * tags - An map of name value pairs for addition information about the log context.
41
+
42
+ ### Tags
37
43
 
38
- ### Units Of Work
44
+ You can use tags to provide additional meta data about a log message or the context that the log message is being made in. Using tags can keep you log messages clean. You can avoid string interoplation to add additional meta data.
39
45
 
40
- A unit of work can be used to tie together all log messages within a block. This can be very useful to isolate a group of messages that represent one path through the system. For instance, in a web application, a single request represents a natural unit of work, and when you are looking through a log file, it is useful to see the entire set of log entries as a unit instead of interspersed with messages from other concurrent requests.
46
+ Each of the logger methods includes an additional argument that can be used to specify tags on a messsage:
41
47
 
42
48
  ```ruby
43
- # All log entries in this block will get a common unit of work id.
44
- Lumberjack.unit_of_work do
45
- logger.info("Begin request")
46
- yield
47
- logger.info("End request")
48
- end
49
+ logger.info("request completed", duration: elapsed_time, status: response.status)
50
+ ```
51
+
52
+ You can also specify tags on a logger that will be included with every log message.
53
+
54
+ ```ruby
55
+ logger.tag(host: Socket.gethostname)
56
+ ```
57
+
58
+ You can specify tags that will only be applied to the logger in a block as well.
59
+
60
+ ```ruby
61
+ logger.tag(thread_id: Thread.current.object_id) do
62
+ logger.info("here") # Will include the `thread_id` tag
63
+ logger.tag(count: 15)
64
+ logger.info("with count") # Will include the `count` tag
65
+ end
66
+ logger.info("there") # Will not include the `thread_id` or `count` tag
67
+ ```
68
+
69
+ You can also set tags to `Proc` objects that will be evaluated when creating a log entry.
70
+
71
+ ```ruby
72
+ logger.tag(thread_id: lambda { Thread.current.object_id })
73
+ Thread.new do
74
+ logger.info("inside thread") # Will include the `thread_id` tag with id of the spawned thread
75
+ end
76
+ logger.info("outside thread") # Will include the `thread_id` tag with id of the main thread
77
+ ```
78
+
79
+ Finally, you can specify a logging context with tags that apply within a block to all loggers.
80
+
81
+ ```ruby
82
+ Lumberjack.context do
83
+ Lumberjack.tag(request_id: SecureRandom.hex)
84
+ logger.info("begin request") # Will include the `request_id` tag
85
+ end
86
+ logger.info("no requests") # Will not include the `request_id` tag
87
+ ```
88
+
89
+ Tag keys are always converted to strings. Tags are inherited so that message tags take precedence over block tags which take precedence over global tags.
90
+
91
+ #### Compatibility with ActiveSupport::TaggedLogging
92
+
93
+ `Lumberjack::Logger` version 1.1.2 or greater is compatible with `ActiveSupport::TaggedLogging`. This is so that other code that expect to have a logger that responds to the `tagged` method will work. Any tags added with the `tagged` method will be appended to an array in the the "tagged" tag.
94
+
95
+ ```ruby
96
+ logger.tagged("foo", "bar=1", "other") do
97
+ logger.info("here") # will include tags: {"tagged" => ["foo", "bar=1", "other"]}
98
+ end
49
99
  ```
50
100
 
101
+ #### Templates
102
+
103
+ The built in `Lumberjack::Device::Writer` class has built in support for including tags in the output using the `Lumberjack::Template` class.
104
+
105
+ You can specify any tag name you want in a template as well as the `:tags` macro for all tags. If a tag name has been used as it's own macro, it will not be included in the `:tags` macro.
106
+
107
+ #### Unit Of Work
108
+
109
+ Lumberjack 1.0 had a concept of a unit of work id that could be used to tie log messages together. This has been replaced by tags. There is still an implementation of `Lumberjack.unit_of_work`, but it is just a wrapper on the tag implementation.
110
+
51
111
  ### Pluggable Devices
52
112
 
53
113
  When a Logger logs a LogEntry, it sends it to a Lumberjack::Device. Lumberjack comes with a variety of devices for logging to IO streams or files.
@@ -56,27 +116,74 @@ When a Logger logs a LogEntry, it sends it to a Lumberjack::Device. Lumberjack c
56
116
  * Lumberjack::Device::LogFile - Writes log entries to a file.
57
117
  * Lumberjack::Device::DateRollingLogFile - Writes log entries to a file that will automatically roll itself based on date.
58
118
  * Lumberjack::Device::SizeRollingLogFile - Writes log entries to a file that will automatically roll itself based on size.
119
+ * Lumberjack::Device::Multi - This device wraps mulitiple other devices and will write log entries to each of them.
59
120
  * Lumberjack::Device::Null - This device produces no output and is intended for testing environments.
60
121
 
61
122
  If you'd like to send you log to a different kind of output, you just need to extend the Device class and implement the +write+ method. Or check out these plugins:
62
123
 
63
124
  * [lumberjack_syslog_device](https://github.com/bdurand/lumberjack_syslog_device) - send your log messages to the system wide syslog service
64
- * [lumberjack_multi-device](https://github.com/astevens/lumberjack_multi-device) - send log messages to multiple devices
65
125
  * [lumberjack_mongo_device](https://github.com/bdurand/lumberjack_mongo_device) - store your log messages to a [MongoDB](http://www.mongodb.org/) NoSQL data store
66
126
  * [lumberjack-couchdb-driver](https://github.com/narkisr/lumberjack-couchdb-driver) - store your log messages to a [CouchDB](http://couchdb.apache.org/) NoSQL data store
67
127
  * [lumberjack_heroku_device](https://github.com/tonycoco/lumberjack_heroku_device) - log to Heroku's logging system
68
128
 
69
129
  ### Customize Formatting
70
130
 
71
- When a message is logged, it is first converted into a string. You can customize how it is converted by adding mappings to a Formatter.
131
+ #### Formatters
132
+
133
+ The message you send to the logger can be any object type and does not need to be a string. You can specify a `Lumberjack::Formatter` to instruct the logger how to format objects before outputting them to the device. You do this by mapping classes or modules to formatter code. This code can be either a block or an object that responds to the `call` method. The formatter will be called with the object logged as the message and the returned value will be what is sent to the device.
134
+
135
+ ```ruby
136
+ # Format all floating point number with three significant digits.
137
+ logger.formatter.add(Float) { |value| value.round(3) }
138
+
139
+ # Format all enumerable objects as a comma delimited string.
140
+ logger.formatter.add(Enumerable) { |value| value.join(", ") }
141
+ ```
142
+
143
+ There are several built in classes you can add as formatters. You can use a symbol to reference built in formatters.
72
144
 
73
145
  ```ruby
74
146
  logger.formatter.add(Hash, :pretty_print) # use the Formatter::PrettyPrintFormatter for all Hashes
75
- logger.formatter.add(MyClass){|obj| "#{obj.class}@#{obj.id}"} # use a block to provide a custom format
147
+ logger.formatter.add(Hash, Lumberjack::Formatter::PrettyPrintFormatter.new) # alternative using a formatter instance
148
+ ```
149
+
150
+ * `:object` - `Lumberjack::Formatter::ObjectFormatter` - no op conversion that returns the object itself.
151
+ * `:string` - `Lumberjack::Formatter::StringFormatter` - calls `to_s` on the object.
152
+ * `:strip` - `Lumberjack::Formatter::StripFormatter` - calls `to_s.strip` on the object.
153
+ * `:inspect` - `Lumberjack::Formatter::InspectFormatter` - calls `inspect` on the object.
154
+ * `:exception` - `Lumberjack::Formatter::ExceptionFormatter` - special formatter for exceptions which logs them as multi line statements with the message and backtrace.
155
+ * `:date_time` - `Lumberjack::Formatter::DateTimeFormatter` - special formatter for dates and times to format them using `strftime`.
156
+ * `:pretty_print` - `Lumberjack::Formatter::PrettyPrintFormatter` - returns the pretty print format of the object.
157
+ * `:id` - `Lumberjack::Formatter::IdFormatter` - returns a hash of the object with keys for the id attribute and class.
158
+ * `:structured` - `Lumberjack::Formatter::StructuredFormatter` - crawls the object and applies the formatter recursively to Enumerable objects found in it (arrays, hashes, etc.).
159
+
160
+ To define your own formatter, either provide a block or an object that responds to `call` with a single argument.
161
+
162
+ The default formatter will pass through values for strings, numbers, and booleans, and use the `:inspect` formatter for all objects except for exceptions which will be formatted with the `:exception` formatter.
163
+
164
+ #### Tag Formatters
165
+
166
+ The `logger.formatter` will only apply to log messages. You can use `logger.tag_formatter` to register formatters for tags. You can register both default formatters that will apply to all tag values, as well as tag specifice formatters that will apply only to objects with a specific tag name.
167
+
168
+ The fomatter values can be either a `Lumberjack::Formatter` or a block or an object that responds to `call`. If you supply a `Lumberjack::Formatter`, the tag value will be passed through the rules for that formatter. If you supply a block or other object, it will be called with the tag value.
169
+
170
+ ```ruby
171
+ # These will all do the same thing formatting all tag values with `inspect`
172
+ logger.tag_formatter.default(Lumberjack::Formatter.new.clear.add(Object, :inspect))
173
+ logger.tag_formatter.default(Lumberjack::Formatter::InspectFormatter.new)
174
+ logger.tag_formatter.default { |value| value.inspect }
175
+
176
+ # This will register formatters only on specific tag names
177
+ logger.tag_formatter.add(:thread) { |thread| "Thread(#{thread.name})" }
178
+ logger.tag_formatter.add(:current_user, Lumberjack::Formatter::IdFormatter.new)
76
179
  ```
77
180
 
78
- If you use the built in devices, you can also customize the Template used to format the LogEntry.
79
-
181
+ #### Templates
182
+
183
+ If you use the built in `Lumberjack::Writer` derived devices, you can also customize the Template used to format the LogEntry.
184
+
185
+ See `Lumberjack::Template` for a complete list of macros you can use in the template. You can also use a block that receives a `Lumberjack::LogEntry` as a template.
186
+
80
187
  ```ruby
81
188
  # Change the format of the time in the log
82
189
  Lumberjack::Logger.new("application.log", :time_format => "%m/%d/%Y %H:%M:%S")
@@ -84,23 +191,27 @@ If you use the built in devices, you can also customize the Template used to for
84
191
  # Use a simple template that only includes the time and the message
85
192
  Lumberjack::Logger.new("application.log", :template => ":time - :message")
86
193
 
194
+ # Use a simple template that includes tags, but handles the `duration` tag separately.
195
+ # All tags will appear at the end of the message except for `duration` which will be at the beginning.
196
+ Lumberjack::Logger.new("application.log", :template => ":time (:duration) - :message - :tags")
197
+
87
198
  # Use a custom template as a block that only includes the first character of the severity
88
199
  template = lambda{|e| "#{e.severity_label[0, 1]} #{e.time} - #{e.message}"}
89
200
  Lumberjack::Logger.new("application.log", :template => template)
90
201
  ```
91
202
 
92
- ### Buffered Performance
203
+ ### Buffered Logging
93
204
 
94
- The logger has hooks for devices that support buffering to increase performance by batching physical writes. Log entries are not guaranteed to be written until the Lumberjack::Logger#flush method is called.
205
+ The logger has hooks for devices that support buffering to potentially increase performance by batching physical writes. Log entries are not guaranteed to be written until the Lumberjack::Logger#flush method is called. Buffering can improve performance if I/O is slow or there high overhead writing to the log device.
95
206
 
96
- You can use the <tt>:flush_seconds</tt> option on the logger to periodically flush the log. This is usually a good idea so you can more easily debug hung processes. Without periodic flushing, a process that hangs may never write anything to the log because the messages are sitting in a buffer. By turning on periodic flushing, the logged messages will be written which can greatly aid in debugging the problem.
207
+ You can use the `:flush_seconds` option on the logger to periodically flush the log. This is usually a good idea so you can more easily debug hung processes. Without periodic flushing, a process that hangs may never write anything to the log because the messages are sitting in a buffer. By turning on periodic flushing, the logged messages will be written which can greatly aid in debugging the problem.
97
208
 
98
- The built in stream based logging devices use an internal buffer. The size of the buffer (in bytes) can be set with the <tt>:buffer_size</tt> options when initializing a logger. The default behavior is to not to buffer.
209
+ The built in stream based logging devices use an internal buffer. The size of the buffer (in bytes) can be set with the `:buffer_size` options when initializing a logger. The default behavior is to not to buffer.
99
210
 
100
211
  ```ruby
101
212
  # Set buffer to flush after 8K has been written to the log.
102
213
  logger = Lumberjack::Logger.new("application.log", :buffer_size => 8192)
103
-
214
+
104
215
  # Turn off buffering so entries are immediately written to disk.
105
216
  logger = Lumberjack::Logger.new("application.log", :buffer_size => 0)
106
217
  ```
@@ -111,6 +222,14 @@ The built in devices include two that can automatically roll log files based eit
111
222
 
112
223
  There is a similar feature in the standard library Logger class, but the implementation here is safe to use with multiple processes writing to the same log file.
113
224
 
225
+ ## Difference Standard Library Logger
226
+
227
+ `Lumberjack::Logger` does not extend from the `Logger` class in the standard library, but it does implement a compantible API. The main difference is in the flow of how messages are ultimately sent to devices for output.
228
+
229
+ The standard library Logger logic converts the log entries to strings and then sends the string to the device to be written to a stream. Lumberjack, on the other hand, sends structured data in the form of a `Lumberjack::LogEntry` to the device and lets the device worry about how to format it. The reason for this flip is to better support structured data logging. Devices (even ones that write to streams) can format the entire payload including non-string objects and tags however they need to.
230
+
231
+ The logging methods (`debug`, 'info', 'warn', 'error', 'fatal') are overloaded with an additional argument for setting tags on the log entry.
232
+
114
233
  ## Examples
115
234
 
116
235
  These example are for Rails applications, but there is no dependency on Rails for using this gem. Most of the examples are applicable to any Ruby application.
@@ -139,17 +258,17 @@ To set up a logger to roll log files when they get to 100Mb, you could use this:
139
258
  ```ruby
140
259
  config.logger = Lumberjack::Logger.new(log_file_path, :max_size => 100.megabytes)
141
260
  ```
142
-
261
+
143
262
  To change the log message format, you could use this code:
144
263
 
145
264
  ```ruby
146
265
  config.logger = Lumberjack::Logger.new(log_file_path, :template => ":time - :message")
147
266
  ```
148
267
 
149
- To change the log message format to output JSON, you could use this code (this example requires the multi-json gem):
150
-
268
+ To change the log message format to output JSON, you could use this code:
269
+
151
270
  ```ruby
152
- config.logger = Lumberjack::Logger.new(log_file_path, :template => lambda{|e| MultiJson.dump(e)})
271
+ config.logger = Lumberjack::Logger.new(log_file_path, :template => lambda{|e| JSON.dump(time: e.time, level: e.severity_label, message: e.message)})
153
272
  ```
154
273
 
155
274
  To send log messages to syslog instead of to a file, you could use this (require the lumberjack_syslog_device gem):
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.13
1
+ 1.2.8
@@ -1,21 +1,27 @@
1
1
  # frozen_string_literals: true
2
2
 
3
- require 'rbconfig'
4
- require 'time'
5
- require 'thread'
6
- require 'securerandom'
3
+ require "rbconfig"
4
+ require "time"
5
+ require "securerandom"
6
+ require "logger"
7
7
 
8
8
  module Lumberjack
9
- LINE_SEPARATOR = (RbConfig::CONFIG['host_os'].match(/mswin/i) ? "\r\n" : "\n")
10
-
11
- require File.expand_path("../lumberjack/severity.rb", __FILE__)
12
- require File.expand_path("../lumberjack/log_entry.rb", __FILE__)
13
- require File.expand_path("../lumberjack/formatter.rb", __FILE__)
14
- require File.expand_path("../lumberjack/device.rb", __FILE__)
15
- require File.expand_path("../lumberjack/logger.rb", __FILE__)
16
- require File.expand_path("../lumberjack/template.rb", __FILE__)
17
- require File.expand_path("../lumberjack/rack.rb", __FILE__)
18
-
9
+ LINE_SEPARATOR = (RbConfig::CONFIG["host_os"] =~ /mswin/i ? "\r\n" : "\n")
10
+
11
+ require_relative "lumberjack/severity"
12
+ require_relative "lumberjack/formatter"
13
+
14
+ require_relative "lumberjack/context"
15
+ require_relative "lumberjack/log_entry"
16
+ require_relative "lumberjack/device"
17
+ require_relative "lumberjack/logger"
18
+ require_relative "lumberjack/tags"
19
+ require_relative "lumberjack/tag_formatter"
20
+ require_relative "lumberjack/tagged_logger_support"
21
+ require_relative "lumberjack/tagged_logging"
22
+ require_relative "lumberjack/template"
23
+ require_relative "lumberjack/rack"
24
+
19
25
  class << self
20
26
  # Define a unit of work within a block. Within the block supplied to this
21
27
  # method, calling +unit_of_work_id+ will return the same value that can
@@ -27,19 +33,61 @@ module Lumberjack
27
33
  # For the common use case of treating a single web request as a unit of work, see the
28
34
  # Lumberjack::Rack::UnitOfWork class.
29
35
  def unit_of_work(id = nil)
30
- save_val = Thread.current[:lumberjack_logger_unit_of_work_id]
31
36
  id ||= SecureRandom.hex(6)
32
- Thread.current[:lumberjack_logger_unit_of_work_id] = id
33
- begin
34
- return yield
35
- ensure
36
- Thread.current[:lumberjack_logger_unit_of_work_id] = save_val
37
+ context do
38
+ context[:unit_of_work_id] = id
39
+ yield
37
40
  end
38
41
  end
39
-
42
+
40
43
  # Get the UniqueIdentifier for the current unit of work.
41
44
  def unit_of_work_id
42
- Thread.current[:lumberjack_logger_unit_of_work_id]
45
+ context[:unit_of_work_id]
46
+ end
47
+
48
+ # Contexts can be used to store tags that will be attached to all log entries in the block.
49
+ #
50
+ # If this method is called with a block, it will set a logging context for the scope of a block.
51
+ # If there is already a context in scope, a new one will be created that inherits
52
+ # all the tags of the parent context.
53
+ #
54
+ # Otherwise, it will return the current context. If one doesn't exist, it will return a new one
55
+ # but that context will not be in any scope.
56
+ def context(&block)
57
+ current_context = Thread.current[:lumberjack_context]
58
+ if block
59
+ use_context(Context.new(current_context), &block)
60
+ else
61
+ current_context || Context.new
62
+ end
63
+ end
64
+
65
+ # Set the context to use within a block.
66
+ def use_context(context, &block)
67
+ current_context = Thread.current[:lumberjack_context]
68
+ begin
69
+ Thread.current[:lumberjack_context] = (context || Context.new)
70
+ yield
71
+ ensure
72
+ Thread.current[:lumberjack_context] = current_context
73
+ end
74
+ end
75
+
76
+ # Return true if inside a context block.
77
+ def context?
78
+ !!Thread.current[:lumberjack_context]
79
+ end
80
+
81
+ # Return the tags from the current context or nil if there are no tags.
82
+ def context_tags
83
+ context = Thread.current[:lumberjack_context]
84
+ context&.tags
85
+ end
86
+
87
+ # Set tags on the current context
88
+ def tag(tags)
89
+ context = Thread.current[:lumberjack_context]
90
+ context&.tag(tags)
43
91
  end
44
92
  end
45
93
  end