cogger 0.11.0 → 0.13.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: d529b8e4d8dd9fc3197a9e693e17cfcfc9cdadc4a5910f560a0bb50c5b0a5a02
4
- data.tar.gz: 652d74a7778cc22c4219c8051b5dfd24691ed959bdb2108f678282ed279cec41
3
+ metadata.gz: 57f5049812c9af7fd2f1f936ac37c85562fad47517f6b3d2ccd2e34e2d1ee691
4
+ data.tar.gz: 2ecc0b1bd9e9cc37c85ee9f8db19c936b47d65a71b4723631f96debcdbd4b23e
5
5
  SHA512:
6
- metadata.gz: 5cff486456ad103849b33360e4e660bb0837626e92a5debca5380977804ad877100878dbd2b8abc4e89840caa0e20445df24883ac79890feac8a8fc367ca7985
7
- data.tar.gz: 841a17616a1aa5fb1ed1c7848d8b2f9237926993cf911910e12fe00b4d7c7b991a86bcc36ac404b976eadd006903a4e65dd94bef96113a296dcf82575ed88200
6
+ metadata.gz: 4318c120bb3182a8a0740025b1528a6643b876b3d0ff71e3b875304484b4da5df44af044d474e2d93cacd1807487560063ac5e4d8499ef514a42c1c5644573a6
7
+ data.tar.gz: 7018412ed2a90da5e9fc31931e203d76767f405ff1559644570382891ccdb412c19c30eb2bb86f56f52be4e624f2938decb8f00c5fbf50feaf11735cf2e9f8bc
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -21,33 +21,34 @@ toc::[]
21
21
  * Provides customizable templates which leverage the native {format_link}.
22
22
  * Provides customizable formatters for simple, color, JSON, and/or custom output.
23
23
  * Provides multiple streams so you can log the same information to several outputs at once.
24
+ * Provides global and individual log entry tagging.
24
25
  * Provides filtering of sensitive information.
25
26
 
26
27
  == Screenshots
27
28
 
28
29
  *Emoji*
29
30
 
30
- image::https://alchemists.io/images/projects/cogger/screenshots/emoji.png[Emoji,width=204,height=251]
31
+ image::https://alchemists.io/images/projects/cogger/screenshots/emoji.png[Emoji,width=234,height=293]
31
32
 
32
33
  *Color*
33
34
 
34
- image::https://alchemists.io/images/projects/cogger/screenshots/color.png[Color,width=181,height=247]
35
+ image::https://alchemists.io/images/projects/cogger/screenshots/color.png[Color,width=202,height=288]
35
36
 
36
37
  *Simple*
37
38
 
38
- image::https://alchemists.io/images/projects/cogger/screenshots/simple.png[Simple,width=274,height=253]
39
+ image::https://alchemists.io/images/projects/cogger/screenshots/simple.png[Simple,width=288,height=253]
39
40
 
40
41
  *Detail*
41
42
 
42
- image::https://alchemists.io/images/projects/cogger/screenshots/detail.png[Detail,width=476,height=256]
43
+ image::https://alchemists.io/images/projects/cogger/screenshots/detail.png[Detail,width=611,height=284]
43
44
 
44
45
  *JSON*
45
46
 
46
- image::https://alchemists.io/images/projects/cogger/screenshots/json.png[JSON,width=929,height=256]
47
+ image::https://alchemists.io/images/projects/cogger/screenshots/json.png[JSON,width=962,height=297]
47
48
 
48
49
  *Rack*
49
50
 
50
- image::https://alchemists.io/images/projects/cogger/screenshots/rack.png[Rack,width=656,height=252]
51
+ image::https://alchemists.io/images/projects/cogger/screenshots/rack.png[Rack,width=883,height=282]
51
52
 
52
53
  == Requirements
53
54
 
@@ -92,7 +93,7 @@ All interaction is provided by `Cogger` which can be used as follows:
92
93
  [source,ruby]
93
94
  ----
94
95
  logger = Cogger.new
95
- logger.info "demo" # "demo"
96
+ logger.info "Demo" # "Demo"
96
97
  ----
97
98
 
98
99
  If you set your logging level to `debug`, you can walk through each level:
@@ -102,22 +103,24 @@ If you set your logging level to `debug`, you can walk through each level:
102
103
  logger = Cogger.new level: :debug
103
104
 
104
105
  # Without blocks.
105
- logger.debug "demo" # "demo"
106
- logger.info "demo" # "demo"
107
- logger.warn "demo" # "demo"
108
- logger.error "demo" # "demo"
109
- logger.fatal "demo" # "demo"
110
- logger.unknown "demo" # "demo"
111
- logger.any "demo" # "demo"
106
+ logger.debug "Demo" # "🔎 Demo"
107
+ logger.info "Demo" # "🟢 Demo"
108
+ logger.warn "Demo" # "⚠️ Demo"
109
+ logger.error "Demo" # "🛑 Demo"
110
+ logger.fatal "Demo" # "🔥 Demo"
111
+ logger.unknown "Demo" # "⚫️ Demo"
112
+ logger.any "Demo" # "⚫️ Demo"
113
+ logger.add Logger::INFO, "Demo" # "🟢 Demo"
112
114
 
113
115
  # With blocks.
114
- logger.debug { "demo" } # "demo"
115
- logger.info { "demo" } # "demo"
116
- logger.warn { "demo" } # "demo"
117
- logger.error { "demo" } # "demo"
118
- logger.fatal { "demo" } # "demo"
119
- logger.unknown { "demo" } # "demo"
120
- logger.any { "demo" } # "demo"
116
+ logger.debug { "Demo" } # "🔎 Demo"
117
+ logger.info { "Demo" } # "🟢 Demo"
118
+ logger.warn { "Demo" } # "⚠️ Demo"
119
+ logger.error { "Demo" } # "🛑 Demo"
120
+ logger.fatal { "Demo" } # "🔥 Demo"
121
+ logger.unknown { "Demo" } # "⚫️ Demo"
122
+ logger.any { "Demo" } # "⚫️ Demo"
123
+ logger.add(Logger::INFO) { "Demo" } # "🟢 Demo"
121
124
  ----
122
125
 
123
126
  === Initialization
