cogger 0.24.1 → 0.25.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: 2c178fc1648e2a2cb5681f4606ea28841441004fdf6f7bc8d3794535fb32b3a0
4
- data.tar.gz: 13cbbd1098321e423ba912fc9c772854f47538229344a3a51651c7c126c86107
3
+ metadata.gz: 82eadd70b70fc632efb641adf780c4f68fa76786ec1f170343e2e0dcb909182c
4
+ data.tar.gz: 1b9f9159eb2e21950aec9a369a0272f68f4ae5111e104093ba491181f6c8edf3
5
5
  SHA512:
6
- metadata.gz: a4fa3db73c99e7ab46d3659dcce0279dcefb514c9537db0bdb22d17988c3d2da0cf69dfdb8afbbfb1197ecd10ee4df363ef4ad95c985663c467baa04579b997d
7
- data.tar.gz: f61da5f577ed2d9511d8655922bd7b816353f13d21c60ae969b92360bdb8fddf5c8ed00ca6ac356cb960f1340fa8adc07677e6a978dad0034a9719dd7cf34bdd
6
+ metadata.gz: b7d78ff5e80252151ab31e919d46a56bce0fc64a118b3f6d961953bd8a4c8d53c2ecd2f670ccb058129a3f91817ed5ed45cead216461e1a66f6ece33210d10ad
7
+ data.tar.gz: 45da02e73d70296f684f1de615f55a9ff37ca4df5ed0e31946af0951350a652f9936cd5d60032d0ab70dedd5093cd519f55feae961f830b9ef1dfbb31ff9603b
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -6,6 +6,7 @@
6
6
  :logger_link: link:https://rubyapi.org/o/s?q=Logger[Logger]
7
7
  :pattern_matching_link: link:https://alchemists.io/articles/ruby_pattern_matching[pattern matching]
8
8
  :rack_link: link:https://github.com/rack/rack[Rack]
9
+ :rfc_3339_link: link:https://datatracker.ietf.org/doc/html/rfc3339[RFC 3339]
9
10
  :tone_link: link:https://alchemists.io/projects/tone[Tone]
10
11
 
11
12
  = Cogger
@@ -27,7 +28,7 @@ toc::[]
27
28
 
28
29
  == Screenshots
29
30
 
30
- image::https://alchemists.io/images/projects/cogger/screenshots/demo.png[Rack,width=724,height=1118]
31
+ image::https://alchemists.io/images/projects/cogger/screenshots/demo.png[Rack,width=703,height=1151]
31
32
 
32
33
  == Requirements
33
34
 
@@ -102,7 +103,7 @@ logger.any { "Demo" } # ⚫️ [console] Demo
102
103
  logger.add(Logger::INFO) { "Demo" } # 🟢 [console] Demo
103
104
  ----
104
105
 
105
- The `[console]`, in the above output, is the program ID which, in this case, is the ID of this gem's IRB console.
106
+ The `[console]`, in the above output, is the program ID which is the ID of this gem's IRB console.
106
107
 
107
108
  === Initialization
108
109
 
@@ -112,7 +113,8 @@ When creating a new logger, you can configure behavior via the following attribu
112
113
  * `io`: The input/output stream. This can be `STDOUT/$stdout`, a file/path, or `nil`. Default: `$stdout`.
113
114
  * `level`: The log level you want to log at. Can be `:debug`, `:info`, `:warn`, `:error`, `:fatal`, or `:unknown`. Default: `:info`.
114
115
  * `formatter`: The formatter to use for formatting your log output. Default: `Cogger::Formatter::Color`. See the _Formatters_ section for more info.
115
- * `tags`: Global tagging for _every_ log entry which _must_ be an array of objects you wish to use for tagging purposes.
116
+ * `tags`: The global tags used for all log entries. _Must_ be an array of objects you wish to use for tagging purposes. Default: `[]`.
117
+ * `datetime_format`: The global date/time format used for all `Time`, `Date`, and/or `DateTime` values in your log entries. Default: `%Y-%m-%dT%H:%M:%S.%L%:z`.
116
118
  * `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`.
117
119
  * `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`.
