cogger 0.20.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.adoc +170 -118
- data/cogger.gemspec +2 -2
- data/lib/cogger/entry.rb +6 -6
- data/lib/cogger/formatters/color.rb +1 -1
- data/lib/cogger/formatters/crash.rb +1 -1
- data/lib/cogger/formatters/emoji.rb +1 -1
- data/lib/cogger/formatters/kit/colorizer.rb +2 -2
- data/lib/cogger/formatters/simple.rb +1 -1
- data/lib/cogger/hub.rb +7 -7
- data/lib/cogger/registry.rb +9 -5
- data.tar.gz.sig +0 -0
- metadata +5 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27b6a9a59fe330393a4d81ce97ae08be93fa89231eeabc872c89d521525f09ea
|
4
|
+
data.tar.gz: 00a17bfc9a2db66e33ce2e48eab961a131f69fbbdb2b8d6ed24bbd4b423fbf33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 534dce93e4bb50e37b769f9a4078fd0d9450663d2e82c98d8b7f121beb96ee2a3832cc43929e9478e7ce7c171e500aaa015d7b787eb0a82d8a1638188490a707
|
7
|
+
data.tar.gz: bc43a0d84c1a4b6090374965d54034d7f92ec55852b49cb71e7f4545cbd76357b37877f31de88f360af08650bc9d8a636fdd5fc59f255e78fbb3780b584d92b6
|
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
|
23
|
-
* Provides customizable formatters for simple, color, JSON, and/or custom
|
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
|
-
|
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
|
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" #
|
109
|
-
logger.info "Demo" #
|
110
|
-
logger.warn "Demo" #
|
111
|
-
logger.error "Demo" #
|
112
|
-
logger.fatal "Demo" #
|
113
|
-
logger.unknown "Demo" #
|
114
|
-
logger.any "Demo" #
|
115
|
-
logger.add Logger::INFO, "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" } #
|
119
|
-
logger.info { "Demo" } #
|
120
|
-
logger.warn { "Demo" } #
|
121
|
-
logger.error { "Demo" } #
|
122
|
-
logger.fatal { "Demo" } #
|
123
|
-
logger.unknown { "Demo" } #
|
124
|
-
logger.any { "Demo" } #
|
125
|
-
logger.add(Logger::INFO) { "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
|
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
|
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
|
220
|
-
"<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>%<
|
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
|
226
|
-
"%<
|
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
|
-
"%<
|
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 (`<
|
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
|
244
|
-
* *Specific*: A specific directive means the color you use will be applied without any further processing regardless of
|
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`:
|
249
|
-
* `
|
250
|
-
* `at`:
|
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,
|
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
|
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
|
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
|
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] [%<
|
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] [%<
|
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
|
-
|
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, "%<
|
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.
|
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
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
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
|
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
|
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
|
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","
|
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("%<
|
524
|
+
logger = Cogger.new formatter: Cogger::Formatters::JSON.new("%<level>s %<verb>s")
|
525
525
|
|
526
526
|
logger.info verb: "GET", path: "/"
|
527
|
-
# {"
|
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","
|
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","
|
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
|
-
# "
|
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",
|
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
|
-
"%<
|
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. `
|
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
|
-
# "
|
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] [
|
754
|
-
# {"id":"console","
|
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
|
-
"
|
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:
|
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
|
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 "#
|
946
|
-
it "logs
|
947
|
-
demo.
|
948
|
-
expect(logger.reread).to include("
|
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.
|
5
|
+
spec.version = "0.22.0"
|
6
6
|
spec.authors = ["Brooke Kuhlmann"]
|
7
7
|
spec.email = ["brooke@alchemists.io"]
|
8
8
|
spec.homepage = "https://alchemists.io/projects/cogger"
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
|
25
25
|
spec.required_ruby_version = "~> 3.3"
|
26
26
|
spec.add_dependency "core", "~> 1.0"
|
27
|
-
spec.add_dependency "refinements", "~> 12.
|
27
|
+
spec.add_dependency "refinements", "~> 12.5"
|
28
28
|
spec.add_dependency "tone", "~> 1.0"
|
29
29
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
30
30
|
|
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, :
|
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
|
-
|
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
|
-
|
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
|
-
|
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:,
|
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:,
|
44
|
+
{id:, level:, at:, message:, **computed_tags.to_h, **payload}
|
45
45
|
end
|
46
46
|
|
47
47
|
def tagged tagger: Tag
|
@@ -3,9 +3,9 @@
|
|
3
3
|
module Cogger
|
4
4
|
module Formatters
|
5
5
|
module Kit
|
6
|
-
# Transform color based on dynamic (
|
6
|
+
# Transform color based on dynamic (level) or standard color preference.
|
7
7
|
Colorizer = lambda do |value, attributes|
|
8
|
-
value == "dynamic" ? attributes[:
|
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(
|
71
|
-
log(Logger::SEV_LABEL.fetch(
|
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(
|
98
|
-
dispatch(
|
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(
|
103
|
+
def dispatch(level, message, **payload, &)
|
104
104
|
entry = configuration.entry.for(
|
105
105
|
message,
|
106
106
|
id: configuration.id,
|
107
|
-
|
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
|
113
|
+
mutex.synchronize { streams.each { |logger| logger.public_send level, entry } }
|
114
114
|
true
|
115
115
|
end
|
116
116
|
|
data/lib/cogger/registry.rb
CHANGED
@@ -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] [%<
|
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] [%<
|
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
|
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
|
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.
|
4
|
+
version: 0.22.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-
|
38
|
+
date: 2024-07-08 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: core
|
@@ -57,14 +57,14 @@ dependencies:
|
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: '12.
|
60
|
+
version: '12.5'
|
61
61
|
type: :runtime
|
62
62
|
prerelease: false
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '12.
|
67
|
+
version: '12.5'
|
68
68
|
- !ruby/object:Gem::Dependency
|
69
69
|
name: tone
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
@@ -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.
|
158
|
+
rubygems_version: 3.5.14
|
159
159
|
signing_key:
|
160
160
|
specification_version: 4
|
161
161
|
summary: A customizable and feature rich logger.
|
metadata.gz.sig
CHANGED
Binary file
|