@@ -128,6 +131,7 @@ When creating a new logger, you can configure behavior via the following attribu
128
131
  * `io`: The input/output stream. This can be `STDOUT/$stdout`, a file/path, or `nil`. Default: `$stdout`.
129
132
  * `level`: The severity level you want to log at. Can be `:debug`, `:info`, `:warn`, `:error`, `:fatal`, or `:unknown`. Default: `:info`.
130
133
  * `formatter`: The formatter to use for formatting your log output. Default: `Cogger::Formatter::Color`. See the _Formatters_ section for more info.
134
+ * `tags`: Global tagging for _every_ log entry which _must_ be an array of objects you wish to use for tagging purposes.
131
135
  * `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`.
132
136
  * `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`.
133
137
  * `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).
@@ -144,12 +148,80 @@ logger = Cogger.new
144
148
  logger = Cogger.new id: :demo,
145
149
  io: "demo.log",
146
150
  level: :debug,
151
+ formatter: :json,
152
+ tags: %w[DEMO DB],
147
153
  mode: false,
148
154
  age: 5,
149
155
  size: 1_000,
150
156
  suffix: "%Y"
151
157
  ----
152
158
 
159
+ === Inspection
160
+
161
+ Each instance can be inspected via the `#inspect` message:
162
+
163
+ [source,ruby]
164
+ ----
165
+ logger = Cogger.new
166
+ logger.inspect
167
+
168
+ # "#<Cogger::Hub @id=console,
169
+ # @io=IO,
170
+ # @level=1,
171
+ # @formatter=Cogger::Formatters::Emoji,
172
+ # @tags=[],
173
+ # @mode=false,
174
+ # @age=0,
175
+ # @size=1048576,
176
+ # @suffix=\"%Y-%m-%d\",
177
+ # @entry=Cogger::Entry,
178
+ # @logger=Logger>"
179
+ ----
180
+
181
+ You can also look at individual attributes:
182
+
183
+ [source,ruby]
184
+ ----
185
+ logger = Cogger.new
186
+
187
+ logger.id # "console"
188
+ logger.io # #<IO:<STDOUT>>
189
+ logger.tags # []
190
+ logger.mode # false
191
+ logger.age # 0
192
+ logger.size # 1048576
193
+ logger.suffix # "%Y-%m-%d"
194
+
195
+ logger.level # 1
196
+ logger.formatter # Cogger::Formatters::Emoji
197
+ logger.debug? # false
198
+ logger.info? # true
199
+ logger.warn? # true
200
+ logger.error? # true
201
+ logger.fatal? # true
202
+ ----
203
+
204
+ === Mutations
205
+
206
+ Each instance can be mutated using the following messages:
207
+
208
+ [source,ruby]
209
+ ----
210
+ logger = Cogger.new io: StringIO.new
211
+
212
+ logger.close # nil
213
+ logger.reopen # Logger
214
+ logger.debug! # 0
215
+ logger.info! # 1
216
+ logger.warn! # 2
217
+ logger.error! # 3
218
+ logger.fatal! # 4
219
+ logger.formatter = Cogger::Formatters::Simple.new # Cogger::Formatters::Simple
220
+ logger.level = Logger::WARN # 2
221
+ ----
222
+
223
+ Please see the {logger_link} documentation for more information.
224
+
153
225
  === Environment
154
226
 
155
227
  The default log level is `INFO` but can be customized via your environment. For instance, you could