118
120
  * `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).
@@ -131,6 +133,7 @@ logger = Cogger.new id: :demo,
131
133
  level: :debug,
132
134
  formatter: :json,
133
135
  tags: %w[DEMO DB],
136
+ datetime_format: "%Y-%m-%d",
134
137
  mode: false,
135
138
  age: 5,
136
139
  size: 1_000,
@@ -147,6 +150,23 @@ Cogger::LEVELS
147
150
  # ["debug", "info", "warn", "error", "fatal", "unknown"]
148
151
  ----
149
152
 
153
+ === Date/Time
154
+
155
+ The default date/time format used for _all_ log values can be viewed via the following:
156
+
157
+ [source,ruby]
158
+ ----
159
+ Cogger::DATETIME_FORMAT
160
+ # "%Y-%m-%dT%H:%M:%S.%L%:z
161
+ ----
162
+
163
+ The above adheres to {rfc_3339_link} and can be customized -- as mentioned earlier -- when creating a new logger instance. Example:
164
+
165
+ [source,ruby]
166
+ ----
167
+ Cogger.new datetime_format: "%Y-%m-%d"
168
+ ----
169
+
150
170
  === Environment
151
171
 
152
172
  You can use your environment to define the desired default log level. The default log level is: `"info"`. Although, you can set the log level to any of the following:
@@ -184,9 +204,104 @@ logger.level = Logger::WARN # 2
184
204
 
185
205
  Please see the {logger_link} documentation for more information.
186
206
 
207
+ === Emojis
208
+
209
+ Emojis can be used to decorate and add visual emphasis to your logs. Here are the defaults:
210
+
211
+ [source,ruby]
212
+ ----
213
+ Cogger.emojis
214
+
215
+ # {
216
+ # :debug => "🔎",
217
+ # :info => "🟢",
218
+ # :warn => "⚠️",
219
+ # :error => "🛑",
220
+ # :fatal => "🔥",
221
+ # :any => "⚫️"
222
+ # }
223
+ ----
224
+
225
+ The `:emoji` formatter is the default formatter which provides dynamic rendering of emojis based on log level. Example:
226
+
227
+ [source,ruby]
228
+ ----
229
+ logger = Cogger.new
230
+ logger.info "Demo"
231
+
232
+ # 🟢 [console] Demo
233
+ ----
234
+
235
+ To add multiple custom emojis, you can chain messages together when registering them:
236
+
237
+ [source,ruby]
238
+ ----
239
+ Cogger.add_emoji(:tada, "🎉")
240
+ .add_emoji :favorite, "❇️"
241
+ ----
242
+
243
+ If you always want to use the _same_ emoji, you could use the emoji formatter with a specific template:
244
+
245
+ [source,ruby]
246
+ ----
247
+ logger = Cogger.new formatter: Cogger::Formatters::Emoji.new("%<emoji:tada>s %<message:dynamic>s")
248
+
249
+ logger.info "Demo"
250
+ logger.warn "Demo"
251
+
252
+ # 🎉 Demo
253
+ # 🎉 Demo
254
+ ----
255
+
256
+ As you can see, using a specific emoji will _always_ display regardless of the current log level.
257
+
258
+ 💡 Emojis are used by the color and emoji formatters so check out the _Templates_ and _Formatters_ sections below to learn more.
259
+
260
+ === Aliases
261
+
262
+ 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:
263
+
264
+ [source,ruby]
265
+ ----
266
+ Cogger.add_alias :haze, :bold, :white, :on_purple
267
+ Cogger.aliases
268
+ ----
269
+
270
+ 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.
271
+
272
+ Aliases are a powerful way to customize colors via concise syntax in your templates. Building upon the aliases, added above, you'd be able to use them in your templates as follows:
273
+
274
+ [source,ruby]
275
+ ----
276
+ # Element
277
+ "<haze>%<message></haze>"
278
+
279
+ # Key
280
+ "%<message:haze>"
281
+ ----
282
+
283
+ 💡 Aliases are used by the color and emoji formatters so check out the {tone_link} documentation and/or _Templates_ and _Formatters_ sections below to learn more.
284
+
187
285
  === Templates
188
286
 
189
- Templates are used by all formatters and adhere to an _enhanced_ version of the {format_link} as used by `Kernel#format`. All specifiers, flags, width, and precision are supported except for the following restrictions:
287
+ Templates are used by all formatters and adhere to an _enhanced_ version of the {format_link} as used by `Kernel#format`. Here’s what is provided by default:
288
+
289
+ [source,ruby]
290
+ ----
291
+ Cogger.templates
292
+
293
+ # {
294
+ # :color => "<dynamic>[%<id>s]</dynamic> %<message:dynamic>s",
295
+ # :detail => "[%<id>s] [%<level>s] [%<at>s] %<message>s",
296
+ # :emoji => "%<emoji:dynamic>s <dynamic>[%<id>s]</dynamic> %<message:dynamic>s",
297
+ # :json => nil,
298
+ # :property => nil,
299
+ # :simple => "[%<id>s] %<message>s",
300
+ # :rack => "[%<id>s] [%<level>s] [%<at>s] %<verb>s %<status>s %<duration>s %<ip>s %<path>s %<length># s %<params>s"
301
+ # }
302
+ ----
303
+
304
+ All {format_link} specifiers, flags, width, and precision are supported except for the following restrictions:
190
305
 
