cogger 0.20.0 → 0.21.0

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: 5f2b0f4f7353ac75a6b309e176963333fd2b5f4508344cb6500b42bb0f17a588
4
- data.tar.gz: fe4b0673680fdb3758b4bff0179761423982e8437c33f06bdfc4430974da65dc
3
+ metadata.gz: 6ffa4173a8cc5ef5a1bf7f4e8a134a3f3f3c782e555529bf1cce751f68f3712e
4
+ data.tar.gz: aa044bdb5f4b4c5f13782c7309d4edb292bb8b950553e0efbda06a6daabea0df
5
5
  SHA512:
6
- metadata.gz: f8117b0512c9c6c88a490bbaaa4af1fb12af6b55cc50cddb35072103f8db1653c748d1df7e2d1d5d23368b8b7b9fc8ca89404c718fc9b8a9d0ebb832d856712d
7
- data.tar.gz: dbbe9eefd135ac5b06e33cd7af20da6c889fcb18b705d3ab3c54b3fb32780e41bb5b47f8e7f7526ce03c31d5c75ce03e8a9c71870a3fc35bbd407e5698246e48
6
+ metadata.gz: 44fb9e2bf663a071811ee8a81b388fd6102de8d5b78cbae7b41286dd0c355edbbc089cebed4bbbd32f9ef33e3c69fb48e02323144ea8e11266784b4fbaf47076
7
+ data.tar.gz: 2c786a9f217c43a8f7f31f6f48d3311f8862d2470ff7f25c8b507fbdd4cd3371dd64574c13092415cfd8cc6cf7309d94ad704b896ecb4f1fcd83b8f038b87191
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -19,8 +19,8 @@ toc::[]
19
19
  * Enhances Ruby's default {logger_link} with additional functionality and firepower.
20
20
  * Provides dynamic/specific emoji output.
21
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.
22
+ * Provides customizable templates which leverage native {format_link}.
23
+ * Provides customizable formatters for simple, color, emoji, JSON, and/or custom formats.
24
24
  * Provides multiple streams so you can log the same information to several outputs at once.
25
25
  * Provides global and individual log entry tagging.
26
26
  * Provides filtering of sensitive information.
@@ -28,29 +28,7 @@ toc::[]
28
28
 
29
29
  == Screenshots
30
30
 
31
- *Emoji*
32
-
33
- image::https://alchemists.io/images/projects/cogger/screenshots/emoji.png[Emoji,width=234,height=293]
34
-
35
- *Color*
36
-
37
- image::https://alchemists.io/images/projects/cogger/screenshots/color.png[Color,width=202,height=288]
38
-
39
- *Simple*
40
-
41
- image::https://alchemists.io/images/projects/cogger/screenshots/simple.png[Simple,width=288,height=253]
42
-
43
- *Detail*
44
-
45
- image::https://alchemists.io/images/projects/cogger/screenshots/detail.png[Detail,width=611,height=284]
46
-
47
- *JSON*
48
-
49
- image::https://alchemists.io/images/projects/cogger/screenshots/json.png[JSON,width=1002,height=290]
50
-
51
- *Rack*
52
-
53
- image::https://alchemists.io/images/projects/cogger/screenshots/rack.png[Rack,width=883,height=282]
31
+ image::https://alchemists.io/images/projects/cogger/screenshots/demo.png[Rack,width=713,height=1110]
54
32
 
55
33
  == Requirements
56
34
 
@@ -90,7 +68,7 @@ require "cogger"
90
68
 
91
69
  == Usage
92
70
 
93
- All interaction is provided by `Cogger` which can be used as follows:
71
+ All behavior is provided by creating an instance of `Cogger`. Example:
94
72
 
95
73
  [source,ruby]
96
74
  ----
@@ -105,33 +83,35 @@ If you set your logging level to `debug`, you can walk through each level:
105
83
  logger = Cogger.new level: :debug
106
84
 
107
85
  # Without blocks.
108
- logger.debug "Demo" # "🔎 Demo"
109
- logger.info "Demo" # "🟢 Demo"
110
- logger.warn "Demo" # "⚠️ Demo"
111
- logger.error "Demo" # "🛑 Demo"
112
- logger.fatal "Demo" # "🔥 Demo"
113
- logger.unknown "Demo" # "⚫️ Demo"
114
- logger.any "Demo" # "⚫️ Demo"
115
- logger.add Logger::INFO, "Demo" # "🟢 Demo"
86
+ logger.debug "Demo" # 🔎 [console] Demo
87
+ logger.info "Demo" # 🟢 [console] Demo
88
+ logger.warn "Demo" # ⚠️ [console] Demo
89
+ logger.error "Demo" # 🛑 [console] Demo
90
+ logger.fatal "Demo" # 🔥 [console] Demo
91
+ logger.unknown "Demo" # ⚫️ [console] Demo
92
+ logger.any "Demo" # ⚫️ [console] Demo
93
+ logger.add Logger::INFO, "Demo" # 🟢 [console] Demo
116
94
 
117
95
  # With blocks.