@@ -174,7 +246,7 @@ Templates are used by all formatters and adhere to {format_link} as used by `Ker
174
246
  - 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}.
175
247
  - Use of the `n$` flag is prohibited because this isn't compatible with the above.
176
248
 
177
- In addition to the above, the {format_link} is further enhanced with the use of _universal_ and _individual_ directives which are primarily used by the _color_ formatter but might prove useful for other formatters. Example:
249
+ 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:
178
250
 
179
251
  [source,ruby]
180
252
  ----
@@ -213,7 +285,7 @@ At this point, you might have gathered that there are specific keys you can use
213
285
 
214
286
  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.
215
287
 
216
- The last key (or keys) is variable and customizable to your needs which is the log event message. Here a couple of examples to illustrate:
288
+ 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:
217
289
 
218
290
  [source,ruby]
219
291
  ----
@@ -247,35 +319,38 @@ Cogger.emojis
247
319
  # }
248
320
  ----
249
321
 
250
- To add an emoji, use:
322
+ The `:emoji` formatter is the default formatter which provides dynamic rendering of emojis based on severity level. Example:
251
323
 
252
324
  [source,ruby]
253
325
  ----
254
- Cogger.add_emoji(:tada, "🎉")
255
- .add_emoji :favorite, "❇️"
326
+ logger = Cogger.new
327
+ logger.info "Demo"
328
+
329
+ # 🟢 Demo
256
330
  ----
257
331
 
258
- By default, the `:emoji` formatter provides dynamic rendering of emojis based on severity level. Example:
332
+ To add one or more emojis, you can chain messages together when registering them:
259
333
 
260
334
  [source,ruby]
261
335
  ----
262
- logger = Cogger.new formatter: :emoji
263
- logger.info "demo"
264
-
265
- # 🟢 demo
336
+ Cogger.add_emoji(:tada, "🎉")
337
+ .add_emoji :favorite, "❇️"
266
338
  ----
267
339
 
268
- If you wanted to use a specific emoji, you could use the color formatter with a specific template:
340
+ If you always want to use the _same_ emoji, you could use the emoji formatter with a specific template:
269
341
 
270
342
  [source,ruby]
271
343
  ----
272
- logger = Cogger.new formatter: Cogger::Formatters::Color.new("%<emoji:tada>s %<message:dynamic>s")
273
- logger.info "demo"
344
+ logger = Cogger.new formatter: Cogger::Formatters::Emoji.new("%<emoji:tada>s %<message:dynamic>s")
274
345
 
275
- # 🎉 demo
346
+ logger.info "Demo"
347
+ logger.warn "Demo"
348
+
349
+ # 🎉 Demo
350
+ # 🎉 Demo
276
351
  ----
277
352
 
278
- Keep in mind that using a specific, non-dynamic, emoji will _always_ display no matter the current severity level.
353
+ As you can see, using a specific and non-dynamic emoji will _always_ display regardless of the current severity level.
279
354
 
280
355
  === Aliases
281
356
 
@@ -300,7 +375,7 @@ Aliases are a powerful way to customize your colors and use short syntax in your
300
375
  "%<message:haze>"
301
376
  ----
302
377
 
303
- Check out the {tone_link} documentation for further examples.
378
+ 💡 These aliases are used by the color and emoji formatters but check out the {tone_link} documentation and _Formatters_ section below for further examples.
304
379
 
305
380
  === Formatters
306
381
 
@@ -320,8 +395,8 @@ Cogger.formatters
320
395
  # "[%<id>s] [%<severity>s] [%<at>s] %<message>s"
321
396
  # ],
322
397
  # :emoji => [
323
- # Cogger::Formatters::Color < Object,
324
- # "%<emoji:dynamic>s% <message:dynamic>s"
398
+ # Cogger::Formatters::Emoji < Cogger::Formatters::Color,
399
+ # nil
325
400
  # ],
326
401
  # :json => [
327
402
  # Cogger::Formatters::JSON < Object,
@@ -342,10 +417,10 @@ You can add a formatter by providing a key, class, and _optional_ template. If a
342
417
 
343
418
  [source,ruby]
344
419
  ----
345
- # Add
420
+ # Registration
346
421
  Cogger.add_formatter :basic, Cogger::Formatters::Simple, "%<severity>s %<message>s"
347
422
 
348
- # Get
423
+ # Usage
349
424
  Cogger.get_formatter :basic
350
425
  # [Cogger::Formatters::Simple, "%<severity>s %<message>s"]
351
426
  ----
@@ -354,8 +429,10 @@ Symbols or strings can be used interchangeably when adding/getting formatters. A
354
429
 
355
430
  [source,ruby]
356
431
  ----
357
- Cogger::Formatters::Simple::TEMPLATE
358
- # "%<message>s"
432
+ Cogger::Formatters::Color::TEMPLATE # "%<message:dynamic>s"
433
+ Cogger::Formatters::Emoji::TEMPLATE # "%<emoji:dynamic>s %<message:dynamic>s"
434
+ Cogger::Formatters::JSON::TEMPLATE # nil
435
+ Cogger::Formatters::Simple::TEMPLATE # "%<message>s"
359
436
  ----
360
437
 
361
438
  💡 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.
@@ -375,18 +452,14 @@ logger = Cogger.new formatter: :rack
375
452
 
376
453
  ==== Color
377
454
 
378
- The color formatter is enabled by default and is the equivalent of initializing with either of the following:
455
+ The color formatter allows you to have color coded logs and can be configured as follows:
379
456
 
380
457
  [source,ruby]
381
458
  ----
382
- logger = Cogger.new
383
- logger = Cogger.new formatter: Cogger::Formatters::Color.new
384
- logger = Cogger.new formatter: Cogger::Formatters::Color.new("%<message:dynamic>s")
459
+ logger = Cogger.new formatter: :color
385
460
  ----
386
461
 
387
- All three of the above examples are identical so you can start to see how different formatters can be used and customized further. Please refer back to the _Templates_ section on how to customize this formatter with more sophisticated templates.
388
-
389
- In addition to template customization, you can customize your color aliases as well. Default colors are provided by {tone_link} which are _aliased_ by log level:
462
+ Please refer back to the _Templates_ section on how to customize this formatter with more sophisticated templates. In addition to template customization, you can customize your color aliases as well. Default colors are provided by {tone_link} which are _aliased_ by log level:
390
463
 
391
464
  [source,ruby]
392
465
  ----
@@ -417,21 +490,71 @@ Once an alias is added, it can be immediately applied via the template of your f
417
490
  logger = Cogger.new formatter: Cogger::Formatters::Color.new("<mystery>%<message>s</mystery>")
418
491
  ----
419
492
 
420
- ℹ️ Much like the simple formatter, any leading or trailing whitespace is automatically after the template has been formatted.
493
+ ℹ️ Much like the simple formatter, any leading or trailing whitespace is automatically removed after the template has been formatted.
494
+
495
+ ==== Emoji
496
+
497
+ The emoji formatter is enabled by default and is the equivalent of initializing with either of the following:
498
+
499
+ [source,ruby]
500
+ ----
501
+ logger = Cogger.new
502
+ logger = Cogger.new formatter: :emoji
503
+ logger = Cogger.new formatter: Cogger::Formatters::Emoji.new("%<emoji:dynamic>s %<message:dynamic>s")
504
+ ----
505
+
506
+ All of the above examples are identical so you can see how different formatters can be used and customized further. The default emojis are registered as follows:
507
+
508
+ [source,ruby]
509
+ ----
510
+ Cogger.emojis
511
+
512
+ # {
513
+ # :debug => "🔎",
514
+ # :info => "🟢",
515
+ # :warn => "⚠️ ",
516
+ # :error => "🛑",
517
+ # :fatal => "🔥",
518
+ # :any => "⚫️"
519
+ # }
520
+ ----
521
+
522
+ This allows an emoji to be dynamically applied based on log severity. You can add or modify aliases as follows:
523
+
524
+ [source,ruby]
525
+ ----
526
+ Cogger.add_emoji :warn, "🟡"
527
+ ----
528
+
529
+ Once an alias is added/updated, it can be immediately applied via the template of your formatter. Example:
530
+
531
+ [source,ruby]
532
+ ----
533
+ logger = Cogger.new
534
+ logger.warn "Demo"
535
+ # 🟡 Demo
536
+ ----
537
+
538
+ ℹ️ Much like the simple and color formatters, any leading or trailing whitespace is automatically removed after the template has been formatted.
421
539
 
422
540
  ==== JSON
423
541
 
424
- This formatter is similar in behavior to the _simple_ formatter except the template allows you to order the layout of your keys only. All other information is ignored. To use:
542
+ 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, only the order of your template keys matters. Example:
543
+
544
+ *Default Order*
425
545
 
426
546
  [source,ruby]
427
547
  ----
428
- # Default order
429
548
  logger = Cogger.new formatter: :json
430
549
  logger.info verb: "GET", path: "/"
431
550
 
432
551
  # {"id":"console","severity":"INFO","at":"2023-04-10 09:03:55 -0600","verb":"GET","path":"/"}
552
+ ----
433
553
 
434
- # Custom order
554
+ *Custom Order*
555
+
556
+ [source,ruby]
557
+ ----
435
558
  logger = Cogger.new formatter: Cogger::Formatters::JSON.new("%<severity>s %<verb>s")
436
559
  logger.info verb: "GET", path: "/"
437
560
 
@@ -440,18 +563,65 @@ logger.info verb: "GET", path: "/"
440
563
 
441
564
  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.
442
565
 
443
- ==== Original
566
+ 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:
567
+
568
+ [source,ruby]
569
+ ----
570
+ logger = Cogger.new formatter: json
571
+
572
+ logger.info "Demo"
573
+ # {"id":"console","severity":"INFO","at":"2023-10-18 19:38:55 -0600","message":"Demo"}
574
+
575
+ logger.info messsage: "Demo"
576
+ {"id":"console","severity":"INFO","at":"2023-10-18 19:39:19 -0600","messsage":"Demo"}
577
+ ----
578
+
579
+ 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 outout. Here's an example where a mix of single and hash keys are used:
580
+
581
+ [source,ruby]
582
+ ----
583
+ logger = Cogger.new formatter: :json
584
+
585
+ logger.info "Demo", tags: ["WEB", "PRIMARY", {service: :api, demo: true}]
586
+
587
+ # {
588
+ # "id":"console",
589
+ # "severity":"INFO",
590
+ # "at":"2023-10-18 19:47:11 -0600",
591
+ # "message":"Demo",
592
+ # "tags":["WEB","PRIMARY"],
593
+ # "service":"api",
594
+ # "demo":true
595
+ # }
596
+ ----
597
+
598
+ 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.
599
+
600
+ ==== Native
444
601
 
445
- Should you wish to use the original formatter as provided by original/native {logger_link}, you can get that behavior by specifying it as your preferred formatter. Example:
602
+ 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:
446
603
 
447
604
  [source,ruby]
448
605
  ----
449
606
  require "logger"
450
607
 
451
608
  logger = Cogger.new formatter: Logger::Formatter.new
452
- logger.info "demo"
609
+ logger.info "Demo"
610
+
611
+ # 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={}>
612
+ ----
453
613
 
454
- # I, [2023-04-11T19:35:51.175733 #84790] INFO -- console: demo
614
+ 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:
615
+
616
+ [source,ruby]
617
+ ----
618
+ formatter = Cogger::Formatters::Simple.new(
619
+ "%<severity>s, [%<at>s] %<severity>s -- %<id>s: %<message>s"
620
+ )
621
+ logger = Cogger.new(formatter:)
622
+ logger.info "Demo"
623
+
624
+ # INFO, [2023-10-15 15:07:13 -0600] INFO -- console: Demo
455
625
  ----
456
626
 
457
627
  ==== Custom
@@ -468,7 +638,7 @@ class MyFormatter
468
638
  @sanitizer = sanitizer
469
639
  end
470
640
 
471
- def call(*entry) = "#{format template, sanitizer.call(*entry)}\n"
641
+ def call(*input) = "#{format template, sanitizer.call(*input)}\n"
472
642
 
473
643
  private
474
644
 
@@ -476,47 +646,105 @@ class MyFormatter
476
646
  end
477
647
  ----
478
648
 
479
- There is no restriction on what dependency you might want to initialize your custom formatter with but -- as a bare minimum -- you'll want to provide a default template and inject the sanitizer which sanitizes the raw log entry into a hash you can interact with in your implementation. The only other requirement is that you must implement `#call` which takes a log entry which is an array of positional arguments (i.e. `severity`, `at`, `id`, `message`) and answers back a formatted string. If you need more examples you can either read the link:https://rubyapi.org/o/logger/formatter#method-i-call[Logger::Formatter] documentation or look at any of the formatters provided within this gem.
649
+ 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.
480
650
 