191
306
  * 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}.
192
307
  * Use of the `n$` flag is prohibited because it's not compatible with the above.
@@ -209,7 +324,7 @@ Template keys works exactly as you'd expect when formatting a string using the {
209
324
  Each key can be _enhanced_ further by delimiting the key with a colon and supplying a directive. Directives can be any of the following:
210
325
 
211
326
  * *Dynamic*: Color is automatically calculated based on current log level.
212
- * *Literal*: Color is specific/static while ignoring current log level.
327
+ * *Specific*: Color is specific/static while ignoring current log level.
213
328
 
214
329
  Here's a few examples to illustrate:
215
330
 
@@ -218,7 +333,7 @@ Here's a few examples to illustrate:
218
333
  # Dynamic
219
334
  "%<level:dynamic>s %<at:dynamic>s %<id:dynamic>s %<message:dynamic>s"
220
335
 
221
- # Literal
336
+ # Specific
222
337
  "%<level:purple>s %<at:yellow>s %<id:cyan>s %<message:green>s"
223
338
  ----
224
339
 
@@ -237,7 +352,7 @@ Cogger.aliases
237
352
  # }
238
353
  ----
239
354
 
240
- In the literal example, the color is exactly what is specified which means the `level` is purple, `at` is yellow, `id` is cyan, and `message` is green. This is means you can mix-n-match dynamic and literal directives as desired:
355
+ In the specific example, the `level` is purple; `at` is yellow; `id` is cyan; and `message` is green. This is means you can mix-n-match dynamic and specific directives as desired:
241
356
 
242
357
  [source,ruby]
243
358
  ----
@@ -248,14 +363,14 @@ Assuming the current log level is _info_, then `level` is green; `at` is yellow;
248
363
 
249
364
  ==== Emojis
250
365
 
251
- Template emojis work similar to _keys_ but the `emoji` key is _special_ in that you can't use `emoji` as a key in your log messages. In other words the `emoji` key can only be used in templates. That said, emojis can be dynamic or literal. Example:
366
+ Template emojis work similar to _keys_ but the `emoji` key is _special_ in that you can't use `emoji` as a key in your log messages. In other words the `emoji` key can only be used in templates. That said, emojis can be dynamic or specific. Example:
252
367
 
253
368
  [source,ruby]
254
369
  ----
255
370
  # Dynamic
256
371
  "%<emoji:dynamic>s %<message:dynamic>s"
257
372
 
258
- # Literal
373
+ # Specific
259
374
  "%<emoji:any>s %<message:dynamic>s"
260
375
  ----
261
376
 
@@ -274,22 +389,22 @@ Cogger.emojis
274
389
  # }
275
390
  ----
276
391
 
277
- In the literal example, the emoji will be rendered exactly as defined.
392
+ In the specific example, the emoji will be rendered exactly as defined.
278
393
 
279
394
  ==== Elements
280
395
 
281
- Template elements are slightly different than _keys_ and _emojis_ in that they behave more like HTML elements. This means you can use open and close tags to use dynamic or literal colors. Example:
396
+ Template elements are slightly different than _keys_ and _emojis_ in that they behave more like HTML elements. This means you can use open and close tags to use dynamic or specific colors. Example:
282
397
 
283
398
  [source,ruby]
284
399
  ----
285
400
  # Dynamic
286
401
  "<dynamic>%<level>s %<at>s %<id>s %<message>s</dynamic>"
287
402
 
288
- # Literal
403
+ # Specific
289
404
  "<purple>%<level>s %<at>s %<id>s %<message>s</purple>"
290
405
  ----
291
406
 