118
- logger.debug { "Demo" } # "🔎 Demo"
119
- logger.info { "Demo" } # "🟢 Demo"
120
- logger.warn { "Demo" } # "⚠️ Demo"
121
- logger.error { "Demo" } # "🛑 Demo"
122
- logger.fatal { "Demo" } # "🔥 Demo"
123
- logger.unknown { "Demo" } # "⚫️ Demo"
124
- logger.any { "Demo" } # "⚫️ Demo"
125
- logger.add(Logger::INFO) { "Demo" } # "🟢 Demo"
96
+ logger.debug { "Demo" } # 🔎 [console] Demo
97
+ logger.info { "Demo" } # 🟢 [console] Demo
98
+ logger.warn { "Demo" } # ⚠️ [console] Demo
99
+ logger.error { "Demo" } # 🛑 [console] Demo
100
+ logger.fatal { "Demo" } # 🔥 [console] Demo
101
+ logger.unknown { "Demo" } # ⚫️ [console] Demo
102
+ logger.any { "Demo" } # ⚫️ [console] Demo
103
+ logger.add(Logger::INFO) { "Demo" } # 🟢 [console] Demo
126
104
  ----
127
105
 
106
+ The `[console]`, in the above output, is the program ID which, in this case, is the ID of this gem's IRB console.
107
+
128
108
  === Initialization
129
109
 
130
110
  When creating a new logger, you can configure behavior via the following attributes:
131
111
 
132
112
  * `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"`,
133
113
  * `io`: The input/output stream. This can be `STDOUT/$stdout`, a file/path, or `nil`. Default: `$stdout`.
134
- * `level`: The severity level you want to log at. Can be `:debug`, `:info`, `:warn`, `:error`, `:fatal`, or `:unknown`. Default: `:info`.
114
+ * `level`: The log level you want to log at. Can be `:debug`, `:info`, `:warn`, `:error`, `:fatal`, or `:unknown`. Default: `:info`.
135
115
  * `formatter`: The formatter to use for formatting your log output. Default: `Cogger::Formatter::Color`. See the _Formatters_ section for more info.
136
116
  * `tags`: Global tagging for _every_ log entry which _must_ be an array of objects you wish to use for tagging purposes.
137
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`.
@@ -210,29 +190,29 @@ Please see the {logger_link} documentation for more information.
210
190
  Templates are used by all formatters and adhere to the {format_link} as used by `Kernel#format`. All specifiers, flags, width, and precision are supported except for the following restrictions:
211
191
 
212
192
  - 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}.
213
- - Use of the `n$` flag is prohibited because this isn't compatible with the above.
193
+ - Use of the `n$` flag is prohibited because it's not compatible with the above.
214
194
 
215
195
  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 can prove useful for other formatters. Example:
216
196
 
217
197
  [source,ruby]
218
198
  ----
219
- # Universal: Dynamic (color is determined by severity)
220
- "<dynamic>%<severity>s %<at>s %<id>s %<message>s</dynamic>"
199
+ # Universal: Dynamic (color is determined by level).
200
+ "<dynamic>%<level>s %<at>s %<id>s %<message>s</dynamic>"
221
201
 
222
- # Universal: Specific (uses the green color only)
223
- "<green>%<severity>s %<at>s %<id>s %<message>s</green>"
202
+ # Universal: Specific (uses the green color only).
203
+ "<green>%<level>s %<at>s %<id>s %<message>s</green>"
224
204
 
225
- # Individual: Dynamic (color is determined by severity)
226
- "%<severity:dynamic>s %<at:dynamic>s %<id:dynamic>s %<message:dynamic>s"
205
+ # Individual: Dynamic (color is determined by level).
206
+ "%<level:dynamic>s %<at:dynamic>s %<id:dynamic>s %<message:dynamic>s"
227
207
 
228
- # Individual: Specific (uses a rainbow of colors)
229
- "%<severity:purple>s %<at:yellow>s %<id:cyan>s %<message:green>s"
208
+ # Individual: Specific (uses a rainbow of colors).
209
+ "%<level:purple>s %<at:yellow>s %<id:cyan>s %<message:green>s"
230
210
  ----
231
211
 
232
212
  Here's a detailed breakdown of the above:
233
213
 
234
214
  * *Universal*: Applies color universally to the _entire_ template and requires you to:
235
- ** Wrap your entire template in a and start (`<example>`) and end tag (`</example>`) which works much like an HTML tag in this context.
215
+ ** Wrap your entire template in a and start (`<dynamic>`) and end tag (`</dynamic>`) which works much like an HTML tag in this context.
236
216
  ** 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.
237
217
  * *Individual*: Individual templates allow you to apply color to _specific_ attributes and require you to:
238
218
  ** Format your attributes as `attribute:directive`. The colon delimiter is required to separate your attribute for your color choice.
@@ -240,18 +220,18 @@ Here's a detailed breakdown of the above:
240
220
 
241
221
  In addition to the general categorization of universal and individual tags, each support the following directives:
242
222
 
243
- * *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.
244
- * *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.
223
+ * *Dynamic*: A dynamic directive means color will be determined by log level only. This means if info level is used, the associated color (alias) for info will be applied. Same goes for warn, error, etc.
224
+ * *Specific*: A specific directive means the color you use will be applied without any further processing regardless of log level. This gives you the ability to customize your colors further in situations where dynamic coloring isn't enough.
245
225
 
246
226
  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:
247
227
 