481
- === Filters
651
+ === Tags
482
652
 
483
- Filters allow you to mask sensitive information you don't want showing up in your logs. Here are the defaults:
653
+ Tags allow you to tag your messages at both a global and local (i.e. per message) level. For example, here's what tagging looks like when used globally:
484
654
 
485
655
  [source,ruby]
486
656
  ----
487
- Cogger.filters
657
+ logger = Cogger.new tags: %w[WEB]
658
+ logger.info "Demo"
488
659
 
489
- # [
490
- # :_csrf,
491
- # :password,
492
- # :password_confirmation
493
- # ]
660
+ # 🟢 [WEB] Demo
494
661
  ----
495
662
 
496
- To add additional filters, use:
663
+ Each tag is wrapped in brackets (i.e. `[]`) and you can use multiple tags:
664
+
665
+ [source,ruby]
666
+ ----
667
+ logger = Cogger.new tags: %w[WEB EXAMPLE]
668
+ logger.info "Demo"
669
+
670
+ # 🟢 [WEB] [EXAMPLE] Demo
671
+ ----
672
+
673
+ You are not limited to string-based tags. Any object will work:
674
+
675
+
676
+ [source,ruby]
677
+ ----
678
+ logger = Cogger.new tags: ["ONE", :two, 3, {four: "FOUR"}, proc { "FIVE" }]
679
+ logger.info "Demo"
680
+
681
+ # 🟢 [ONE] [two] [3] [FIVE] [four=FOUR] Demo
682
+ ----
683
+
684
+ 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.
685
+
686
+ In addition to global tags, you can use local tags per log message. Example:
687
+
688
+ [source,ruby]
689
+ ----
690
+ logger = Cogger.new
691
+ logger.info "Demo", tags: ["ONE", :two, 3, {four: "FOUR"}, proc { "FIVE" }]
692
+
693
+ # 🟢 [ONE] [two] [3] [FIVE] [four=FOUR] Demo
694
+ ----
695
+
696
+ You can also combine global and local tags:
697
+
698
+ [source,ruby]
699
+ ----
700
+ logger = Cogger.new tags: ["ONE", :two]
701
+ logger.info "Demo", tags: [3, proc { "FOUR" }]
702
+
703
+ # 🟢 [ONE] [two] [3] [FOUR] Demo
704
+ ----
705
+
706
+ As you can see, tags are highly versatile. That said, the following guidelines are worth consideration when using them:
707
+
708
+ * Prefer uppercase tag names to make them visually stand out.
709
+ * Prefer short names, ideally 1-4 characters since long tags defeat the purpose of brevity.
710
+ * Prefer consistent tag names by using tags that are not synonymous or ambiguous.
711
+ * Prefer using tags by feature rather than things like environments. Examples: API, DB, MAILER.
712
+ * Prefer the JSON formatter for structured metadata instead of tags. Logging JSON formatted messages with tags will work but sticking with a traditional hash, instead of tags, will probably serve you better.
713
+
714
+ === Filters
715
+
716
+ Filters allow you to mask sensitive information you don't want showing up in your logs. The default is an empty set:
717
+
718
+ [source,ruby]
719
+ ----
720
+ Cogger.filters # #<Set: {}>
721
+ ----
722
+
723
+ To add filters, use:
497
724
 
