cogger 0.6.0 → 0.7.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: d2ff34be63a6d20792b0dad16762afaf0f03226964b2a83ed08194fef2f37a75
4
- data.tar.gz: 5fce7ffb39529c8d4c29f10a03d29e3173219f0365428fa10d003501c38a2553
3
+ metadata.gz: 04acb9b4497c231d507b13ca31312db5cec0cf8e5ad8786d23afb20344acf9f6
4
+ data.tar.gz: 537e54ca280321a1522ff7f9b1789f2d396780317fade574d4260a3aee1cb495
5
5
  SHA512:
6
- metadata.gz: a8d82b63e521610dda3906c998e8533ad6f82920f1294dedc10a8acba2ec63084213c3ab80f37ae50525f83928d628ea7a94a37fd52c9abbb63a7da54cc619c7
7
- data.tar.gz: 57e01b5b658f64abc8581a98e95cbb6b6794a787e7b244d79d3aa61f21d157252b19a53a84cbc3e0d18c3058250063d555d5fa133f8ddec67a12fca203657be5
6
+ metadata.gz: 46fd6ca89fd5c7da0c3fbf25ebe6e796cd24617688fbe8dd3681bc423d48842decb122e26d18b37391e0f34f5c3a239ab8bf5b81e72ac1f1379041142831cebf
7
+ data.tar.gz: 1fef8f07f3340fc6e3afe7b89ed3abd087e9ae5b55c46a0c0a23685a670eb7d8e85603220411592ee1f22a64993fdd0181b54990d3cf728bd55146376c14ca08
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -1,24 +1,31 @@
1
- :pastel_link: link:https://github.com/piotrmurach/pastel[Pastel]
2
-
3
1
  :toc: macro
4
2
  :toclevels: 5
5
3
  :figure-caption!:
6
4
 
5
+ :tone_link: link:https://alchemists.io/projects/tone[Tone]
6
+ :logger_link: link:https://rubyapi.org/o/s?q=Logger[Logger]
7
+ :format_link: link:https://ruby-doc.org/3.2.1/format_specifications_rdoc.html[Format Specification]
8
+ :pattern_matching_link: link:https://alchemists.io/articles/ruby_pattern_matching[pattern matching]
9
+ :refinements_link: link:https://alchemists.io/projects/refinements[Refinements]
10
+
7
11
  = Cogger
8
12
 
9
- Cogger is a portmanteau for colorized logging (i.e. `[c]olorized + l[ogger] = cogger`) which
10
- decorates Ruby's native logger with colorized output.
13
+ Cogger is a portmanteau for custom logging (i.e. `[c]ustom + l[ogger] = cogger`) which enhances Ruby's native logging functionality with additional features such as dynamic emojis, colorized text, structured JSON, and much more.
11
14
 
12
15
  toc::[]
13
16
 
14
17
  == Features
15
18
 
16
19
  - Decorates Ruby's default `Logger`.
17
- - Uses color decoration as provided by the {pastel_link} gem.
20
+ - Provides dynamic emoji output based on severity.
21
+ - Provides dynamic or specific color decoration via the {tone_link} gem.
22
+ - Provides customizable formatters for simple, color, JSON, and/or custom output.
23
+ - Provides customizable templates which leverage the native {format_link}.
24
+ - Provides filtering of sensitive information.
18
25
 
19
26
  == Screenshot
20
27
 
21
- image::https://alchemists.io/images/projects/cogger/screenshots/console.png[Console,width=552,height=679,role=focal_point]
28
+ image::https://alchemists.io/images/projects/cogger/screenshots/console.png[Console,width=1139,height=211,role=focal_point]
22
29
 
23
30
  == Requirements
24
31
 
@@ -35,150 +42,380 @@ bin/setup
35
42
 
36
43
  == Usage
37
44
 