248
- * `id`: This is the program/process ID you created your logger with (i.e. `Cogger.new id: :demo`).
249
- * `severity`: This is the severity at which you messaged your logger (i.e. `logger.info`).
250
- * `at`: This is the date/time as which your log event was created.
228
+ * `id`: The program/process ID you created your logger with (i.e. `Cogger.new id: :demo`).
229
+ * `level`: The level at which you messaged your logger (i.e. `logger.info`).
230
+ * `at`: The date/time as which your log event was created.
251
231
 
252
- 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.
232
+ This also means if you pass in these same keys as a log event (example: `logger.info id: :bad, at: Time.now, level: :bogus`) they will be ignored.
253
233
 
254
- The last key (or keys) is variable and customizable to your needs which is the log event message. The only special key is the `tags` key which is explained later. Here a couple of examples to illustrate:
234
+ The last key (or keys) is customizable to your needs and is known as the log event message. The only special key is the `tags` key which will be explained later. Here a couple of examples to illustrate:
255
235
 
256
236
  [source,ruby]
257
237
  ----
@@ -278,21 +258,21 @@ Cogger.emojis
278
258
  # {
279
259
  # :debug => "🔎",
280
260
  # :info => "🟢",
281
- # :warn => "⚠️ ",
261
+ # :warn => "⚠️",
282
262
  # :error => "🛑",
283
263
  # :fatal => "🔥",
284
264
  # :any => "⚫️"
285
265
  # }
286
266
  ----
287
267
 
288
- The `:emoji` formatter is the default formatter which provides dynamic rendering of emojis based on severity level. Example:
268
+ The `:emoji` formatter is the default formatter which provides dynamic rendering of emojis based on log level. Example:
289
269
 
290
270
  [source,ruby]
291
271
  ----
292
272
  logger = Cogger.new
293
273
  logger.info "Demo"
294
274
 
295
- # 🟢 Demo
275
+ # 🟢 [console] Demo
296
276
  ----
297
277
 
298
278
  To add one or more emojis, you can chain messages together when registering them:
@@ -316,7 +296,7 @@ logger.warn "Demo"
316
296
  # 🎉 Demo
317
297
  ----
318
298
 
319
- As you can see, using a specific and non-dynamic emoji will _always_ display regardless of the current severity level.
299
+ As you can see, using a specific and non-dynamic emoji will _always_ display regardless of the current log level.
320
300
 
321
301
  === Aliases
322
302
 
@@ -358,7 +338,7 @@ Cogger.formatters
358
338
  # ],
359
339
  # :detail => [
360
340
  # Cogger::Formatters::Simple < Object,
361
- # "[%<id>s] [%<severity>s] [%<at>s] %<message>s"
341
+ # "[%<id>s] [%<level>s] [%<at>s] %<message>s"
362
342
  # ],
363
343
  # :emoji => [
364
344
  # Cogger::Formatters::Emoji < Cogger::Formatters::Color,
@@ -374,7 +354,7 @@ Cogger.formatters
374
354
  # ],
375
355
  # :rack => [
376
356
  # Cogger::Formatters::Simple < Object,
377
- # "[%<id>s] [%<severity>s] [%<at>s] %<verb>s %<status>s %<duration>s %<ip>s %<path>s %<length>s # %<params>s"
357
+ # "[%<id>s] [%<level>s] [%<at>s] %<verb>s %<status>s %<duration>s %<ip>s %<path>s %<length>s # %<params>s"
378
358
  # ]
379
359
  # }
380
360
  ----
@@ -384,11 +364,16 @@ You can add a formatter by providing a key, class, and _optional_ template. If a
384
364
  [source,ruby]
385
365
  ----
386
366
  # Registration
387
- Cogger.add_formatter :basic, Cogger::Formatters::Simple, "%<severity>s %<message>s"
367
+
368
+ Cogger.add_formatter :basic, Cogger::Formatters::Simple, "%<level>s %<message>s"
388
369
 
389
370
  # Usage
371
+
390
372
  Cogger.get_formatter :basic
391
- # [Cogger::Formatters::Simple, "%<severity>s %<message>s"]
373
+ # [Cogger::Formatters::Simple, "%<level>s %<message>s"]
374
+
375
+ Cogger.get_formatter :bogus
376
+ # Unregistered formatter: bogus. (KeyError)
392
377
  ----
393
378
 
394
379
  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:
@@ -405,12 +390,18 @@ Cogger::Formatters::Simple::TEMPLATE # "%<message>s"
405
390
 
406
391
  ==== Simple
407
392
 
408
- 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:
393
+ 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. Example:
409
394
 
410
395
  [source,ruby]
411
396
  ----
412
- logger = Cogger.new formatter: :detail
413
397
  logger = Cogger.new formatter: :simple
398
+ ----
399
+
400
+ This formatter can be used via the following template variations:
401
+
402
+ [source,ruby]
403
+ ----
404
+ logger = Cogger.new formatter: :detail
414
405
  logger = Cogger.new formatter: :rack
415
406
  ----
416
407
 
@@ -431,17 +422,17 @@ Please refer back to the _Templates_ section on how to customize this formatter
431
422
  ----
432
423
  Cogger.aliases
433
424
 