292
- In the dynamic example, all characters within the template string will use the same color as determined by the current log level. In the literal example, all characters will be purple.
407
+ In the dynamic example, all characters within the template string will use the same color as determined by the current log level. In the specific example, all characters will be purple.
293
408
 
294
409
  Using template elements, in this manner, keeps your templates simple when needing to apply the same color to multiple characters at once.
295
410
 
@@ -321,89 +436,13 @@ Additional keys as provided by your message hash and/or tags can be customized a
321
436
 
322
437
  Template keys, emojis, and elements do have a few restrictions:
323
438
 
324
- * Use the special `emoji` key to provide dynamic or literal emoji logging.
439
+ * Use the special `emoji` key to provide dynamic or specific emoji logging.
325
440
  * Use the special `tags` key to provide tagged logging. More information on tags can be found later in this document.
326
441
  * Avoid supplying the same keys as the default keys. Example: `logger.info id: :bad, at: Time.now, level: :bogus`. This is because these keys will be ignored. In other words, you can't _override_ the default keys.
327
442
  * Avoid wrapping keys and/or emojis in elements because nesting isn't supported and can lead to strange output. Example: `<green>%<emoji:error>s %<id:dynamic>s</green>`.
328
443
  * Avoid wrapping elements within elements because nesting isn't supported and can lead to strange output. Example: `<dynamic><cyan>%<message>s</cyan></dynamic>`.
329
444
  * Avoid situations where a message hash doesn't match the keys in the template because an empty message will be logged instead. This applies to all formatters except the JSON formatter which will log any key/value that doesn't have a `nil` value.
330
445
 
331
- === Emojis
332
-
333
- In addition to coloring to your log output, you can add emojis as well. Here are the defaults:
334
-
335
- [source,ruby]
336
- ----
337
- Cogger.emojis
338
-
339
- # {
340
- # :debug => "🔎",
341
- # :info => "🟢",
342
- # :warn => "⚠️",
343
- # :error => "🛑",
344
- # :fatal => "🔥",
345
- # :any => "⚫️"
346
- # }
347
- ----
348
-
349
- The `:emoji` formatter is the default formatter which provides dynamic rendering of emojis based on log level. Example:
350
-
351
- [source,ruby]
352
- ----
353
- logger = Cogger.new
354
- logger.info "Demo"
355
-
356
- # 🟢 [console] Demo
357
- ----
358
-
359
- To add one or more emojis, you can chain messages together when registering them:
360
-
361
- [source,ruby]
362
- ----
363
- Cogger.add_emoji(:tada, "🎉")
364
- .add_emoji :favorite, "❇️"
365
- ----
366
-
367
- If you always want to use the _same_ emoji, you could use the emoji formatter with a specific template:
368
-
369
- [source,ruby]
370
- ----
371
- logger = Cogger.new formatter: Cogger::Formatters::Emoji.new("%<emoji:tada>s %<message:dynamic>s")
372
-
373
- logger.info "Demo"
374
- logger.warn "Demo"
375
-
376
- # 🎉 Demo
377
- # 🎉 Demo
378
- ----
379
-
380
- As you can see, using a specific and non-dynamic emoji will _always_ display regardless of the current log level.
381
-
382
- === Aliases
383
-
384
- 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:
385
-
386
- [source,ruby]
387
- ----
388
- Cogger.add_alias :haze, :bold, :white, :on_purple
389
- Cogger.aliases
390
- ----
391
-
392
- 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.
393
-
394
- 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:
395
-
396
- [source,ruby]
397
- ----
398
- # Universal
399
- "<haze>%<message></haze>"
400
-
401
- # Individual
402
- "%<message:haze>"
403
- ----
404
-
405
- 💡 These aliases are used by the color and emoji formatters but check out the {tone_link} documentation and _Formatters_ section below for further examples.
406
-
407
446
  === Formatters
408
447
 
409
448
  Multiple formatters are provided for you which can be further customized as needed. Here's what is provided by default:
@@ -413,28 +452,32 @@ Multiple formatters are provided for you which can be further customized as need
413
452
  Cogger.formatters
414
453
 
415
454
  # {
416
- # :color => [
417
- # Cogger::Formatters::Color < Object,
418
- # nil
455
+ # :color => [
456
+ # Cogger::Formatters::Color < Cogger::Formatters::Abstract,
457
+ # "<dynamic>[%<id>s]</dynamic> %<message:dynamic>s"
419
458
  # ],