498
725
  [source,ruby]
499
726
  ----
500
727
  Cogger.add_filter(:login)
501
728
  .add_filter "email"
502
729
 
503
- # [
504
- # :_csrf,
505
- # :password,
506
- # :password_confirmation,
507
- # :login,
508
- # :email
509
- # ]
730
+ Cogger.filters # #<Set: {:login, :email}>
510
731
  ----
511
732
 
512
733
  Symbols and strings can be used interchangeably but are stored as symbols since symbols are used when filtering log entries. Once your filters are in place, you can immediately see their effects:
513
734
 
514
735
  [source,ruby]
515
736
  ----
737
+ Cogger.add_filter :password
516
738
  logger = Cogger.new formatter: :json
517
739
  logger.info login: "jayne", password: "secret"
518
740
 
519
- # {"id":"console","severity":"INFO","at":"2023-04-09 17:33:00 -0600","login":"[FILTERED]","password":"[FILTERED]"}
741
+ # {
742
+ # "id":"console",
743
+ # "severity":"INFO",
744
+ # "at":"2023-10-18 19:21:40 -0600",
745
+ # "login":"jayne",
746
+ # "password":"[FILTERED]"
747
+ # }
520
748
  ----
521
749
 
522
750
  === Streams
@@ -532,7 +760,7 @@ logger = Cogger.new
532
760
  logger.info "Demo."
533
761
  ----
534
762
 
535
- The above would log the `"Demo."` message to `$stdout` (i.e. the default stream), to the `tmp/demo.log` file, and to `/dev/null`. All of the attributes you would use to construct your default logger apply to any stream. This also means any custom template/formatter can be applied to your streams. Here's another example:
763
+ The above would log the `"Demo."` message to `$stdout` -- the default stream -- to the `tmp/demo.log` file, and to `/dev/null`. All attributes used to construct your default logger apply to all additional streams unless customized further. This means any custom template/formatter can be applied to your streams. Example:
536
764
 
537
765
  [source,ruby]
538
766
  ----
@@ -542,6 +770,25 @@ logger.info "Demo."
542
770
 
543
771
  In this situation, you'd get colorized output to `$stdout` and JSON output to the `tmp/demo.log` file.
544
772
 
773
+ There is a lot you can do with streams. For example, if you wanted to experiment with the same message formatted by multiple formatters, you could add a stream per format. Example:
774
+
775
+ [source,ruby]
776
+ ----
777
+ logger = Cogger.new
778
+ .add_stream(formatter: :color)
779
+ .add_stream(formatter: :detail)
780
+ .add_stream(formatter: :json)
781
+ .add_stream(formatter: :simple)
782
+
783
+ logger.info "Demo"
784
+
785
+ # 🟢 Demo
786
+ # Demo
787
+ # [console] [INFO] [2023-10-15 15:17:27 -0600] Demo
788
+ # {"id":"console","severity":"INFO","at":"2023-10-15 15:17:27 -0600","message":"Demo"}
789
+ # Demo
790
+ ----
791
+
545
792
  === Defaults
546
793
 
547
794
  Should you ever need quick access to the defaults, you can use:
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.11.0"
5
+ spec.version = "0.13.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/cogger"
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.cert_chain = [Gem.default_cert_path]
24
24
 
25
25
  spec.required_ruby_version = "~> 3.2"
26
+ spec.add_dependency "core", "~> 0.1"
26
27
  spec.add_dependency "refinements", "~> 11.0"
27
28
  spec.add_dependency "tone", "~> 0.3"
28
29
  spec.add_dependency "zeitwerk", "~> 2.6"
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "core"
3
4
  require "logger"
4
5
 
5
6
  module Cogger
@@ -9,20 +10,24 @@ module Cogger
9
10
  :io,
10
11
  :level,
11
12
  :formatter,
13
+ :tags,
12
14
  :mode,
13
15
  :age,
14
16
  :size,
15
17
  :suffix,
18
+ :entry,
16
19
  :logger
17
20
  ) do
18
21
  def initialize id: Program.call,
19
22
  io: $stdout,
20
23
  level: Logger.const_get(ENV.fetch("LOG_LEVEL", "INFO")),
21
- formatter: Formatters::Color.new,
24
+ formatter: Formatters::Emoji.new,
25
+ tags: Core::EMPTY_ARRAY,
22
26
  mode: false,
23
27
  age: 0,
24
28
  size: 1_048_576,
25
29
  suffix: "%Y-%m-%d",
30
+ entry: Entry,
26
31
  logger: Logger
27
32
  super
28
33
  end
@@ -40,9 +45,9 @@ module Cogger
40
45
 
41
46
  def inspect
42
47
  "#<#{self.class} @id=#{id}, @io=#{io.class}, @level=#{level}, " \
43
- "@formatter=#{formatter.class}, " \
48
+ "@formatter=#{formatter.class}, @tags=#{tags.inspect}, " \
44
49
  "@mode=#{mode}, @age=#{age}, @size=#{size}, @suffix=#{suffix.inspect}, " \
45
- "@logger=#{logger}>"
50
+ "@entry=#{entry}, @logger=#{logger}>"
46
51
  end
47
52
  end