434
- # {
435
- # debug: :white,
436
- # info: :green,
437
- # warn: :yellow,
438
- # error: :red,
439
- # fatal: %i[bold white on_red],
440
- # any: %i[dim bright_white]
441
- # }
425
+ {
426
+ debug: [:white],
427
+ info: [:green],
428
+ warn: [:yellow],
429
+ error: [:red],
430
+ fatal: %i[bold white on_red],
431
+ any: [dim bright_white]
432
+ }
442
433
  ----
443
434
 
444
- 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:
435
+ This allows a color -- or combination of color styles (i.e. foreground + background) -- to be dynamically applied based on log level. You can add additional aliases via:
445
436
 
446
437
  [source,ruby]
447
438
  ----
@@ -478,14 +469,14 @@ Cogger.emojis
478
469
  # {
479
470
  # :debug => "🔎",
480
471
  # :info => "🟢",
481
- # :warn => "⚠️ ",
472
+ # :warn => "⚠️",
482
473
  # :error => "🛑",
483
474
  # :fatal => "🔥",
484
475
  # :any => "⚫️"
485
476
  # }
486
477
  ----
487
478
 
488
- This allows an emoji to be dynamically applied based on log severity. You can add or modify aliases as follows:
479
+ This allows an emoji to be dynamically applied based on log level. You can add or modify aliases as follows:
489
480
 
490
481
  [source,ruby]
491
482
  ----
@@ -498,14 +489,23 @@ Once an alias is added/updated, it can be immediately applied via the template o
498
489
  ----
499
490
  logger = Cogger.new
500
491
  logger.warn "Demo"
501
- # 🟡 Demo
492
+ # 🟡 [console] Demo
502
493
  ----
503
494
 
504
495
  ℹ️ Much like the simple and color formatters, any leading or trailing whitespace is automatically removed after the template has been formatted.
505
496
 
497
+ ==== Detail
498
+
499
+ This formatter is the _Simple_ formatter with a different template and can be configured as follows:
500
+
501
+ [source,ruby]
502
+ ----
503
+ logger = Cogger.new formatter: :detail
504
+ ----
505
+
506
506
  ==== JSON
507
507
 
508
- This formatter is similar in behavior to the _simple_ formatter except that date/time defaults to UTC, is formattted according to link:https://datatracker.ietf.org/doc/html/rfc3339[RFC 3339] using millisecond precision, and the template allows you to _order_ the layout of your keys. All other template information is ignored, only the order of your template keys matters. Example:
508
+ This formatter is similar in behavior to the _simple_ formatter except that date/time defaults to UTC, is formatted according to link:https://datatracker.ietf.org/doc/html/rfc3339[RFC 3339] using millisecond precision, and the template allows you to _order_ the layout of your keys. All other template information is ignored, only the order of your template keys matters. Example:
509
509
 
510
510
  *Default Order*
511
511
 
@@ -514,17 +514,17 @@ This formatter is similar in behavior to the _simple_ formatter except that date
514
514
  logger = Cogger.new formatter: :json
515
515
 
516
516
  logger.info verb: "GET", path: "/"
517
- # {"id":"console","severity":"INFO","at":"2023-12-10T18:42:32.844+00:00","verb":"GET","path":"/"}
517
+ # {"id":"console","level":"INFO","at":"2023-12-10T18:42:32.844+00:00","verb":"GET","path":"/"}
518
518
  ----
519
519
 
520
520
  *Custom Order*
521
521
 
522
522
  [source,ruby]
523
523
  ----
524
- logger = Cogger.new formatter: Cogger::Formatters::JSON.new("%<severity>s %<verb>s")
524
+ logger = Cogger.new formatter: Cogger::Formatters::JSON.new("%<level>s %<verb>s")
525
525
 
526
526
  logger.info verb: "GET", path: "/"
527
- # {"severity":"INFO","verb":"GET","id":"console","at":"2023-12-10T18:43:03.805+00:00","path":"/"}
527
+ # {"level":"INFO","verb":"GET","id":"console","at":"2023-12-10T18:43:03.805+00:00","path":"/"}
528
528
  ----
529
529
 
530
530
  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.
@@ -536,10 +536,10 @@ You can always supply a message as your first argument -- or specify it by using
536
536
  logger = Cogger.new formatter: :json
537
537
 
538
538
  logger.info "Demo"
539
- # {"id":"console","severity":"INFO","at":"2023-12-10T18:43:42.029+00:00","message":"Demo"}
539
+ # {"id":"console","level":"INFO","at":"2023-12-10T18:43:42.029+00:00","message":"Demo"}
540
540
 
541
541
  logger.info message: "Demo"
542
- # {"id":"console","severity":"INFO","at":"2023-12-10T18:44:14.568+00:00","message":"Demo"}
542
+ # {"id":"console","level":"INFO","at":"2023-12-10T18:44:14.568+00:00","message":"Demo"}
543
543
  ----
544
544
 
545
545
  When tags are provided, the `:tags` key will appear in the output depending on whether you are using _single tags_. If hash tags are used, they'll show up as additional attributes in the output. Here's an example where a mix of single and hash keys are used:
@@ -551,7 +551,7 @@ logger = Cogger.new formatter: :json
551
551
  logger.info "Demo", tags: ["WEB", "PRIMARY", {service: :api, demo: true}]
552
552
  # {
553
553
  # "id":"console",