38
- All colorized logging is provided by `Cogger` which can be used as follows:
45
+ All interaction is provided by `Cogger` which can be used as follows:
46
+
47
+ [source,ruby]
48
+ ----
49
+ logger = Cogger.new
50
+ logger.info "demo" # "demo"
51
+ ----
52
+
53
+ If you set your logging level to `debug`, you can walk through each level:
54
+
55
+ [source,ruby]
56
+ ----
57
+ logger = Cogger.new level: :debug
58
+
59
+ # Without blocks.
60
+ logger.debug "demo" # "demo"
61
+ logger.info "demo" # "demo"
62
+ logger.warn "demo" # "demo"
63
+ logger.error "demo" # "demo"
64
+ logger.fatal "demo" # "demo"
65
+ logger.unknown "demo" # "demo"
66
+ logger.any "demo" # "demo"
67
+
68
+ # With blocks.
69
+ logger.debug { "demo" } # "demo"
70
+ logger.info { "demo" } # "demo"
71
+ logger.warn { "demo" } # "demo"
72
+ logger.error { "demo" } # "demo"
73
+ logger.fatal { "demo" } # "demo"
74
+ logger.unknown { "demo" } # "demo"
75
+ logger.any { "demo" } # "demo"
76
+ ----
77
+
78
+ ...or, if you'd like to display all severities at once, use:
39
79
 
40
80
  [source,ruby]
41
81
  ----
42
- logger = Cogger.init
82
+ %i[debug info warn error fatal unknown any].each { |severity| logger.public_send severity, "demo" }
83
+ ----
84
+
85
+ === Initialization
86
+
87
+ When creating a new logger, you can configure behavior via the following attributes:
88
+
89
+ * `id`: The program/process ID which shows up in the logs as your `id`. Default: `$PROGRAM_NAME`. For example, if initialized within `demo.rb`, the `id` would be `"demo"`,
90
+ * `io`: The input/output stream. This can be `STDOUT/$stdout`, a file/path, or `nil`. Default: `$stdout`.
91
+ * `level`: The severity level you want to log at. Can be `:debug`, `:info`, `:warn`, `:error`, `:fatal`, or `:unknown`. Default: `:info`.
92
+ * `formatter`: The formatter to use for formatting your log output. Default: `Cogger::Formatter::Color`. See the _Formatters_ section for more info.
93
+ * `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`.
94
+ * `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`.
95
+ * `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).
96
+ * `suffix`: The rotation suffix. This only applies when logging to a file. This is equivalent to the `shift_period_suffix` as found with the {logger_link} class and is used when creating new rotation files. Default: `%Y-%m-%d`.
43
97
 
44
- logger.debug "test" # true
45
- logger.debug { "test" } # true
46
- logger.info "test" # true
47
- logger.info { "test" } # true
48
- logger.warn "test" # true
49
- logger.warn { "test" } # true
50
- logger.error "test" # true
51
- logger.error { "test" } # true
52
- logger.fatal "test" # true
53
- logger.fatal { "test" } # true
54
- logger.unknown "test" # true
55
- logger.unknown { "test" } # true
56
- logger.any "test" # true
57
- logger.any { "test" } # true
98
+ Given the above description, here's how'd you create a new logger instance with all attributes:
99
+
100
+ [source,ruby]
101
+ ----
102
+ # Default
103
+ logger = Cogger.new
104
+
105
+ # Custom
106
+ logger = Cogger.new id: :demo,
107
+ io: "demo.log",
108
+ level: :debug,
109
+ mode: false,
110
+ age: 5,
111
+ size: 1_000,
112
+ suffix: "%Y"
113
+ ----
114
+
115
+ === Environment
116
+
117
+ The default log level is `INFO` but can be customized via your environment. For instance, you could
118
+ set the logging level to any of the following:
119
+
120
+ [source,bash]
121
+ ----
122
+ export LOG_LEVEL=DEBUG
123
+ export LOG_LEVEL=INFO
124
+ export LOG_LEVEL=WARN
125
+ export LOG_LEVEL=ERROR
126
+ export LOG_LEVEL=FATAL
127
+ export LOG_LEVEL=UNKNOWN
128
+ export LOG_LEVEL=ANY
58
129
  ----
59
130
 
60
- By default, all logging is configured to use `INFO` level and writes to `$stdout`. To see what the
61
- colorized output from the above looks like, please see the screenshot shown in the _Screenshots_
62
- section as documented earlier.
131
+ By default, `Cogger` will automatically use whatever is set via the `LOG_LEVEL` environment variable unless overwritten during initialization.
132
+
133
+ === Templates
63
134
 
64
- Beyond the standard log level methods, the following methods are also available:
135
+ Templates are used by all formatters and adhere to {format_link} as used by `Kernel#format`. All specifiers, flags, width, and precision are supported except for the following restrictions:
136
+
137
+ - 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}.
138
+ - Use of the `n$` flag is prohibited because this isn't compatible with the above.
139
+
140
+ 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:
65
141
 