48
53
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "core"
4
+
5
+ module Cogger
6
+ # Defines a log entry which can be formatted for output.
7
+ Entry = Data.define :id, :severity, :at, :message, :tags, :payload do
8
+ def self.for(message = nil, **payload)
9
+ new id: (payload.delete(:id) || Program.call),
10
+ severity: (payload.delete(:severity) || "INFO").upcase,
11
+ message: (block_given? ? yield : message),
12
+ tags: Array(payload.delete(:tags)),
13
+ payload:
14
+ end
15
+
16
+ def self.for_crash message, error, id:
17
+ new id:,
18
+ severity: "FATAL",
19
+ message:,
20
+ payload: {
21
+ error_message: error.message,
22
+ error_class: error.class,
23
+ backtrace: error.backtrace
24
+ }
25
+ end
26
+
27
+ def initialize id: Program.call,
28
+ severity: "INFO",
29
+ at: Time.now,
30
+ message: nil,
31
+ tags: [],
32
+ payload: Core::EMPTY_HASH
33
+ super
34
+ end
35
+
36
+ def attributes = {id:, severity:, at:, message:, **payload}
37
+
38
+ def tagged_attributes tagger: Tag
39
+ computed_tags = tagger.for(*tags)
40
+
41
+ return attributes if computed_tags.empty?
42
+
43
+ {id:, severity:, at:, message:, **computed_tags.to_h, **payload}
44
+ end
45
+
46
+ def tagged tagger: Tag
47
+ attributes.tap do |pairs|
48
+ computed_tags = tagger.for(*tags)
49
+ pairs[:message] = "#{computed_tags} #{pairs[:message]}" unless computed_tags.empty?
50
+ end
51
+ end
52
+ end
53
+ end
@@ -11,8 +11,8 @@ module Cogger
11
11
  @processor = processor
12
12
  end
13
13
 
14
- def call(*entry)
15
- updated_template, attributes = processor.call(template, *entry)
14
+ def call(*input)
15
+ updated_template, attributes = processor.call(template, *input)
16
16
  "#{format(updated_template, **attributes).tap(&:strip!)}\n"
17
17
  end
18
18
 
@@ -16,8 +16,8 @@ module Cogger
16
16
  @processor = processor
17
17
  end
18
18
 