554
- # "severity":"INFO",
554
+ # "level":"INFO",
555
555
  # "at":"2023-12-10T18:44:32.723+00:00",
556
556
  # "message":"Demo",
557
557
  # "tags":["WEB",
@@ -563,6 +563,15 @@ logger.info "Demo", tags: ["WEB", "PRIMARY", {service: :api, demo: true}]
563
563
 
564
564
  Notice, with the above, that the single tags of `WEB` and `PRIMARY` show up in the `tags` array while the `:service` and `:demo` keys show up at the top level of the hash. Since the `:tags`, `:service`, `:demo` keys are normal keys, like any key in your JSON output, this means you can use a custom template to arrange the order of these keys if you don't like the default.
565
565
 
566
+ ==== Rack
567
+
568
+ This formatter is the _Simple_ formatter with a different template and can be configured as follows:
569
+
570
+ [source,ruby]
571
+ ----
572
+ logger = Cogger.new formatter: :rack
573
+ ----
574
+
566
575
  ==== Native
567
576
 
568
577
  Should you wish to use the native formatter as provided by original/native {logger_link}, it will work but not in the manner you might expect. Example:
@@ -574,7 +583,7 @@ require "logger"
574
583
  logger = Cogger.new formatter: Logger::Formatter.new
575
584
  logger.info "Demo"
576
585
 
577
- # I, [2023-10-15T14:32:55.061777 #72801] INFO -- console: #<data Cogger::Entry id="console", severity=:info, at=2023-10-15 14:32:55.061734 -0600, message="Demo", tags=[], payload={}>
586
+ # I, [2023-10-15T14:32:55.061777 #72801] INFO -- console: #<data Cogger::Entry id="console", level=:info, at=2023-10-15 14:32:55.061734 -0600, message="Demo", tags=[], payload={}>
578
587
  ----
579
588
 
580
589
  While the above doesn't cause an error, you only get a dump of the `Cogger::Entry` which is not what you want. To replicate native {logger_link} functionality, you can do use the simple formatter as follows to produce the rough equivalent:
@@ -582,7 +591,7 @@ While the above doesn't cause an error, you only get a dump of the `Cogger::Entr
582
591
  [source,ruby]
583
592
  ----
584
593
  formatter = Cogger::Formatters::Simple.new(
585
- "%<severity>s, [%<at>s] %<severity>s -- %<id>s: %<message>s"
594
+ "%<level>s, [%<at>s] %<level>s -- %<id>s: %<message>s"
586
595
  )
587
596
  logger = Cogger.new(formatter:)
588
597
  logger.info "Demo"
@@ -612,7 +621,7 @@ class MyFormatter
612
621
  end
613
622
  ----
614
623
 
615
- 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 input into a `Cogger::Entry` object 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`, `entry`) and answers back a formatted string. If you need more examples you can look at any of the formatters provided within this gem.
624
+ 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 input into a `Cogger::Entry` object 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. `level`, `at`, `id`, `entry`) and answers back a formatted string. If you need more examples you can look at any of the formatters provided within this gem.
616
625
 
617
626
  === Tags
618
627
 
@@ -623,7 +632,7 @@ Tags allow you to tag your messages at both a global and local (i.e. per message
623
632
  logger = Cogger.new tags: %w[WEB]
624
633
  logger.info "Demo"
625
634
 
626
- # 🟢 [WEB] Demo
635
+ # 🟢 [console] [WEB] Demo
627
636
  ----
628
637
 
629
638
  Each tag is wrapped in brackets (i.e. `[]`) and you can use multiple tags:
@@ -633,18 +642,17 @@ Each tag is wrapped in brackets (i.e. `[]`) and you can use multiple tags:
633
642
  logger = Cogger.new tags: %w[WEB EXAMPLE]
634
643
  logger.info "Demo"
635
644
 
636
- # 🟢 [WEB] [EXAMPLE] Demo
645
+ # 🟢 [console] [WEB] [EXAMPLE] Demo
637
646
  ----
638
647
 
639
648
  You are not limited to string-based tags. Any object will work:
640
649
 
641
-
642
650
  [source,ruby]
643
651
  ----
644
652
  logger = Cogger.new tags: ["ONE", :two, 3, {four: "FOUR"}, proc { "FIVE" }]
645
653
  logger.info "Demo"
646
654
 
647
- # 🟢 [ONE] [two] [3] [FIVE] [four=FOUR] Demo
655
+ # 🟢 [console] [ONE] [two] [3] [FIVE] [four=FOUR] Demo
648
656
  ----
649
657
 
650
658
  With the above, we have string, symbol, integer, hash, and proc tags. With hashes, you'll always get a the key/value pair formatted as: `key=value`. Procs/lambdas allow you to lazy evaluate your tag at time of logging which provides a powerful way to acquire the current process ID, thread ID, and so forth.
@@ -656,7 +664,7 @@ In addition to global tags, you can use local tags per log message. Example:
656
664
  logger = Cogger.new
657
665
  logger.info "Demo", tags: ["ONE", :two, 3, {four: "FOUR"}, proc { "FIVE" }]
658
666
 
659
- # 🟢 [ONE] [two] [3] [FIVE] [four=FOUR] Demo
667
+ # 🟢 [console] [ONE] [two] [3] [FIVE] [four=FOUR] Demo
660
668
  ----
661
669
 
662
670
  You can also combine global and local tags:
@@ -666,7 +674,7 @@ You can also combine global and local tags:
666
674
  logger = Cogger.new tags: ["ONE", :two]
667
675
  logger.info "Demo", tags: [3, proc { "FOUR" }]
668
676
 
669
- # 🟢 [ONE] [two] [3] [FOUR] Demo
677
+ # 🟢 [console] [ONE] [two] [3] [FOUR] Demo
670
678
  ----
671
679
 
672
680
  As you can see, tags are highly versatile. That said, the following guidelines are worth consideration when using them:
@@ -706,7 +714,7 @@ logger.info login: "jayne", password: "secret"
706
714
 
707
715
  # {
708
716
  # "id":"console",
709
- # "severity":"INFO",
717
+ # "level":"INFO",
710
718
  # "at":"2023-10-18 19:21:40 -0600",
711
719
  # "login":"jayne",
712
720
  # "password":"[FILTERED]"
@@ -748,11 +756,11 @@ logger = Cogger.new
748
756
 
749
757
  logger.info "Demo"
750
758
 
751
- # 🟢 Demo
752
- # Demo
753
- # [console] [INFO] [2023-10-15 15:17:27 -0600] Demo
754
- # {"id":"console","severity":"INFO","at":"2023-10-15 15:17:27 -0600","message":"Demo"}
755
- # Demo
759
+ # 🟢 [console] Demo
760
+ # [console] Demo
761
+ # [console] [INFO] [2024-06-16 15:09:38 -0600] Demo
762
+ # {"id":"console","level":"INFO","at":"2024-06-16T21:09:38.896+00:00","message":"Demo"}
763
+ # [console] Demo
756
764
  ----
757
765
 
758
766
  === Abort
@@ -763,23 +771,29 @@ Aborting a program is mostly syntax sugar for Command Line Interfaces (CLIs) whi
763
771
  ----
764
772
  logger = Cogger.new
765
773
 
766
- # Not recommended since `Kernel#exit false` is faster.
767
- logger.abort
768
- # Logs no message and exits with status code: 1.
769
-
770
774
  logger.abort "Danger!"