66
142
  [source,ruby]
67
143
  ----
68
- logger = Cogger.init
144
+ # Universal: Dynamic
145
+ "<dynamic>%<severity>s %<at>s %<id>s %<message>s</dynamic>"
146
+
147
+ # Universal: Specific
148
+ "<green>%<severity>s %<at>s %<id>s %<message>s</green>"
149
+
150
+ # Individual: Dynamic
151
+ "%<severity:dynamic>s %<at:green>s %<id:green>s %<message:green>s"
69
152
 
70
- logger.formatter # #<Proc:0x000000010626ebc8 $HOME/OSS/cogger/lib/cogger/client.rb:37 (lambda)>
71
- logger.level # 1
72
- logger.progname # nil
153
+ # Individual: Specific
154
+ "%<severity:purple>s %<at:yellow>s %<id:cyan>s %<message:green>s"
73
155
  ----
74
156
 
75
- === Customization
157
+ Here's a detailed breakdown of the above:
76
158
 
77
- Customization of the logger differs, slightly, from what you'd get with the standard `Logger` class.
78
- The following sections will explain what these differences look like.
159
+ * *Universal*: Applies color universally to the _entire_ template and requires you to:
160
+ ** Wrap your entire template in a and start (`<example>`) and end tag (`</example>`).
161
+ ** Your tag names must either be `<dynamic></dynamic>`, any default color (i.e. `<green></green>`), or alias (i.e. `<your_alias></your_alias>`) as supported by the {tone_link} gem.
162
+ * *Individual*: Individual templates allow you to apply color to _specific_ attributes and require you to:
163
+ ** Format your attributes as `attribute:directive`. The colon delimiter is required to separate your attribute for your color choice.
164
+ ** The color value (what follows after the colon) can be `dynamic`, any default color (i.e. `green`), or alias (i.e. `your_alias`) as supported by the {tone_link} gem.
79
165
 
80
- ==== Initialization
166
+ In addition to the general categorization of universal and individual tags, each support the following directives:
81
167
 
82
- For starters, the first argument is a positional argument that defaults to `Logger.new($stdout)` but
83
- you could swap out the default logger with something that logs to a string. For example:
168
+ * *Dynamic*: A dynamic directive means that color will be determined by severity level only. This means if info level is used, the associated color (alias) for info will be applied. Same goes for warn, error, etc.
169
+ * *Specific*: A specific directive means the color you use will be applied without any further processing regardless of the severity level. This gives you the ability to customize your colors further in situations where dynamic coloring isn't enough.
170
+
171
+ === Emojis
172
+
173
+ In addition to coloring to your log output, you can add emojis as well. Here are the defaults:
84
174
 
85
175
  [source,ruby]
86
176
  ----
