cogger 0.6.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2ff34be63a6d20792b0dad16762afaf0f03226964b2a83ed08194fef2f37a75
4
- data.tar.gz: 5fce7ffb39529c8d4c29f10a03d29e3173219f0365428fa10d003501c38a2553
3
+ metadata.gz: 3226b0b30d4c6a4eba83e9aec637de1938ac852f8a7e1bbd3b4a07d501d67920
4
+ data.tar.gz: 4e00980079107adbb150c4b03f7d80f63ede92fe6fbbb628642d532dc9d82e9b
5
5
  SHA512:
6
- metadata.gz: a8d82b63e521610dda3906c998e8533ad6f82920f1294dedc10a8acba2ec63084213c3ab80f37ae50525f83928d628ea7a94a37fd52c9abbb63a7da54cc619c7
7
- data.tar.gz: 57e01b5b658f64abc8581a98e95cbb6b6794a787e7b244d79d3aa61f21d157252b19a53a84cbc3e0d18c3058250063d555d5fa133f8ddec67a12fca203657be5
6
+ metadata.gz: cf70a4540105ad59bc4237c9d654e2db5191eeb00b504391a465957b28d7d2fbb7c418969d30762fc8fe0f57ea97893be8980432ab7c2bd0b5643f9fea81ec02
7
+ data.tar.gz: d731085187625db4b92c45cc30eaff79c763d47c9e169d3e24a672627f9e2d144b40e4cd49074ce5afb47d05aa1e43c9cd29c0f2c97494d6f91d35e860a8e799
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -1,24 +1,32 @@
1
- :pastel_link: link:https://github.com/piotrmurach/pastel[Pastel]
2
-
3
1
  :toc: macro
4
2
  :toclevels: 5
5
3
  :figure-caption!:
6
4
 
5
+ :tone_link: link:https://alchemists.io/projects/tone[Tone]
6
+ :logger_link: link:https://rubyapi.org/o/s?q=Logger[Logger]
7
+ :format_link: link:https://ruby-doc.org/3.2.1/format_specifications_rdoc.html[Format Specification]
8
+ :pattern_matching_link: link:https://alchemists.io/articles/ruby_pattern_matching[pattern matching]
9
+ :refinements_link: link:https://alchemists.io/projects/refinements[Refinements]
10
+
7
11
  = Cogger
8
12
 
9
- Cogger is a portmanteau for colorized logging (i.e. `[c]olorized + l[ogger] = cogger`) which
10
- decorates Ruby's native logger with colorized output.
13
+ Cogger is a portmanteau for custom logging (i.e. `[c]ustom + l[ogger] = cogger`) which enhances Ruby's native {logger_link} functionality with additional features such as dynamic emojis, colorized text, structured JSON, multiple outputs, and much more. 🚀
11
14
 
12
15
  toc::[]
13
16
 
14
17
  == Features
15
18
 
16
- - Decorates Ruby's default `Logger`.
17
- - Uses color decoration as provided by the {pastel_link} gem.
19
+ * Enhances Ruby's default {logger_link} with additional functionality and firepower.
20
+ * Provides dynamic/specific emoji output.
21
+ * Provides dynamic/specific colorized output via the {tone_link} gem.
22
+ * Provides customizable templates which leverage the native {format_link}.
23
+ * Provides customizable formatters for simple, color, JSON, and/or custom output.
24
+ * Provides multiple streams so you can log the same information to several outputs at once.
25
+ * Provides filtering of sensitive information.
18
26
 
19
27
  == Screenshot
20
28
 
21
- image::https://alchemists.io/images/projects/cogger/screenshots/console.png[Console,width=552,height=679,role=focal_point]
29
+ image::https://alchemists.io/images/projects/cogger/screenshots/console.png[Console,width=1139,height=211,role=focal_point]
22
30
 
23
31
  == Requirements
24
32
 
@@ -26,98 +34,109 @@ image::https://alchemists.io/images/projects/cogger/screenshots/console.png[Cons
26
34
 
27
35
  == Setup
28
36
 
29
- To set up the project, run:
37
+ To install _with_ security, run:
30
38
 
31
39
  [source,bash]
32
40
  ----