420
- # :detail => [
421
- # Cogger::Formatters::Simple < Object,
459
+ # :detail => [
460
+ # Cogger::Formatters::Simple < Cogger::Formatters::Abstract,
422
461
  # "[%<id>s] [%<level>s] [%<at>s] %<message>s"
423
462
  # ],
424
- # :emoji => [
463
+ # :emoji => [
425
464
  # Cogger::Formatters::Emoji < Cogger::Formatters::Color,
426
- # nil
465
+ # "%<emoji:dynamic>s <dynamic>[%<id>s]</dynamic> %<message:dynamic>s"
427
466
  # ],
428
- # :json => [
429
- # Cogger::Formatters::JSON < Object,
467
+ # :json => [
468
+ # Cogger::Formatters::JSON < Cogger::Formatters::Abstract,
430
469
  # nil
431
470
  # ],
432
- # :simple => [
433
- # Cogger::Formatters::Simple < Object,
471
+ # :property => [
472
+ # Cogger::Formatters::Property < Cogger::Formatters::Abstract,
434
473
  # nil
435
474
  # ],
436
- # :rack => [
437
- # Cogger::Formatters::Simple < Object,
475
+ # :simple => [
476
+ # Cogger::Formatters::Simple < Cogger::Formatters::Abstract,
477
+ # "[%<id>s] %<message>s"
478
+ # ],
479
+ # :rack => [
480
+ # Cogger::Formatters::Simple < Cogger::Formatters::Abstract,
438
481
  # "[%<id>s] [%<level>s] [%<at>s] %<verb>s %<status>s %<duration>s %<ip>s %<path>s %<length>s # %<params>s"
439
482
  # ]
440
483
  # }
@@ -457,28 +500,13 @@ Cogger.get_formatter :bogus
457
500
  # Unregistered formatter: bogus. (KeyError)
458
501
  ----
459
502
 
460
- 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:
461
-
462
- [source,ruby]
463
- ----
464
- Cogger::Formatters::Color::TEMPLATE
465
- # "<dynamic>[%<id>s]</dynamic> %<message:dynamic>s"
466
-
467
- Cogger::Formatters::Emoji::TEMPLATE
468
- # "%<emoji:dynamic>s <dynamic>[%<id>s]</dynamic> %<message:dynamic>s"
469
-
470
- Cogger::Formatters::JSON::TEMPLATE
471
- # nil
472
-
473
- Cogger::Formatters::Simple::TEMPLATE
474
- # "[%<id>s] %<message>s"
475
- ----
503
+ 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 via `Cogger.templates` as mentioned earlier.
476
504
 
477
505
  💡 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.
478
506
 
479
507
  ==== Simple
480
508
 
481
- 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:
509
+ The simple formatter is a bare bones formatter that uses no color information and only supports basic {format_link} as mentioned in the _Templates_ section earlier. Example:
482
510
 
483
511
  [source,ruby]
484
512
  ----
@@ -591,9 +619,76 @@ This formatter is the _Simple_ formatter with a different template and can be co
591
619
  logger = Cogger.new formatter: :detail
592
620
  ----
593
621
 