771
- # 🛑 Danger!
775
+ # 🛑 [console] Danger!
772
776
  # Exits with status code: 1.
773
777
 
774
778
  logger.abort { "Danger!" }
775
- # 🛑 Danger!
779
+ # 🛑 [console] Danger!
776
780
  # Exits with status code: 1.
777
781
 
778
782
  logger.abort message: "Danger!"
779
- # 🛑 Danger!
783
+ # 🛑 [console] Danger!
780
784
  # Exits with status code: 1.
781
785
  ----
782
786
 
787
+ You can use `#abort` without a message which will not log anything and immediately exit:
788
+
789
+ [source,ruby]
790
+ ----
791
+ logger.abort
792
+ # Logs no message and exits with status code: 1.
793
+ ----
794
+
795
+ This is _not recommended_ since using `Kernel#exit` directly is more performant.
796
+
783
797
  === Rack
784
798
 
785
799
  {rack_link} is _implicitly_ supported which means your middleware _must be_ Rack-based and _must require_ the Rack gem since `Cogger::Rack::Logger` doesn't _explicitly_ require Rack by default. If these requirements are met then, to add HTTP request logging, you only need to use it. Example:
@@ -835,7 +849,7 @@ Once this middleware is configured and used within your application, you'll star
835
849
  ----