87
- logger = Cogger.init Logger.new(StringIO.new)
177
+ Cogger.emojis
178
+
179
+ # {
180
+ # :debug => "🔎",
181
+ # :info => "🟢",
182
+ # :warn => "⚠️ ",
183
+ # :error => "🛑",
184
+ # :fatal => "🔥"
185
+ # }
88
186
  ----
89
187
 
90
- You can also create a logger which might use custom colors. Example:
188
+ To add an emoji, use:
91
189
 
92
190
  [source,ruby]
93
191
  ----
94
- logger = Cogger.init color: MyColor.new
192
+ Cogger.add_emoji(:tada, "🎉")
193
+ .add_emoji :favorite, "❇️"
95
194
  ----
96
195
 
97
- More information on how to customize your colors will be provided shortly. Lastly, you can provide any _setable_ attribute which would normally be used when constructing a
98
- normal logger. Example:
196
+ By default, the `:emoji` formatter provides dynamic rendering of emojis based on severity level. Example:
99
197
 
100
198
  [source,ruby]
101
199
  ----
102
- logger = Cogger.init formatter: ->(severity, _at, _name, message) { "#{message}\n" },
103
- level: :debug,
104
- progname: "Test",
105
- datetime_format: "%Y-%m-%d"
200
+ logger = Cogger.new formatter: :emoji
201
+ logger.info "demo"
202
+
203
+ # 🟢 demo
106
204
  ----
107
205
 
108
- Alternatively, you can use a block as well:
206
+ If you wanted to use a specific emoji, you could use the color formatter with a specific template:
109
207
 
110
208
  [source,ruby]
111
209
  ----
112
- logger = Cogger.init do |instance|
113
- instance.formatter = ->(severity, _at, _name, message) { "#{message}\n" }
114
- instance.level = :debug
115
- instance.progname = "Test"
116
- instance.datetime_format = "%Y-%m-%d"
117
- end
210
+ logger = Cogger.new formatter: Cogger::Formatters::Color.new("%<emoji:tada>s %<message:dynamic>s")
211
+ logger.info "demo"
212
+
213
+ # 🎉 demo
118
214
  ----
119
215
 
120
- ==== Environment
216
+ Keep in mind that using a specific, non-dynamic, emoji will _always_ display no matter the current severity level.
121
217
 
122
- The default log level is `INFO` but can be customized via your environment. For instance, you could
123
- set the logging level to any of the following:
218
+ === Formatters
124
219
 
125
- [source,bash]
220
+ Multiple formatters are provided for you which can be further customized as needed. Here's what is provided by default:
221
+
222
+ [source,ruby]
126
223
  ----