33
- bin/setup
41
+ # 💡 Skip this line if you already have the public certificate installed.
42
+ gem cert --add <(curl --compressed --location https://alchemists.io/gems.pem)
43
+ gem install cogger --trust-policy HighSecurity
34
44
  ----
35
45
 
36
- == Usage
37
-
38
- All colorized logging is provided by `Cogger` which can be used as follows:
46
+ To install _without_ security, run:
39
47
 
40
- [source,ruby]
48
+ [source,bash]
41
49
  ----
42
- logger = Cogger.init
43
-
44
- logger.debug "test" # true
45
- logger.debug { "test" } # true
46
- logger.info "test" # true
47
- logger.info { "test" } # true
48
- logger.warn "test" # true
49
- logger.warn { "test" } # true
50
- logger.error "test" # true
51
- logger.error { "test" } # true
52
- logger.fatal "test" # true
53
- logger.fatal { "test" } # true
54
- logger.unknown "test" # true
55
- logger.unknown { "test" } # true
56
- logger.any "test" # true
57
- logger.any { "test" } # true
50
+ gem install cogger
58
51
  ----
59
52
 
60
- By default, all logging is configured to use `INFO` level and writes to `$stdout`. To see what the
61
- colorized output from the above looks like, please see the screenshot shown in the _Screenshots_
62
- section as documented earlier.
63
-
64
- Beyond the standard log level methods, the following methods are also available:
53
+ You can also add the gem directly to your project:
65
54
 
66
- [source,ruby]
55
+ [source,bash]
67
56
  ----
68
- logger = Cogger.init
69
-
70
- logger.formatter # #<Proc:0x000000010626ebc8 $HOME/OSS/cogger/lib/cogger/client.rb:37 (lambda)>
71
- logger.level # 1
72
- logger.progname # nil
57
+ bundle add cogger
73
58
  ----
74
59
 
75
- === Customization
60
+ Once the gem is installed, you only need to require it:
76
61
 
77
- Customization of the logger differs, slightly, from what you'd get with the standard `Logger` class.
78
- The following sections will explain what these differences look like.
62
+ [source,ruby]
63
+ ----
64
+ require "cogger"
65
+ ----
79
66
 
80
- ==== Initialization
67
+ == Usage
81
68
 
82
- For starters, the first argument is a positional argument that defaults to `Logger.new($stdout)` but
83
- you could swap out the default logger with something that logs to a string. For example:
69
+ All interaction is provided by `Cogger` which can be used as follows:
84
70
 
85
71
  [source,ruby]
86
72
  ----
87
- logger = Cogger.init Logger.new(StringIO.new)
73
+ logger = Cogger.new
74
+ logger.info "demo" # "demo"
88
75
  ----
89
76
 
90
- You can also create a logger which might use custom colors. Example:
77
+ If you set your logging level to `debug`, you can walk through each level:
91
78
 
92
79
  [source,ruby]
93
80
  ----
94
- logger = Cogger.init color: MyColor.new
81
+ logger = Cogger.new level: :debug
82
+
83
+ # Without blocks.
84
+ logger.debug "demo" # "demo"
85
+ logger.info "demo" # "demo"
86
+ logger.warn "demo" # "demo"
87
+ logger.error "demo" # "demo"
88
+ logger.fatal "demo" # "demo"
89
+ logger.unknown "demo" # "demo"
90
+ logger.any "demo" # "demo"
91
+
92
+ # With blocks.
93
+ logger.debug { "demo" } # "demo"
94
+ logger.info { "demo" } # "demo"
95
+ logger.warn { "demo" } # "demo"
96
+ logger.error { "demo" } # "demo"
97
+ logger.fatal { "demo" } # "demo"
98
+ logger.unknown { "demo" } # "demo"
99
+ logger.any { "demo" } # "demo"
95
100
  ----
96
101
 
97
- More information on how to customize your colors will be provided shortly. Lastly, you can provide any _setable_ attribute which would normally be used when constructing a
98
- normal logger. Example:
102
+ ...or, if you'd like to display all severities at once, use:
99
103
 
100
104
  [source,ruby]
101
105
  ----
102
- logger = Cogger.init formatter: ->(severity, _at, _name, message) { "#{message}\n" },
103
- level: :debug,
104
- progname: "Test",
105
- datetime_format: "%Y-%m-%d"
106
+ %i[debug info warn error fatal unknown any].each { |severity| logger.public_send severity, "demo" }
106
107
  ----
107
108
 
108
- Alternatively, you can use a block as well:
109
+ === Initialization
110
+
111
+ When creating a new logger, you can configure behavior via the following attributes:
112
+
113
+ * `id`: The program/process ID which shows up in the logs as your `id`. Default: `$PROGRAM_NAME`. For example, if run within a `demo.rb` script, the `id` would be `"demo"`,
114
+ * `io`: The input/output stream. This can be `STDOUT/$stdout`, a file/path, or `nil`. Default: `$stdout`.
115
+ * `level`: The severity level you want to log at. Can be `:debug`, `:info`, `:warn`, `:error`, `:fatal`, or `:unknown`. Default: `:info`.
116
+ * `formatter`: The formatter to use for formatting your log output. Default: `Cogger::Formatter::Color`. See the _Formatters_ section for more info.
117
+ * `mode`: The binary mode which determines if your logs should be written in binary mode or not. Can be `true` or `false` and is identical to the `binmode` functionality found in the {logger_link} class. Default: `false`.
118
+ * `age`: The rotation age of your log. This only applies when logging to a file. This is equivalent to the `shift_age` as found with the {logger_link} class. Default: `0`.
119
+ * `size`: The rotation size of your log. This only applies when logging to a file. This is equivalent to the `shift_size` as found with the {logger_link} class. Default: `1,048,576` (i.e. 1 MB).
120
+ * `suffix`: The rotation suffix. This only applies when logging to a file. This is equivalent to the `shift_period_suffix` as found with the {logger_link} class and is used when creating new rotation files. Default: `%Y-%m-%d`.
121
+
122
+ Given the above description, here's how'd you create a new logger instance with all attributes:
109
123
 
110
124
  [source,ruby]
111
125
  ----
112
- logger = Cogger.init do |instance|
113
- instance.formatter = ->(severity, _at, _name, message) { "#{message}\n" }
114
- instance.level = :debug
115
- instance.progname = "Test"
116
- instance.datetime_format = "%Y-%m-%d"
117
- end
126
+ # Default
127
+ logger = Cogger.new
128
+
129
+ # Custom
130
+ logger = Cogger.new id: :demo,
131
+ io: "demo.log",
132
+ level: :debug,
133
+ mode: false,
134
+ age: 5,
135
+ size: 1_000,
136
+ suffix: "%Y"
118
137
  ----
119
138
 
120
- ==== Environment
139
+ === Environment
121
140
 
122
141
  The default log level is `INFO` but can be customized via your environment. For instance, you could
123
142
  set the logging level to any of the following:
@@ -130,55 +149,379 @@ export LOG_LEVEL=WARN
130
149
  export LOG_LEVEL=ERROR
131
150
  export LOG_LEVEL=FATAL
132
151
  export LOG_LEVEL=UNKNOWN
133
- export LOG_LEVEL=ANY
134
152
  ----
135
153
 
136
- By default, `Cogger::Client` will automatically use whatever is set via the `LOG_LEVEL` environment
137
- variable unless overwritten during initialization.
154
+ By default, `Cogger` will automatically use whatever is set via the `LOG_LEVEL` environment variable unless overwritten during initialization.
155
+
156
+ === Templates
157
+
158
+ Templates are used by all formatters and adhere to {format_link} as used by `Kernel#format`. All specifiers, flags, width, and precision are supported except for the following restrictions:
159
+
160
+ - Use of _reference by name_ is required which means `%<demo>s` is allowed but `%{demo}` is not. This is because _reference by name_ is required for regular expressions and/or {pattern_matching_link}.
161
+ - Use of the `n$` flag is prohibited because this isn't compatible with the above.
162
+
163
+ In addition to the above, the {format_link} is further enhanced with the use of _universal_ and _individual_ directives which are primarily used by the _color_ formatter but might prove useful for other formatters. Example:
164
+
165
+ [source,ruby]
166
+ ----
167
+ # Universal: Dynamic (color is determined by severity)
168
+ "<dynamic>%<severity>s %<at>s %<id>s %<message>s</dynamic>"
169
+
170
+ # Universal: Specific (uses the green color only)
171
+ "<green>%<severity>s %<at>s %<id>s %<message>s</green>"
172
+
173
+ # Individual: Dynamic (color is determined by severity)
174
+ "%<severity:dynamic>s %<at:dynamic>s %<id:dynamic>s %<message:dynamic>s"
175
+
176
+ # Individual: Specific (uses a rainbow of colors)
177
+ "%<severity:purple>s %<at:yellow>s %<id:cyan>s %<message:green>s"
178
+ ----
179
+
180
+ Here's a detailed breakdown of the above:
181
+
182
+ * *Universal*: Applies color universally to the _entire_ template and requires you to:
183
+ ** Wrap your entire template in a and start (`<example>`) and end tag (`</example>`) which works much like an HTML tag in this context.
184
+ ** Your tag names must either be `<dynamic></dynamic>`, any default color (example: `<green></green>`), or alias (i.e. `<your_alias></your_alias>`) as supported by the {tone_link} gem.
185
+ * *Individual*: Individual templates allow you to apply color to _specific_ attributes and require you to:
186
+ ** Format your attributes as `attribute:directive`. The colon delimiter is required to separate your attribute for your color choice.
187
+ ** The color value (what follows after the colon) can be `dynamic`, any default color (example: `green`), or alias (i.e. `your_alias`) as supported by the {tone_link} gem.
188
+
189
+ In addition to the general categorization of universal and individual tags, each support the following directives:
190
+
191
+ * *Dynamic*: A dynamic directive means that color will be determined by severity level only. This means if info level is used, the associated color (alias) for info will be applied. Same goes for warn, error, etc.
192
+ * *Specific*: A specific directive means the color you use will be applied without any further processing regardless of the severity level. This gives you the ability to customize your colors further in situations where dynamic coloring isn't enough.
193
+
194
+ At this point, you might have gathered that there are specific keys you can use for the log event metadata in your template and everything else is up to you. This stems from the fact that {logger_link} entries always have the following metadata:
195
+
196
+ * `id`: This is the program/process ID you created your logger with (i.e. `Cogger.new id: :demo`).
197
+ * `severity`: This is the severity at which you messaged your logger (i.e. `logger.info`).
198
+ * `at`: This is the date/time as which your log event was created.
199
+
200
+ This also means if you pass in these same keys as a log event (example: `logger.info id: :bad, at: Time.now, severity: :bogus`) they will be ignored.
201
+
202
+ The last key (or keys) is variable and customizable to your needs which is the log event message. Here a couple of examples to illustrate:
203
+
204
+ [source,ruby]
205
+ ----
206
+ # Available as "%<message>s" in your template.
207
+ logger.info "demo"
208
+
209
+ # Available as "%<message>s" in your template.
210
+ logger.info message: "demo"
211
+
212
+ # Available as "%<verb>s" and "%<path>s" in your template.
213
+ logger.info verb: "GET", path: "/"`
214
+ ----
215
+
216
+ 💡 In situations where a message hash is logged but the keys of that hash don't match the keys in the template, then an empty message will be logged. This applies to all formatters except the JSON formatter which will log any key/value that doesn't have a `nil` value.
217
+
218
+ === Emojis
219
+
220
+ In addition to coloring to your log output, you can add emojis as well. Here are the defaults:
138
221
 
139
- ==== Colorization
222
+ [source,ruby]
223
+ ----
224
+ Cogger.emojis
225
+
226
+ # {
227
+ # :debug => "🔎",
228
+ # :info => "🟢",
229
+ # :warn => "⚠️ ",
230
+ # :error => "🛑",
231
+ # :fatal => "🔥"
232
+ # }
233
+ ----
140
234
 
141
- Default colors are provided by the `Cogger::Color` class which are keyed by log level:
235
+ To add an emoji, use:
142
236
 
143
237
  [source,ruby]
144
238
  ----
145
- {
146
- debug: %i[white],
147
- info: %i[green],
148
- warn: %i[yellow],
149
- error: %i[red],
150
- fatal: %i[white bold on_red],
151
- unknown: %i[white bold],
152
- any: %i[white bold]
153
- }
239
+ Cogger.add_emoji(:tada, "🎉")
240
+ .add_emoji :favorite, "❇️"
154
241
  ----
155
242
 
156
- All keys require an array of styles which can then be decorated by {pastel_link}. This means that if
157
- you wanted to use custom colors, you could create a new instance of the `Color` class and inject it
158
- into the client as follows:
243
+ By default, the `:emoji` formatter provides dynamic rendering of emojis based on severity level. Example:
159
244
 
245
+ [source,ruby]
246
+ ----
247
+ logger = Cogger.new formatter: :emoji
248
+ logger.info "demo"
249
+
250
+ # 🟢 demo
251
+ ----
252
+
253
+ If you wanted to use a specific emoji, you could use the color formatter with a specific template:
160
254
 
161
255
  [source,ruby]
162
256
  ----
163
- custom_color = Cogger::Color.new(
164
- defaults: {
165
- debug: %i[white on_black],
166
- info: %i[green on_black],
167
- warn: %i[yellow on_black],
168
- error: %i[red on_black],
169
- fatal: %i[red on_black],
170
- unknown: %i[white on_black],
171
- any: %i[white on_black]
172
- }
173
- )
257
+ logger = Cogger.new formatter: Cogger::Formatters::Color.new("%<emoji:tada>s %<message:dynamic>s")
258
+ logger.info "demo"
174
259
 
175
- logger = Cogger.init color: custom_color
260
+ # 🎉 demo
176
261
  ----
177
262
 
178
- The above would ensure all log level colors are displayed on a black background. Basically, any
179
- style accepted by `Pastel#decorate` method is supported.
263
+ Keep in mind that using a specific, non-dynamic, emoji will _always_ display no matter the current severity level.
264
+
265
+ === Aliases
180
266
 
181
- ==== Testing
267
+ Aliases are specific to the {tone_link} gem which allows you _alias_ specific colors/styles via a new name. Here's how you can use them:
268
+
269
+ [source,ruby]
270
+ ----
271
+ Cogger.add_alias :haze, :bold, :white, :on_purple
272
+ Cogger.aliases
273
+ ----
274
+
275
+ The above would add a `:haze` alias which consists of bold white text on a purple background. Once added, you'd then be able to view a list of all default and custom aliases. You can also override an existing alias if you'd like something else.
276
+
277
+ Aliases are a powerful way to customize your colors and use short syntax in your templates. Building upon the alias, added above, you'd be able to use it in your templates as follows:
278
+
279
+ [source,ruby]
280
+ ----
281
+ # Universal
282
+ "<haze>%<message></haze>"
283
+
284
+ # Individual
285
+ "%<message:haze>"
286
+ ----
287
+
288
+ Check out the {tone_link} documentation for further examples.
289
+
290
+ === Formatters
291
+
292
+ Multiple formatters are provided for you which can be further customized as needed. Here's what is provided by default:
293
+
294
+ [source,ruby]
295
+ ----
296
+ Cogger.formatters
297
+
298
+ # {
299
+ # :color => [
300
+ # Cogger::Formatters::Color < Object,
301
+ # nil
302
+ # ],
303
+ # :detail => [
304
+ # Cogger::Formatters::Simple < Object,
305
+ # "[%<id>s] [%<severity>s] [%<at>s] %<message>s"
306
+ # ],
307
+ # :emoji => [
308
+ # Cogger::Formatters::Color < Object,
309
+ # "%<emoji:dynamic>s% <message:dynamic>s"
310
+ # ],
311
+ # :json => [
312
+ # Cogger::Formatters::JSON < Object,
313
+ # nil
314
+ # ],
315
+ # :simple => [
316
+ # Cogger::Formatters::Simple < Object,
317
+ # nil
318
+ # ],
319
+ # :rack => [
320
+ # Cogger::Formatters::Simple < Object,
321
+ # "[%<id>s] [%<severity>s] [%<at>s] %<verb>s %<status>s %<duration>s %<ip>s %<path>s %<length>s # %<params>s"
322
+ # ]
323
+ # }
324
+ ----
325
+
326
+ You can add a formatter by providing a key, class, and _optional_ template. If a template isn't supplied, then the formatter's default template will be used instead (more on that shortly). Example:
327
+
328
+ [source,ruby]
329
+ ----
330
+ # Add
331
+ Cogger.add_formatter :basic, Cogger::Formatters::Simple, "%<severity>s %<message>s"
332
+
333
+ # Get
334
+ Cogger.get_formatter :basic
335
+ # [Cogger::Formatters::Simple, "%<severity>s %<message>s"]
336
+ ----
337
+
338
+ Symbols or strings can be used interchangeably when adding/getting formatters. As mentioned above, a template doesn't have to be supplied if you want to use the formatter's default template which can be inspected as follows:
339
+
340
+ [source,ruby]
341
+ ----
342
+ Cogger::Formatters::Simple::TEMPLATE
343
+ # "%<message>s"
344
+ ----
345
+
346
+ 💡 When you find yourself customizing any of the default formatters, you can reduce typing by adding your custom configuration to the registry and then referring to it via it's associated key when initializing a new logger.
347
+
348
+ ==== Simple
349
+
350
+ The simple formatter is a bare bones formatter that uses no color information, doesn't support the universal/dynamic template syntax, and only supports the {format_link} as mentioned in the _Templates_ section earlier. This formatter can be used via the following template variations:
351
+
352
+ [source,ruby]
353
+ ----
354
+ logger = Cogger.new formatter: :detail
355
+ logger = Cogger.new formatter: :simple
356
+ logger = Cogger.new formatter: :rack
357
+ ----
358
+
359
+ ==== Color
360
+
361
+ The color formatter is enabled by default and is the equivalent of initializing with either of the following:
362
+
363
+ [source,ruby]
364
+ ----
365
+ logger = Cogger.new
366
+ logger = Cogger.new formatter: Cogger::Formatters::Color.new
367
+ logger = Cogger.new formatter: Cogger::Formatters::Color.new("%<message:dynamic>s")
368
+ ----
369
+
370
+ All three of the above examples are identical so you can start to see how different formatters can be used and customized further. Please refer back to the _Templates_ section on how to customize this formatter with more sophisticated templates.
371
+
372
+ In addition to template customization, you can customize your color aliases as well. Default colors are provided by {tone_link} which are _aliased_ by log level:
373
+
374
+ [source,ruby]
375
+ ----
376
+ Cogger.aliases
377
+
378
+ # {
379
+ # debug: :white,
380
+ # info: :green,
381
+ # warn: :yellow,
382
+ # error: :red,
383
+ # fatal: %i[bold white on_red],
384
+ # unknown: %i[bold white],
385
+ # any: %i[bold white]
386
+ # }
387
+ ----
388
+
389
+ This allows a color -- or combination of color styles (i.e. foreground + background) -- to be dynamically applied based on log severity. You can add additional aliases via:
390
+
391
+ [source,ruby]
392
+ ----
393
+ Cogger.add_alias :mystery, :white, :on_purple
394
+ ----
395
+
396
+ Once an alias is added, it can be immediately applied via the template of your formatter. Example:
397
+
398
+ [source,ruby]
399
+ ----
400
+ # Applies the `mystery` alias universally to your template.
401
+ logger = Cogger.new formatter: Cogger::Formatters::Color.new("<mystery>%<message>s</mystery>")
402
+ ----
403
+
404
+ ==== JSON
405
+
406
+ This formatter is similar in behavior to the _simple_ formatter except the template allows you to order the layout of your keys only. All other information is ignored. To use:
407
+
408
+ [source,ruby]
409
+ ----
410
+ # Default order
411
+ logger = Cogger.new formatter: :json
412
+ logger.info verb: "GET", path: "/"
413
+
414
+ # {"id":"console","severity":"INFO","at":"2023-04-10 09:03:55 -0600","verb":"GET","path":"/"}
415
+
416
+ # Custom order
417
+ logger = Cogger.new formatter: Cogger::Formatters::JSON.new("%<severity>s %<verb>s")
418
+ logger.info verb: "GET", path: "/"
419
+
420
+ # {"severity":"INFO","verb":"GET","id":"console","at":"2023-04-10 09:05:03 -0600","path":"/"}
421
+ ----
422
+
423
+ Your template can be a full or partial match of keys. If no keys match what is defined in the template, then the original order of the keys will be used instead.
424
+
425
+ ==== Custom
426
+
427
+ Should none of the built-in formatters be to your liking, you can implement, use, and/or register a custom formatter as well. The most minimum, bare bones, skeleton would be:
428
+
429
+ [source,ruby]
430
+ ----
431
+ class MyFormatter
432
+ TEMPLATE = "%<message>s"
433
+
434
+ def initialize template = TEMPLATE, sanitizer: Kit::Sanitizer.new
435
+ @template = template
436
+ @sanitizer = sanitizer
437
+ end
438
+
439
+ def call(*entry) = "#{format template, sanitizer.call(*entry)}\n"
440
+
441
+ private
442
+
443
+ attr_reader :template, :sanitizer
444
+ end
445
+ ----
446
+
447
+ There is no restriction on what dependency you might want to initialize your custom formatter with but -- as a bare minimum -- you'll want to provide a default template and inject the sanitizer which sanitizes the raw log entry into a hash you can interact with in your implementation. The only other requirement is that you must implement `#call` which takes a log entry which is an array of positional arguments (i.e. `severity`, `at`, `id`, `message`) and answers back a formatted string. If you need more examples you can either read the link:https://rubyapi.org/o/logger/formatter#method-i-call[Logger::Formatter] documentation or look at any of the formatters provided within this gem.
448
+
449
+ === Filters
450
+
451
+ Filters allow you to mask sensitive information you don't want showing up in your logs. Here are the defaults:
452
+
453
+ [source,ruby]
454
+ ----
455
+ Cogger.filters
456
+
457
+ # [
458
+ # :_csrf,
459
+ # :password,
460
+ # :password_confirmation
461
+ # ]
462
+ ----
463
+
464
+ To add additional filters, use:
465
+
466
+ [source,ruby]
467
+ ----
468
+ Cogger.add_filter(:login)
469
+ .add_filter "email"
470
+
471
+ # [
472
+ # :_csrf,
473
+ # :password,
474
+ # :password_confirmation,
475
+ # :login,
476
+ # :email
477
+ # ]
478
+ ----
479
+
480
+ Symbols and strings can be used interchangeably but are stored as symbols since symbols are used when filtering log entries. Once your filters are in place, you can immediately see their effects:
481
+
482
+ [source,ruby]
483
+ ----
484
+ logger = Cogger.new formatter: :json
485
+ logger.info login: "jayne", password: "secret"
486
+
487
+ # {"id":"console","severity":"INFO","at":"2023-04-09 17:33:00 -0600","login":"[FILTERED]","password":"[FILTERED]"}
488
+ ----
489
+
490
+ === Streams
491
+
492
+ You can add multiple log streams (outputs) by using:
493
+
494
+ [source,ruby]
495
+ ----
496
+ logger = Cogger.new
497
+ .add_stream(io: "tmp/demo.log")
498
+ .add_stream(io: nil)
499
+
500
+ logger.info "Demo."
501
+ ----
502
+
503
+ The above would log the `"Demo."` message to `$stdout` (i.e. the default stream), to the `tmp/demo.log` file, and to `/dev/null`. All of the attributes you would use to construct your default logger apply to any stream. This also means any custom template/formatter can be applied to your streams. Here's another example:
504
+
505
+ [source,ruby]
506
+ ----
507
+ logger = Cogger.new.add_stream(io: "tmp/demo.log", formatter: :json)
508
+ logger.info "Demo."
509
+ ----
510
+
511
+ In this situation, you'd get colorized output to `$stdout` and JSON output to the `tmp/demo.log` file.
512
+
513
+ === Defaults
514
+
515
+ Should you ever need quick access to the defaults, you can use:
516
+
517
+ [source,ruby]
518
+ ----
519
+ Cogger.defaults
520
+ ----
521
+
522
+ This is primarily meant for display/inspection purposes, though.
523
+
524
+ === Testing
182
525
 
183
526
  When testing the Cogger client, you might find it convenient to use `StringIO`, or a file, for
184
527
  logging purposes in order to not pollute your test output but also have a convenient way to see what
@@ -187,7 +530,7 @@ was logged. Example:
187
530
  [source,ruby]
188
531
  ----
189
532
  class Demo
190
- def initialize logger: Cogger.init
533
+ def initialize logger: Cogger.new
191
534
  @logger = logger
192
535
  end
193
536
 
@@ -199,22 +542,24 @@ class Demo
199
542
  end
200
543
 
201
544
  RSpec.describe Demo do
545
+ using Refinements::StringIOs
546
+
202
547
  subject(:demo) { described_class.new logger: }
203
548
 
204
- let(:logger) { Cogger.init Logger.new(StringIO.new) }
549
+ let(:logger) { Cogger.new io: }
550
+ let(:io) { StringIO.new }
205
551
 
206
552
  describe "#say" do
207
553
  it "logs text" do
208
554
  demo.say "test"
209
- expect(logger.reread).to include("test")
555
+ expect(io.reread).to include("test")
210
556
  end
211
557
  end
212
558
  end
213
559
  ----
214
560
 
215
561
  Notice that when testing the instance of `Demo` and injecting a logger which logs to a string I/O
216
- object, you can conveniently reread that string to see what was logged. This makes your specs easier
217
- to write while also not adding additional noise to your test suite's output.
562
+ object, you can conveniently _reread_ the string -- provided by the {refinements_link} gem -- to see what was logged. This makes your specs easier to write while avoiding additional noise in your test suite's output.
218
563
 
219
564
  == Development
220
565