836
850
  {
837
851
  "id":"demo",
838
- "severity":"INFO",
852
+ "level":"INFO",
839
853
  "at":"2023-12-10T22:37:06.341+00:00",
840
854
  "verb":"GET",
841
855
  "ip":"127.0.0.1",
@@ -855,7 +869,7 @@ To build upon the above -- and if using the Rails framework -- you could configu
855
869
  # demo/config/application.rb
856
870
  module Demo
857
871
  class Application < Rails::Application
858
- config.logger = Cogger.new id: "demo", formatter: :json,
872
+ config.logger = Cogger.new id: :demo, formatter: :json,
859
873
  config.middleware.swap Rails::Rack::Logger, Cogger::Rack::Logger, {logger: config.logger}
860
874
  end
861
875
  end
@@ -863,6 +877,44 @@ end
863
877
 
864
878
  The above defines `Cogger` as the default logger for the entire application, ensures `Cogger::Rack::Logger` is configured to use it and swaps itself with the default `Rails::Rack::Logger` so you don't have two pieces of middleware logging the same HTTP requests.
865
879
 
880
+ Alternatively, you could use a more advanced configuration with even more detailed logging:
881
+
882
+ [source,ruby]
883
+ ----
884
+ # demo/config/application.rb
885
+ module Demo
886
+ class Application < Rails::Application
887
+ config.version = ENV.fetch "PROJECT_VERSION"
888
+
889
+ config.logger = Cogger.new id: :demo,
890
+ formatter: :json,
891
+ tags: [
892
+ proc { {pid: Process.pid, thread: Thread.current.object_id} },
893
+ {team: "acme", version: config.version}
894
+ ]
895
+
896
+ unless Rails.env.test?
897
+ config.middleware.swap Rails::Rack::Logger, Cogger::Rack::Logger, {logger: config.logger}
898
+ end
899
+ end
900
+ end
901
+ ----
902
+
903
+ The above does the following:
904
+
905
+ * Fetches the project version from the environment and then logs the version as a tag.
906
+ * PID and thread information are dynamically calculated at runtime, via the proc, as tags too.
907
+ * Team information is also captured as a tag.
908
+ * The middleware is only configured for use in any environment other than the test environment.
909
+
910
+ You could also add the following to your Development and Test environments so you capture all logs in a log file:
911
+
912
+ [source,ruby]
913
+ ----
914
+ # Add this to your development and/or test environment configuration.
915
+ config.logger = Cogger.new io: Rails.root.join("log/#{Rails.env}.log")
916
+ ----
917
+
866
918
  === Defaults
867
919
 
868
920
  Should you ever need quick access to the defaults, you can use:
@@ -930,7 +982,7 @@ class Demo
930
982
  @logger = logger
931
983
  end
932
984
 
933
- def say(text) = logger.info { text }
985
+ def call(text) = logger.info { text }
934
986
 
935
987
  private
936
988
 
@@ -942,10 +994,10 @@ RSpec.describe Demo do
942
994
 
943
995
  let(:logger) { Cogger.new io: StringIO.new }
944
996
 
945
- describe "#say" do
946
- it "logs text" do
947
- demo.say "test"
948
- expect(logger.reread).to include("test")
997
+ describe "#call" do
998
+ it "logs message" do
999
+ demo.call "Test."
1000
+ expect(logger.reread).to include("Test.")
949
1001
  end
950
1002
  end
951
1003
  end
data/cogger.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "cogger"
5
- spec.version = "0.20.0"
5
+ spec.version = "0.21.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/cogger"
data/lib/cogger/entry.rb CHANGED
@@ -4,10 +4,10 @@ require "core"
4
4
 
5
5
  module Cogger
6
6
  # Defines a log entry which can be formatted for output.
7
- Entry = Data.define :id, :severity, :at, :message, :tags, :payload do
7
+ Entry = Data.define :id, :level, :at, :message, :tags, :payload do
8
8
  def self.for(message = nil, **payload)
9
9
  new id: payload.delete(:id) || Program.call,
10
- severity: (payload.delete(:severity) || "INFO").upcase,
10
+ level: (payload.delete(:level) || "INFO").upcase,
11
11
  at: payload.delete(:at) || ::Time.now,
12
12
  message: (block_given? ? yield : message),
13
13
  tags: Array(payload.delete(:tags)),
@@ -16,7 +16,7 @@ module Cogger
16
16
 
17
17
  def self.for_crash message, error, id:
18
18
  new id:,
19
- severity: "FATAL",
19
+ level: "FATAL",
20
20
  message:,
21
21
  payload: {
22
22
  error_message: error.message,
@@ -26,7 +26,7 @@ module Cogger
26
26
  end
27
27
 
28
28
  def initialize id: Program.call,
29
- severity: "INFO",
29
+ level: "INFO",
30
30
  at: ::Time.now,
31
31
  message: nil,
32
32
  tags: [],
@@ -34,14 +34,14 @@ module Cogger
34
34
  super
35
35
  end
36
36
 
37
- def attributes = {id:, severity:, at:, message:, **payload}
37
+ def attributes = {id:, level:, at:, message:, **payload}
38
38
 
39
39
  def tagged_attributes tagger: Tag
40
40
  computed_tags = tagger.for(*tags)
41
41
 
42
42
  return attributes if computed_tags.empty?
43
43
 
44
- {id:, severity:, at:, message:, **computed_tags.to_h, **payload}
44
+ {id:, level:, at:, message:, **computed_tags.to_h, **payload}
45
45
  end
46
46
 
47
47
  def tagged tagger: Tag
@@ -4,7 +4,7 @@ module Cogger
4
4
  module Formatters
5
5
  # Formats by color.
6
6
  class Color
7
- TEMPLATE = "%<message:dynamic>s"
7
+ TEMPLATE = "[%<id:dynamic>s] %<message:dynamic>s"
8
8
 
9
9
  def initialize template = TEMPLATE, processor: Processors::Color.new
10
10
  @template = template
@@ -5,7 +5,7 @@ module Cogger
5
5
  # Formats fatal crashes.
6
6
  class Crash
7
7
  TEMPLATE = <<~CONTENT
8
- <dynamic>[%<id>s] [%<severity>s] [%<at>s] Crash!
8
+ <dynamic>[%<id>s] [%<level>s] [%<at>s] Crash!
9
9
  %<message>s
10
10
  %<error_message>s (%<error_class>s)
11
11
  %<backtrace>s</dynamic>
@@ -4,7 +4,7 @@ module Cogger
4
4
  module Formatters
5
5
  # Formats by emoji and color.
6
6
  class Emoji < Color
7
- TEMPLATE = "%<emoji:dynamic>s %<message:dynamic>s"
7
+ TEMPLATE = "%<emoji:dynamic>s [%<id:dynamic>s] %<message:dynamic>s"
8
8
 
9
9
  def initialize(template = TEMPLATE, ...)
10
10
  super
@@ -3,9 +3,9 @@
3
3
  module Cogger
4
4
  module Formatters
5
5
  module Kit
6
- # Transform color based on dynamic (severity) or standard color preference.
6
+ # Transform color based on dynamic (level) or standard color preference.
7
7
  Colorizer = lambda do |value, attributes|
8
- value == "dynamic" ? attributes[:severity].downcase : value
8
+ value == "dynamic" ? attributes[:level].downcase : value
9
9
  end
10
10
  end
11
11
  end
@@ -4,7 +4,7 @@ module Cogger
4
4
  module Formatters
5
5
  # Formats simple templates that require no additional processing.
6
6
  class Simple
7
- TEMPLATE = "%<message>s"
7
+ TEMPLATE = "[%<id>s] %<message>s"
8
8
 
9
9
  def initialize template = TEMPLATE, sanitizer: Kit::Sanitizer
10
10
  @template = template
data/lib/cogger/hub.rb CHANGED
@@ -67,8 +67,8 @@ module Cogger
67
67
  exit false
68
68
  end
69
69
 
70
- def add(severity, message = nil, **, &)
71
- log(Logger::SEV_LABEL.fetch(severity, "ANY").downcase, message, **, &)
70
+ def add(level, message = nil, **, &)
71
+ log(Logger::SEV_LABEL.fetch(level, "ANY").downcase, message, **, &)
72
72
  end
73
73
 
74
74
  alias unknown any
@@ -94,23 +94,23 @@ module Cogger
94
94
  )
95
95
  end
96
96
 
97
- def log(severity, message = nil, **, &)
98
- dispatch(severity, message, **, &)
97
+ def log(level, message = nil, **, &)
98
+ dispatch(level, message, **, &)
99
99
  rescue StandardError => error
100
100
  crash message, error
101
101
  end
102
102
 
103
- def dispatch(severity, message, **payload, &)
103
+ def dispatch(level, message, **payload, &)
104
104
  entry = configuration.entry.for(
105
105
  message,
106
106
  id: configuration.id,
107
- severity:,
107
+ level:,
108
108
  tags: configuration.tags + Array(payload.delete(:tags)),
109
109
  **payload,
110
110
  &
111
111
  )
112
112
 
113
- mutex.synchronize { streams.each { |logger| logger.public_send severity, entry } }
113
+ mutex.synchronize { streams.each { |logger| logger.public_send level, entry } }
114
114
  true
115
115
  end
116
116
 
@@ -14,7 +14,7 @@ module Cogger
14
14
  .add_alias(:any, :dim, :bright_white)
15
15
  .add_emoji(:debug, "🔎")
16
16
  .add_emoji(:info, "🟢")
17
- .add_emoji(:warn, "⚠️ ")
17
+ .add_emoji(:warn, "⚠️")
18
18
  .add_emoji(:error, "🛑")
19
19
  .add_emoji(:fatal, "🔥")
20
20
  .add_emoji(:any, "⚫️")
@@ -22,14 +22,14 @@ module Cogger
22
22
  .add_formatter(
23
23
  :detail,
24
24
  Cogger::Formatters::Simple,
25
- "[%<id>s] [%<severity>s] [%<at>s] %<message>s"
25
+ "[%<id>s] [%<level>s] [%<at>s] %<message>s"
26
26
  )
27
27
  .add_formatter(:emoji, Cogger::Formatters::Emoji)
28
28
  .add_formatter(:json, Cogger::Formatters::JSON)
29
29
  .add_formatter(:simple, Cogger::Formatters::Simple)
30
30
  .add_formatter :rack,
31
31
  Cogger::Formatters::Simple,
32
- "[%<id>s] [%<severity>s] [%<at>s] %<verb>s %<status>s " \
32
+ "[%<id>s] [%<level>s] [%<at>s] %<verb>s %<status>s " \
33
33
  "%<duration>s %<ip>s %<path>s %<length>s %<params>s"
34
34
  end
35
35
 
@@ -45,7 +45,9 @@ module Cogger
45
45
  self
46
46
  end
47
47
 
48
- def get_emoji(key) = emojis[key.to_sym]
48
+ def get_emoji key
49
+ emojis.fetch(key.to_sym) { fail KeyError, "Unregistered emoji: #{key}." }
50
+ end
49
51
 
50
52
  def emojis = @emojis ||= {}
51
53
 
@@ -61,7 +63,9 @@ module Cogger
61
63
  self
62
64
  end
63
65
 
64
- def get_formatter(key) = formatters[key.to_sym]
66
+ def get_formatter key
67
+ formatters.fetch(key.to_sym) { fail KeyError, "Unregistered formatter: #{key}." }
68
+ end
65
69
 
66
70
  def formatters = @formatters ||= {}
67
71
 
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cogger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.0
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -35,7 +35,7 @@ cert_chain:
35
35
  3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
36
36
  gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
37
37
  -----END CERTIFICATE-----
38
- date: 2024-06-01 00:00:00.000000000 Z
38
+ date: 2024-06-16 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: core
@@ -155,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
155
  - !ruby/object:Gem::Version
156
156
  version: '0'
157
157
  requirements: []
158
- rubygems_version: 3.5.11
158
+ rubygems_version: 3.5.12
159
159
  signing_key:
160
160
  specification_version: 4
161
161
  summary: A customizable and feature rich logger.
metadata.gz.sig CHANGED
Binary file