622
+ ==== Property
623
+
624
+ This formatter is similar in behavior to the _simple_ formatter except the template allows you to _order_ the layout of your keys. All other template information is ignored. Example:
625
+
626
+ *Default Order*
627
+
628
+ [source,ruby]
629
+ ----
630
+ logger = Cogger.new formatter: :property
631
+
632
+ logger.info verb: "GET", path: "/"
633
+ # id=console level=INFO at=2024-08-28T14:47:09.447-06:00 verb=GET path=/
634
+ ----
635
+
636
+ *Custom Order*
637
+
638
+ [source,ruby]
639
+ ----
640
+ logger = Cogger.new formatter: Cogger::Formatters::Property.new("%<level>s %<verb>s")
641
+
642
+ logger.info verb: "GET", path: "/"
643
+ # level=INFO verb=GET id=console at=2024-08-28T14:49:13.861-06:00 path=/
644
+ ----
645
+
646
+ 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.
647
+
648
+ You can always supply a message as your first argument -- or specify it by using the `:message` key -- but is removed if not supplied which is why the above doesn't print a message in the output. To illustrate, the following are equivalent:
649
+
650
+ [source,ruby]
651
+ ----
652
+ logger = Cogger.new formatter: :property
653
+
654
+ logger.info "Demo"
655
+ id=console level=INFO at=2024-08-28T14:50:01.990-06:00 message=Demo
656
+
657
+ logger.info message: "demo"
658
+ # id=console level=INFO at=2024-08-28T14:50:25.344-06:00 message=demo
659
+ ----
660
+
661
+ 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:
662
+
663
+ [source,ruby]
664
+ ----
665
+ logger = Cogger.new formatter: :property
666
+
667
+ logger.info "Demo", tags: ["WEB", "PRIMARY", {service: :api, demo: true}]
668
+ # id=console
669
+ # level=INFO
670
+ # at=2024-08-28T14:51:06.600-06:00
671
+ # message=Demo
672
+ # tags="[WEB, PRIMARY]"
673
+ # service=api
674
+ # demo=true
675
+ ----
676
+
677
+ Notice, with the above, that the single tags of `WEB` and `PRIMARY` show up in the `tags` stringified 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 output, this means you can use a custom template to arrange the order of these keys if you don't like the default.
678
+
679
+ Emojis, spaces, tabs, new lines, and control characters will all be escaped and wrapped in quotes if detected for any value. Here's where the message has the special characters but this formatting would be applied to any value.
680
+
681
+ [source,ruby]
682
+ ----
683
+ logger = Cogger.new formatter: :property
684
+
685
+ logger.info "☀️ An example.\t\n \x1F"
686
+ # id=console level=INFO at=2024-08-28T15:03:24.107-06:00 message="\u2600\uFE0F An example.\t\n \x1F"
687
+ ----
688
+
594
689
  ==== JSON
595
690
 
596
- 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:
691
+ This formatter is similar in behavior to the _property_ formatter because you can _order_ the layout of your keys. All other template information is ignored, only the order of your template keys matters. Example:
597
692
 
598
693
  *Default Order*
599
694
 
@@ -671,7 +766,7 @@ require "logger"
671
766
  logger = Cogger.new formatter: Logger::Formatter.new
672
767
  logger.info "Demo"
673
768
 
674
- # 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={}>
769
+ # I, [2024-08-28T15:57:31.930722 #69391] INFO -- console: #<data Cogger::Entry id="console", level=:INFO, at=2024-08-28 15:57:31.930696 -0600, message="Demo", tags=[], datetime_format="%Y-%m-%dT%H:%M:%S.%L%:z", payload={}>
675
770
  ----
676
771
 
677
772
  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 use the `Simple` formatter as follows:
@@ -691,31 +786,36 @@ The above is the rough equivalent of what {logger_link} provides for you by defa
691
786
 
692
787
  ==== Custom
693
788
 
694
- 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:
789
+ Should none of the built-in formatters be to your liking, you can implement, use, and/or register a custom formatter as well. A minimum implementation would be to inherit from the `Abstract` superclass as follows:
695
790
 
696
791
  [source,ruby]
697
792
  ----
698
- class MyFormatter
793
+ class MyFormatter < Cogger::Formatters::Abstract
699
794
  TEMPLATE = "%<message>s"
700
795
 
701
- def initialize template = TEMPLATE, sanitizer: Kit::Sanitizer.new
796
+ def initialize template = TEMPLATE
797
+ super()
702
798
  @template = template
703
- @sanitizer = sanitizer
704
799
  end
705
800
 
706
- def call(*input) = "#{format template, sanitizer.call(*input)}\n"
801
+ def call(*input)
802
+ *, entry = input
803
+ attributes = sanitize entry, :tagged
804
+
805
+ "#{format(template, attributes).tap(&:strip!)}\n"
806
+ end
707
807
 
708
808
  private
709
809
 
710
- attr_reader :template, :sanitizer
810
+ attr_reader :template
711
811
  end
712
812
  ----
713
813
 
714
- 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.
814
+ There is no restriction on the dependencies you might want to inject into your custom formatter but -- at a minimum -- you'll want to provide a default template so it can be sanitized by the superclass. 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.
715
815
 
716
816
  === Tags
717
817
 
718
- Tags allow you to tag your messages at both a global and local (i.e. per message) level. For example, here's a single global tag:
818
+ Tags allow you to tag your messages at both a global and local (i.e. per message) level. _Please note that tags are mostly universal in behavior but can differ based on formatter used._ For example, here's a single global tag:
719
819
 
720
820
  [source,ruby]
721
821
  ----