19
- def call(*entry)
20
- updated_template, attributes = processor.call(template, *entry)
19
+ def call(*input)
20
+ updated_template, attributes = processor.call(template, *input)
21
21
  attributes[:backtrace] = %( #{attributes[:backtrace].join "\n "})
22
22
  "#{format(updated_template, **attributes)}\n"
23
23
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cogger
4
+ module Formatters
5
+ # Formats by emoji and color.
6
+ class Emoji < Color
7
+ TEMPLATE = "%<emoji:dynamic>s %<message:dynamic>s"
8
+
9
+ def initialize(template = TEMPLATE, ...)
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,30 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "core"
3
4
  require "json"
4
5
 
5
6
  module Cogger
6
7
  module Formatters
7
8
  # Formats as JSON output.
8
9
  class JSON
9
- TEMPLATE = "%<id>s %<severity>s %<at>s %<message>s"
10
+ TEMPLATE = nil
10
11
 
11
12
  def initialize template = TEMPLATE,
12
13
  parser: Parsers::Individual.new,
13
- sanitizer: Kit::Sanitizer.new
14
- @template = template
15
- @parser = parser
14
+ sanitizer: Kit::Sanitizer
15
+ @positions = template ? parser.call(template).last.keys : Core::EMPTY_ARRAY
16
16
  @sanitizer = sanitizer
17
17
  end
18
18
 
19
- def call(*entry)
20
- positions = parser.call(template).last.keys
21
- attributes = sanitizer.call(*entry).tap(&:compact!)
19
+ def call(*input)
20
+ attributes = sanitizer.call(*input).tagged_attributes.tap(&:compact!)
21
+
22
+ return "#{attributes.to_json}\n" if positions.empty?
23
+
22
24
  "#{attributes.slice(*positions).merge!(attributes.except(*positions)).to_json}\n"
23
25
  end
24
26
 
25
27
  private
26
28
 
27
- attr_reader :template, :parser, :sanitizer
29
+ attr_reader :positions, :sanitizer
28
30
  end
29
31
  end
30
32
  end
@@ -3,34 +3,13 @@
3
3
  module Cogger
4
4
  module Formatters
5
5
  module Kit
6
- # Transforms a positional log entry into a hash entry for template parsing and formatting.
7
- class Sanitizer
8
- def initialize filters: Cogger.filters
9
- @filters = filters
10
- end
6
+ # Ensures log entry is filtered of sensitive data.
7
+ Sanitizer = lambda do |*input, filters: Cogger.filters|
8
+ *, entry = input
9
+ payload = entry.payload
11
10
 
12
- # :reek:FeatureEnvy
13
- def call(*entry)
14
- severity, at, id, message = entry
15
-
16
- attributes = if message.is_a? Hash
17
- {id:, severity:, at:, message: nil, **message.except(:id, :severity, :at)}
18
- else
19
- {id:, severity:, at:, message:}
20
- end
21
-
22
- filter attributes
23
- end
24
-
25
- private
26
-
27
- attr_reader :filters
28
-
29
- # :reek:FeatureEnvy
30
- def filter attributes
31
- filters.each { |key| attributes[key] = "[FILTERED]" if attributes.key? key }
32
- attributes
33
- end
11
+ filters.each { |key| payload[key] = "[FILTERED]" if payload.key? key }
12
+ entry
34
13
  end
35
14
  end
36
15
  end
@@ -45,7 +45,7 @@ module Cogger
45
45
  # :reek:FeatureEnvy
46
46
  # :reek:TooManyStatements
47
47
  def sanitize_and_extract template, attributes
48
- template.dup.gsub pattern do
48
+ template.gsub pattern do
49
49
  captures = Regexp.last_match.named_captures
50
50
  attributes[captures["key"].to_sym] = captures["directive"]
51
51
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "core"
4
+
3
5
  module Cogger
4
6
  module Formatters
5
7
  module Parsers
@@ -32,7 +34,7 @@ module Cogger
32
34
  def call template
33
35
  return template unless template.match? pattern
34
36
 
35
- [template.gsub(pattern, ""), template.match(pattern)[key]]
37
+ [template.gsub(pattern, Core::EMPTY_STRING), template.match(pattern)[key]]
36
38
  end
37
39
 
38
40
  private
@@ -8,15 +8,15 @@ module Cogger
8
8
  # Processes emojis and colors.
9
9
  class Color
10
10
  def initialize parser: Parsers::Dynamic.new,
11
- kit: {sanitizer: Kit::Sanitizer.new, colorizer: Kit::Colorizer},
11
+ kit: {sanitizer: Kit::Sanitizer, colorizer: Kit::Colorizer},
12
12
  registry: Cogger
13
13
  @parser = parser
14
14
  @kit = kit
15
15
  @registry = registry
16
16
  end
17
17
 
18
- def call(template, *entry)
19
- attributes = sanitizer.call(*entry)
18
+ def call(template, *input)
19
+ attributes = sanitizer.call(*input).tagged
20
20
 
21
21
  case parser.call template
22
22
  in [String => body, String => style] then universal body, style, **attributes
@@ -6,12 +6,12 @@ module Cogger
6
6
  class Simple
7
7
  TEMPLATE = "%<message>s"
8
8
 
9
- def initialize template = TEMPLATE, sanitizer: Kit::Sanitizer.new
9
+ def initialize template = TEMPLATE, sanitizer: Kit::Sanitizer
10
10
  @template = template
11
11
  @sanitizer = sanitizer
12
12
  end
13
13
 
14
- def call(*entry) = "#{format(template, sanitizer.call(*entry)).tap(&:strip!)}\n"
14
+ def call(*input) = "#{format(template, sanitizer.call(*input).tagged).tap(&:strip!)}\n"
15
15
 
16
16
  private
17
17
 
data/lib/cogger/hub.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "forwardable"
3
4
  require "logger"
4
5
  require "refinements/hashes"
5
6
  require "refinements/loggers"
@@ -8,12 +9,35 @@ module Cogger
8
9
  # Loads configuration and simultaneously sends messages to multiple streams.
9
10
  # :reek:TooManyInstanceVariables
10
11
  class Hub
12
+ extend Forwardable
13
+
11
14
  using Refinements::Loggers
12
15
  using Refinements::Hashes
13
16
 
14
- def initialize(registry: Cogger, model: Configuration.new, **attributes)
17
+ delegate %i[
18
+ close
19
+ reopen
20
+ debug!
21
+ debug?
22
+ info!
23
+ info?
24
+ warn!
25
+ warn?
26
+ error!
27
+ error?
28
+ fatal!
29
+ fatal?
30
+ formatter
31
+ formatter=
32
+ level
33
+ level=
34
+ ] => :primary
35
+
36
+ delegate %i[id io tags mode age size suffix] => :configuration
37
+
38
+ def initialize(registry: Cogger, model: Configuration, **attributes)
15
39
  @registry = registry
16
- @configuration = model.with(**find_formatter(attributes))
40
+ @configuration = model[**find_formatter(attributes)]
17
41
  @primary = configuration.to_logger
18
42
  @streams = [@primary]
19
43
  @mutex = Mutex.new
@@ -25,19 +49,23 @@ module Cogger
25
49
  self
26
50
  end
27
51
 
28
- def debug(...) = log(__method__, ...)
52
+ def debug(message = nil, **payload, &) = log(__method__, message, **payload, &)
53
+
54
+ def info(message = nil, **payload, &) = log(__method__, message, **payload, &)
29
55
 
30
- def info(...) = log(__method__, ...)
56
+ def warn(message = nil, **payload, &) = log(__method__, message, **payload, &)
31
57
 
32
- def warn(...) = log(__method__, ...)
58
+ def error(message = nil, **payload, &) = log(__method__, message, **payload, &)
33
59
 
34
- def error(...) = log(__method__, ...)
60
+ def fatal(message = nil, **payload, &) = log(__method__, message, **payload, &)
35
61
 
36
- def fatal(...) = log(__method__, ...)
62
+ def any(message = nil, **payload, &) = log(__method__, message, **payload, &)
37
63
 
38
- def unknown(...) = log(__method__, ...)
64
+ def add(severity, message = nil, **payload, &)
65
+ log(Logger::SEV_LABEL.fetch(severity, "ANY").downcase, message, **payload, &)
66
+ end
39
67
 
40
- alias any unknown
68
+ alias unknown any
41
69
 
42
70
  def reread = primary.reread
43
71
 
@@ -60,17 +88,30 @@ module Cogger
60
88
  )
61
89
  end
62
90
 
63
- # :reek:TooManyStatements
64
- def log(severity, message = nil, &)
65
- mutex.synchronize { streams.each { |logger| logger.public_send(severity, message, &) } }
66
- true
91
+ def log(severity, message = nil, **payload, &)
92
+ dispatch(severity, message, **payload, &)
67
93
  rescue StandardError => error
68
- configuration.with(id: "Cogger", io: $stdout, formatter: Formatters::Crash.new)
94
+ crash message, error
95
+ end
96
+
97
+ def dispatch(severity, message, **payload, &)
98
+ entry = configuration.entry.for(
99
+ message,
100
+ id: configuration.id,
101
+ severity:,
102
+ tags: configuration.tags + Array(payload.delete(:tags)),
103
+ **payload,
104
+ &
105
+ )
106
+
107
+ mutex.synchronize { streams.each { |logger| logger.public_send severity, entry } }
108
+ true
109
+ end
110
+
111
+ def crash message, error
112
+ configuration.with(id: :cogger, io: $stdout, formatter: Formatters::Crash.new)
69
113
  .to_logger
70
- .fatal message:,
71
- error_message: error.message,
72
- error_class: error.class,
73
- backtrace: error.backtrace
114
+ .fatal configuration.entry.for_crash(message, error, id: configuration.id)
74
115
  true
75
116
  end
76
117
  end
@@ -18,20 +18,13 @@ module Cogger
18
18
  .add_emoji(:error, "🛑")
19
19
  .add_emoji(:fatal, "🔥")
20
20
  .add_emoji(:any, "⚫️")