127
- export LOG_LEVEL=DEBUG
128
- export LOG_LEVEL=INFO
129
- export LOG_LEVEL=WARN
130
- export LOG_LEVEL=ERROR
131
- export LOG_LEVEL=FATAL
132
- export LOG_LEVEL=UNKNOWN
133
- export LOG_LEVEL=ANY
224
+ Cogger.formatters
225
+
226
+ # {
227
+ # :color => [
228
+ # Cogger::Formatters::Color < Object,
229
+ # nil
230
+ # ],
231
+ # :detail => [
232
+ # Cogger::Formatters::Simple < Object,
233
+ # "[%<id>s] [%<severity>s] [%<at>s] %<message>s"
234
+ # ],
235
+ # :emoji => [
236
+ # Cogger::Formatters::Color < Object,
237
+ # "%<emoji:dynamic>s% <message:dynamic>s"
238
+ # ],
239
+ # :json => [
240
+ # Cogger::Formatters::JSON < Object,
241
+ # nil
242
+ # ],
243
+ # :simple => [
244
+ # Cogger::Formatters::Simple < Object,
245
+ # nil
246
+ # ],
247
+ # :rack => [
248
+ # Cogger::Formatters::Simple < Object,
249
+ # "[%<id>s] [%<severity>s] [%<at>s] %<verb>s %<status>s %<duration>s %<ip>s %<path>s %<length>s # %<params>s"
250
+ # ]
251
+ # }
252
+ ----
253
+
254
+ You can add a formatter by providing a unique name, class, and associated template (`nil` can be used if you want to use the formatter's default template):
255
+
256
+ [source,ruby]
257
+ ----
258
+ # Add
259
+ Cogger.add_formatter :basic, Cogger::Formatters::Simple, "%<severity>s %<message>s"
260
+
261
+ # Get
262
+ Cogger.get_formatter :basic
263
+ # [Cogger::Formatters::Simple, "%<severity>s %<message>s"]
134
264
  ----
135
265
 
136
- By default, `Cogger::Client` will automatically use whatever is set via the `LOG_LEVEL` environment
137
- variable unless overwritten during initialization.
266
+ 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 by asking for it:
138
267
 
139
- ==== Colorization
268
+ [source,ruby]
269
+ ----
270
+ Cogger::Formatters::Simple::TEMPLATE
271
+ # "%<message>s"
272
+ ----
273
+
274
+ 💡 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 a symbol when initializing a new logger.
275
+
276
+ ==== Simple
277
+
278
+ The simple formatter is a bare bones formatter that uses no color information, doesn't support the universal/dynamic template syntax, and only supports the {format_link} as mentioned in the _Templates_ section earlier. This formatter can be used via the following template variations:
279
+
280
+ [source,ruby]
281
+ ----
282
+ logger = Cogger.new formatter: :detail
283
+ logger = Cogger.new formatter: :simple
284
+ logger = Cogger.new formatter: :rack
285
+ ----
286
+
287
+ ==== Color
288
+
289
+ The color formatter is enabled by default and is the equivalent of initializing with either of the following:
290
+
291
+ [source,ruby]
292
+ ----
293
+ logger = Cogger.new
294
+ logger = Cogger.new formatter: Cogger::Formatters::Color.new
295
+ logger = Cogger.new formatter: Cogger::Formatters::Color.new("%<message:dynamic>s")
296
+ ----
297
+
298
+ 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.
299
+
300
+ 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:
301
+
302
+ [source,ruby]
303
+ ----
304
+ Cogger.aliases
305
+
306
+ # {
307
+ # debug: :white,
308
+ # info: :green,
309
+ # warn: :yellow,
310
+ # error: :red,
311
+ # fatal: %i[white bold on_red],
312
+ # unknown: %i[white bold],
313
+ # any: %i[white bold]
314
+ # }
315
+ ----
316
+
317
+ 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:
318
+
319
+ [source,ruby]
320
+ ----
321
+ Cogger.add_alias :mystery, :white, :on_purple
322
+ ----
323
+
324
+ Once an alias is added, it can be immediately applied via the template of your formatter. Example:
325
+
326
+ [source,ruby]
327
+ ----
328
+ # Applies the `mystery` alias universally to your template.
329
+ logger = Cogger.new formatter: Cogger::Formatters::Color.new("<mystery>%<message>s</mystery>")
330
+ ----
331
+
332
+ ==== JSON
140
333
 
141
- Default colors are provided by the `Cogger::Color` class which are keyed by log level:
334
+ 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:
142
335
 
143
336
  [source,ruby]
144
337
  ----
145
- {
146
- debug: %i[white],
147
- info: %i[green],
148
- warn: %i[yellow],
149
- error: %i[red],
150
- fatal: %i[white bold on_red],
151
- unknown: %i[white bold],
152
- any: %i[white bold]
153
- }
338
+ # Default order
339
+ logger = Cogger.new formatter: :json
340
+ logger.info verb: "GET", path: "/"
341
+
342
+ # {"id":"console","severity":"INFO","at":"2023-04-10 09:03:55 -0600","verb":"GET","path":"/"}
343
+
344
+ # Custom order
345
+ logger = Cogger.new formatter: Cogger::Formatters::JSON.new("%<severity>s %<verb>s")
346
+ logger.info verb: "GET", path: "/"
347
+
348
+ # {"severity":"INFO","verb":"GET","id":"console","at":"2023-04-10 09:05:03 -0600","path":"/"}
154
349
  ----
155
350
 
156
- All keys require an array of styles which can then be decorated by {pastel_link}. This means that if
157
- you wanted to use custom colors, you could create a new instance of the `Color` class and inject it
158
- into the client as follows:
351
+ 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.
352
+
353
+ ==== Custom
159
354
 
355
+ 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:
160
356
 
161
357
  [source,ruby]
162
358
  ----
163
- custom_color = Cogger::Color.new(
164
- defaults: {
165
- debug: %i[white on_black],
166
- info: %i[green on_black],
167
- warn: %i[yellow on_black],
168
- error: %i[red on_black],
169
- fatal: %i[red on_black],
170
- unknown: %i[white on_black],
171
- any: %i[white on_black]
172
- }
173
- )
359
+ class MyFormatter
360
+ TEMPLATE = "%<message>s"
361
+
362
+ def initialize template = TEMPLATE, sanitizer: Kit::Sanitizer.new
363
+ @template = template
364
+ @sanitizer = sanitizer
365
+ end
174
366
 
175
- logger = Cogger.init color: custom_color
367
+ def call(*entry) = "#{format template, sanitizer.call(*entry)}\n"
368
+
369
+ private
370
+
371
+ attr_reader :template, :sanitizer
372
+ end
176
373
  ----
177
374
 
178
- The above would ensure all log level colors are displayed on a black background. Basically, any
179
- style accepted by `Pastel#decorate` method is supported.
375
+ 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] or look at any of the formatters provided within this gem.
180
376
 