@@ -803,11 +903,11 @@ logger = Cogger.new formatter: :json
803
903
  logger.info login: "jayne", password: "secret"
804
904
 
805
905
  # {
806
- # "id":"console",
807
- # "level":"INFO",
808
- # "at":"2023-10-18 19:21:40 -0600",
809
- # "login":"jayne",
810
- # "password":"[FILTERED]"
906
+ # "id": "console",
907
+ # "level": "INFO",
908
+ # "at": "2024-08-28T16:09:26.132-06:00",
909
+ # "login": "jayne",
910
+ # "password": "[FILTERED]"
811
911
  # }
812
912
  ----
813
913
 
@@ -848,8 +948,8 @@ logger.info "Demo"
848
948
 
849
949
  # 🟢 [console] Demo
850
950
  # [console] Demo
851
- # [console] [INFO] [2024-06-16 15:09:38 -0600] Demo
852
- # {"id":"console","level":"INFO","at":"2024-06-16T21:09:38.896+00:00","message":"Demo"}
951
+ # [console] [INFO] [2024-08-28T16:10:27.833-06:00] Demo
952
+ # {"id":"console","level":"INFO","at":"2024-08-28T16:10:27.833-06:00","message":"Demo"}
853
953
  # [console] Demo
854
954
  ----
855
955
 
@@ -1029,6 +1129,7 @@ logger.inspect
1029
1129
  # @io=IO,
1030
1130
  # @level=1,
1031
1131
  # @formatter=Cogger::Formatters::Emoji,
1132
+ # @datetime_format=\"%Y-%m-%dT%H:%M:%S.%L%:z\",
1032
1133
  # @tags=[],
1033
1134
  # @mode=false,
1034
1135
  # @age=0,
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.24.1"
5
+ spec.version = "0.25.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/cogger"
@@ -11,6 +11,7 @@ module Cogger
11
11
  :io,
12
12
  :level,
13
13
  :formatter,
14
+ :datetime_format,
14
15
  :tags,
15
16
  :mode,
16
17
  :age,
@@ -25,6 +26,7 @@ module Cogger
25
26
  io: $stdout,
26
27
  level: Level.call,
27
28
  formatter: Formatters::Emoji.new,
29
+ datetime_format: DATETIME_FORMAT,
28
30
  tags: Core::EMPTY_ARRAY,
29
31
  mode: false,
30
32
  age: 0,
@@ -45,15 +47,16 @@ module Cogger
45
47
  progname: id,
46
48
  level:,
47
49
  formatter:,
50
+ datetime_format:,
48
51
  binmode: mode,
49
52
  shift_period_suffix: suffix
50
53
  end
51
54
 
52
55
  def inspect
53
56
  "#<#{self.class} @id=#{id}, @io=#{io.class}, @level=#{level}, " \
54
- "@formatter=#{formatter.class}, @tags=#{tags.inspect}, " \
55
- "@mode=#{mode}, @age=#{age}, @size=#{size}, @suffix=#{suffix.inspect}, " \
56
- "@entry=#{entry}, @logger=#{logger}>"
57
+ "@formatter=#{formatter.class}, @datetime_format=#{datetime_format.inspect}, " \
58
+ "@tags=#{tags.inspect}, @mode=#{mode}, @age=#{age}, @size=#{size}, " \
59
+ "@suffix=#{suffix.inspect}, @entry=#{entry}, @logger=#{logger}>"
57
60
  end
58
61
  end
59
62
  end
data/lib/cogger/entry.rb CHANGED
@@ -4,19 +4,21 @@ 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, :level, :at, :message, :tags, :payload do
7
+ Entry = Data.define :id, :level, :at, :message, :tags, :datetime_format, :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)),
14
+ datetime_format: payload.delete(:datetime_format) || DATETIME_FORMAT,
14
15
  payload:
15
16
  end
16
17
 
17
- def self.for_crash message, error, id:
18
+ def self.for_crash message, error, id:, at: ::Time.now
18
19
  new id:,
19
20
  level: "FATAL",
21
+ at:,
20
22
  message:,
21
23
  payload: {
22
24
  error_message: error.message,
@@ -30,6 +32,7 @@ module Cogger
30
32
  at: ::Time.now,
31
33
  message: nil,
32
34
  tags: Core::EMPTY_ARRAY,
35
+ datetime_format: DATETIME_FORMAT,
33
36
  payload: Core::EMPTY_HASH
34
37
  super
35
38
  end