21
- .add_filter(:_csrf)
22
- .add_filter(:password)
23
- .add_filter(:password_confirmation)
24
21
  .add_formatter(:color, Cogger::Formatters::Color)
25
22
  .add_formatter(
26
23
  :detail,
27
24
  Cogger::Formatters::Simple,
28
25
  "[%<id>s] [%<severity>s] [%<at>s] %<message>s"
29
26
  )
30
- .add_formatter(
31
- :emoji,
32
- Cogger::Formatters::Color,
33
- "%<emoji:dynamic>s %<message:dynamic>s"
34
- )
27
+ .add_formatter(:emoji, Cogger::Formatters::Emoji)
35
28
  .add_formatter(:json, Cogger::Formatters::JSON)
36
29
  .add_formatter(:simple, Cogger::Formatters::Simple)
37
30
  .add_formatter :rack,
data/lib/cogger/tag.rb ADDED
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "core"
4
+ require "refinements/hashes"
5
+
6
+ module Cogger
7
+ # Models a tag which may consist of an array and/or hash.
8
+ Tag = Data.define :singles, :pairs do
9
+ using Refinements::Hashes
10
+
11
+ def self.for(*bag)
12
+ bag.each.with_object new do |item, tag|
13
+ value = item.is_a?(Proc) ? item.call : item
14
+ value.is_a?(Hash) ? tag.pairs.merge!(value) : tag.singles.append(value)
15
+ end
16
+ end
17
+
18
+ def initialize singles: [], pairs: {}
19
+ super
20
+ end
21
+
22
+ def empty? = singles.empty? && pairs.empty?
23
+
24
+ def to_h = empty? ? Core::EMPTY_HASH : {tags: singles.to_a, **pairs}.tap(&:compress!)
25
+
26
+ def to_s = empty? ? Core::EMPTY_STRING : "#{format_singles} #{format_pairs}".tap(&:strip!)
27
+
28
+ private
29
+
30
+ def format_singles
31
+ singles.map { |value| "[#{value}]" }
32
+ .join " "
33
+ end
34
+
35
+ def format_pairs
36
+ pairs.map { |key, value| "[#{key}=#{value}]" }
37
+ .join(" ")
38
+ end
39
+ end
40
+ end
data/lib/cogger.rb CHANGED
@@ -15,10 +15,5 @@ module Cogger
15
15
 
16
16
  def self.loader(registry = Zeitwerk::Registry) = registry.loader_for __FILE__
17
17
 
18
- def self.init(...)
19
- warn "#{self}##{__method__} is deprecated, use `.new` instead.", category: :deprecated
20
- Client.new(...)
21
- end
22
-
23
18
  def self.new(...) = Hub.new(...)
24
19
  end
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.11.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -35,8 +35,22 @@ cert_chain:
35
35
  3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
36
36
  gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
37
37
  -----END CERTIFICATE-----
38
- date: 2023-10-01 00:00:00.000000000 Z
38
+ date: 2023-10-19 00:00:00.000000000 Z
39
39
  dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: core
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.1'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.1'
40
54
  - !ruby/object:Gem::Dependency
41
55
  name: refinements
42
56
  requirement: !ruby/object:Gem::Requirement
@@ -92,10 +106,11 @@ files:
92
106
  - README.adoc
93
107
  - cogger.gemspec
94
108
  - lib/cogger.rb
95
- - lib/cogger/client.rb
96
109
  - lib/cogger/configuration.rb
110
+ - lib/cogger/entry.rb
97
111
  - lib/cogger/formatters/color.rb
98
112
  - lib/cogger/formatters/crash.rb
113
+ - lib/cogger/formatters/emoji.rb
99
114
  - lib/cogger/formatters/json.rb
100
115
  - lib/cogger/formatters/kit/colorizer.rb
101
116
  - lib/cogger/formatters/kit/sanitizer.rb
@@ -107,6 +122,7 @@ files:
107
122
  - lib/cogger/hub.rb
108
123
  - lib/cogger/program.rb
109
124
  - lib/cogger/registry.rb
125
+ - lib/cogger/tag.rb
110
126
  homepage: https://alchemists.io/projects/cogger
111
127
  licenses:
112
128
  - Hippocratic-2.1
@@ -133,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
149
  - !ruby/object:Gem::Version
134
150
  version: '0'
135
151
  requirements: []
136
- rubygems_version: 3.4.20
152
+ rubygems_version: 3.4.21
137
153
  signing_key:
138
154
  specification_version: 4
139
155
  summary: A customizable and feature rich logger.
metadata.gz.sig CHANGED
Binary file
data/lib/cogger/client.rb DELETED
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "forwardable"
4
- require "logger"
5
- require "refinements/loggers"
6
- require "tone"
7
-
8
- module Cogger
9
- # Provides the primary client for colorized logging.
10
- class Client
11
- extend Forwardable
12
-
13
- using Refinements::Loggers
14
-
15
- delegate %i[formatter level progname debug info warn error fatal unknown] => :logger
16
-
17
- # :reek:TooManyStatements
18
- def initialize logger = Logger.new($stdout), color: Cogger.color, **attributes
19
- warn "#{self.class}##{__method__} is deprecated, use `Cogger.new` instead.",
20
- category: :deprecated
21
-
22
- @logger = logger
23
- @color = color
24
- @attributes = attributes
25
-
26
- configure
27
- yield logger if block_given?
28
- end
29
-
30
- def any(...) = logger.unknown(...)
31
-
32
- def reread = logger.reread
33
-
34
- private
35
-
36
- attr_reader :logger, :color, :attributes
37
-
38
- # rubocop:disable Metrics/AbcSize
39
- def configure
40
- logger.datetime_format = attributes.fetch :datetime_format, logger.datetime_format
41
- logger.level = attributes.fetch :level, default_level
42
- logger.progname = attributes.fetch :progname, logger.progname
43
- logger.formatter = attributes.fetch :formatter, default_formatter
44
- end
45
- # rubocop:enable Metrics/AbcSize
46
-
47
- def default_level = logger.class.const_get ENV.fetch("LOG_LEVEL", "INFO")
48
-
49
- def default_formatter
50
- -> severity, _at, _name, message { "#{color[message, severity.downcase]}\n" }
51
- end
52
- end
53
- end