181
- ==== Testing
377
+ === Filters
378
+
379
+ Filters allow you to mask sensitive information you don't want showing up in your logs. Here are the defaults:
380
+
381
+ [source,ruby]
382
+ ----
383
+ Cogger.filters
384
+
385
+ # [
386
+ # :_csrf,
387
+ # :password,
388
+ # :password_confirmation
389
+ # ]
390
+ ----
391
+
392
+ To add additional filters, use:
393
+
394
+ [source,ruby]
395
+ ----
396
+ Cogger.add_filter(:login)
397
+ .add_filter "email"
398
+
399
+ # [
400
+ # :_csrf,
401
+ # :password,
402
+ # :password_confirmation,
403
+ # :login,
404
+ # :email
405
+ # ]
406
+ ----
407
+
408
+ 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:
409
+
410
+ [source,ruby]
411
+ ----
412
+ logger = Cogger.new formatter: :json
413
+ logger.info login: "jayne", password: "secret"
414
+
415
+ # {"id":"console","severity":"INFO","at":"2023-04-09 17:33:00 -0600","login":"[FILTERED]","password":"[FILTERED]"}
416
+ ----
417
+
418
+ === Testing
182
419
 
183
420
  When testing the Cogger client, you might find it convenient to use `StringIO`, or a file, for
184
421
  logging purposes in order to not pollute your test output but also have a convenient way to see what
@@ -187,7 +424,7 @@ was logged. Example:
187
424
  [source,ruby]
188
425
  ----
189
426
  class Demo
190
- def initialize logger: Cogger.init
427
+ def initialize logger: Cogger.new
191
428
  @logger = logger
192
429
  end
193
430
 
@@ -199,22 +436,24 @@ class Demo
199
436
  end
200
437
 
201
438
  RSpec.describe Demo do
439
+ using Refinements::StringIOs
440
+
202
441
  subject(:demo) { described_class.new logger: }
203
442
 
204
- let(:logger) { Cogger.init Logger.new(StringIO.new) }
443
+ let(:logger) { Cogger.new io: }
444
+ let(:io) { StringIO.new }
205
445
 
206
446
  describe "#say" do
207
447
  it "logs text" do
208
448
  demo.say "test"
209
- expect(logger.reread).to include("test")
449
+ expect(io.reread).to include("test")
210
450
  end
211
451
  end
212
452
  end
213
453
  ----
214
454
 
215
455
  Notice that when testing the instance of `Demo` and injecting a logger which logs to a string I/O
216
- object, you can conveniently reread that string to see what was logged. This makes your specs easier
217
- to write while also not adding additional noise to your test suite's output.
456
+ object, you can conveniently _reread_ the string -- provided by the {refinements_link} gem -- to see what was logged. This makes your specs easier to write while also not adding additional noise to your test suite's output.
218
457
 
219
458
  == Development
220
459
 
data/cogger.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "cogger"
5
- spec.version = "0.6.0"
5
+ spec.version = "0.7.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/cogger"
9
- spec.summary = "Decorates native logging with colorized output."
9
+ spec.summary = "A customizable logger."
10
10
  spec.license = "Hippocratic-2.1"
11
11
 
12
12
  spec.metadata = {
@@ -23,8 +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 "pastel", "~> 0.8"
27
- spec.add_dependency "refinements", "~> 10.0"
26
+ spec.add_dependency "tone", "~> 0.1"
28
27
  spec.add_dependency "zeitwerk", "~> 2.6"
29
28
 
30
29
  spec.extra_rdoc_files = Dir["README*", "LICENSE*"]
data/lib/cogger/client.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require "forwardable"
4
4
  require "logger"
5
5
  require "refinements/loggers"
6
+ require "tone"
6
7
 
7
8
  module Cogger
8
9
  # Provides the primary client for colorized logging.
@@ -13,7 +14,7 @@ module Cogger
13
14
 
14
15
  delegate %i[formatter level progname debug info warn error fatal unknown] => :logger
15
16
 
16
- def initialize logger = Logger.new($stdout), color: Color.new, **attributes
17
+ def initialize logger = Logger.new($stdout), color: Cogger.color, **attributes
17
18
  @logger = logger
18
19
  @color = color
19
20
  @attributes = attributes
@@ -42,7 +43,7 @@ module Cogger
42
43
  def default_level = logger.class.const_get ENV.fetch("LOG_LEVEL", "INFO")
43
44
 
44
45
  def default_formatter
45
- -> severity, _at, _name, message { "#{color.public_send severity.downcase, message}\n" }
46
+ -> severity, _at, _name, message { "#{color[message, severity.downcase]}\n" }
46
47
  end
47
48
  end
48
49
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+
5
+ module Cogger
6
+ # Defines the default configuration for all pipes.
7
+ Configuration = Data.define(
8
+ :id,
9
+ :io,
10
+ :level,
11
+ :formatter,
12
+ :mode,
13
+ :age,
14
+ :size,
15
+ :suffix,
16
+ :logger
17
+ ) do
18
+ def initialize id: Program.call,
19
+ io: $stdout,
20
+ level: Logger.const_get(ENV.fetch("LOG_LEVEL", "INFO")),
21
+ formatter: Formatters::Color.new,
22
+ mode: false,
23
+ age: 0,
24
+ size: 1_048_576,
25
+ suffix: "%Y-%m-%d",
26
+ logger: Logger
27
+ super
28
+ end
29
+
30
+ def to_logger
31
+ logger.new io,
32
+ age,
33
+ size,
34
+ progname: id,
35
+ level:,
36
+ formatter:,
37
+ binmode: mode,
38
+ shift_period_suffix: suffix
39
+ end
40
+
41
+ def inspect
42
+ "#<#{self.class} @id=#{id}, @io=#{io.class}, @level=#{level}, " \
43
+ "@formatter=#{formatter.class}, " \
44
+ "@mode=#{mode}, @age=#{age}, @size=#{size}, @suffix=#{suffix.inspect}, " \
45
+ "@logger=#{logger}>"
46
+ end
47
+ end
48
+ end