ruby_smart-simple_logger 1.2.2 → 1.4.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: f93f509aad065f314393b0b7f630694091fb06c967bc20ad1fe4e0b7683f843b
4
- data.tar.gz: 9d5a325fac9bc01ad330cec1c1c31a9bc3f5602e1934893b04ab5f3baed22ac0
3
+ metadata.gz: 499ca8f400db9b2df6a9e3017fece6c7e2b94c32c72feb2d04c3a7013a946c4e
4
+ data.tar.gz: f684b602ec79afe45e2cebf5b158eacfab127cd1af7e9aee994a7ec824b0f802
5
5
  SHA512:
6
- metadata.gz: 5b4b91d4c70cd0e373af89191b9147739a55443e851ffdc8751e3853d833e04f59cd9aa6d125a60c752e924686a190d8bd492560860e91d18749af48adc210d4
7
- data.tar.gz: 5cb89dd0a2cf9b77f3ce2cbc4bcf7c9f8ee218fb9030a16c9bba0259ac5ca16bf82fcdffef2602533b567b2591d94f672662a46e3562b8a1fdee398980137718
6
+ metadata.gz: aa7911b6005d56ffc56585674bd90ff47f07bb0e632b08447c52e4f4222996ca52d783ab44fcae057b034b2920f0b7e0e5cb044be66a7c79be4dcb1ff18abcc6
7
+ data.tar.gz: 9f1ae4aed0ca7965cbe57d24223a7283915cf7ab876a467945da7269ea6bb66f292704f7e48400a260542eb5b35dc0898b277c5ad338443e459a529e9f5bebf5
@@ -18,21 +18,17 @@ permissions:
18
18
 
19
19
  jobs:
20
20
  test:
21
-
22
- runs-on: ubuntu-latest
23
21
  strategy:
22
+ fail-fast: false
24
23
  matrix:
25
- ruby-version: ['3.1', '3.0', '2.7', '2.6']
26
-
24
+ os: [ubuntu-latest]
25
+ # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0'
26
+ ruby: ['3.2', '3.1', '3.0', '2.7', '2.6']
27
+ runs-on: ${{ matrix.os }}
27
28
  steps:
28
- - uses: actions/checkout@v3
29
- - name: Set up Ruby
30
- # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
31
- # change this to (see https://github.com/ruby/setup-ruby#versioning):
32
- # uses: ruby/setup-ruby@v1
33
- uses: ruby/setup-ruby@0a29871fe2b0200a17a4497bae54fe5df0d973aa # v1.115.3
34
- with:
35
- ruby-version: ${{ matrix.ruby-version }}
36
- bundler-cache: true # runs 'bundle install' and caches installed gems automatically
37
- - name: Run tests
38
- run: bundle exec rake
29
+ - uses: actions/checkout@v3
30
+ - uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: ${{ matrix.ruby }}
33
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
34
+ - run: bundle exec rake
data/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  [![Coverage Status](https://coveralls.io/repos/github/ruby-smart/simple_logger/badge.svg?branch=main&kill_cache=1)](https://coveralls.io/github/ruby-smart/simple_logger?branch=main)
10
10
  [![Tests](https://github.com/ruby-smart/simple_logger/actions/workflows/ruby.yml/badge.svg)](https://github.com/ruby-smart/simple_logger/actions/workflows/ruby.yml)
11
11
 
12
- A simple, multifunctional logging library for Ruby.
12
+ A simple, multifunctional logging library for Ruby (and Rails).
13
13
  It features a fast, customizable logging with multi-device support (e.g. log to STDOUT AND file).
14
14
  Special (PRE-defined) scenes can be used for interactive CLI and better logging visibility.
15
15
 
@@ -36,7 +36,7 @@ Or install it yourself as:
36
36
  ## Enhancements
37
37
  * PRE-defined scenes to fastly create a simple, structured CLI output. _(see [Scenes](#scenes))_
38
38
  * Better log-visibility with masked output through scenes
39
- * ```awesome_print``` gem compatibility for a prettified object debug
39
+ * `awesome_print` gem compatibility for a prettified object debug
40
40
  * Multi-device support (write to logfile & to STDOUT & to ... & to ...)
41
41
  * 'klass_logger' instances for easier access _(see [klass_logger](#klass_logger_Usage))_
42
42
 
@@ -198,10 +198,11 @@ While you can just build a new logger _(or use the klass_logger)_ without any ar
198
198
 
199
199
  ### nil Builtin
200
200
 
201
- A ```nil``` builtin will auto-detect the best logging solution for you.
202
- For CLI or windowed programs it'll just send the logs to ```STDOUT```.
203
- For rails-applications it'll send to the current ```Rails.logger``` instance.
204
- Otherwise it'll store logs temporary in memory _(accessible through the #logs method)_
201
+ A `nil` builtin will auto-detect the best logging solution for you:
202
+ * For CLI or windowed programs it'll just send the logs to `STDOUT`.
203
+ * For Debugging _(e.g. IDE-related debugging gems)_ it'll send the logs to the `Debugger`.
204
+ * For rails-applications it'll send to the current `Rails.logger` instance.
205
+ * Otherwise it'll store logs temporary in memory _(accessible through the #logs method)_
205
206
 
206
207
  **Example:**
207
208
  ```ruby
@@ -211,7 +212,7 @@ logger.debug "some debug"
211
212
 
212
213
  ### stdout / stderr Builtin
213
214
 
214
- A ```:stdout / :stderr``` builtin will send to ```STDOUT / STDERR``` and uses a colored output by default.
215
+ A `:stdout / :stderr` builtin will send to `STDOUT / STDERR` and uses a colored output by default.
215
216
 
216
217
  **Example:**
217
218
  ```ruby
@@ -224,9 +225,34 @@ logger = ::SimpleLogger.new(:stdout)
224
225
  logger.debug "some debug"
225
226
  ```
226
227
 
228
+ ### debugger Builtin
229
+
230
+ A `:debugger` builtin will send to the `Debugger` (e.g. your IDE's debugging gem)
231
+
232
+ **Example:**
233
+ ```ruby
234
+ logger = ::SimpleLogger.new(:debugger)
235
+
236
+ # > will be shown within your debugging gem
237
+ logger.debug "some debug"
238
+ ```
239
+
240
+
241
+ ### null Builtin
242
+
243
+ A `:null` builtin will silently swallow all logging data (so it will not be send).
244
+
245
+ **Example:**
246
+ ```ruby
247
+ logger = ::SimpleLogger.new(:null)
248
+
249
+ # >
250
+ logger.debug "some debug"
251
+ ```
252
+
227
253
  ### rails Builtin
228
254
 
229
- A ```:rails``` builtin will always send to the ```Rails.logger``` instance.
255
+ A `:rails` builtin will always send to the `Rails.logger` instance.
230
256
 
231
257
  **Example:**
232
258
  ```ruby
@@ -238,9 +264,9 @@ logger.debug "some debug"
238
264
 
239
265
  ### proc Builtin
240
266
 
241
- A ```:proc``` builtin will call the provided proc _(through ```options[:proc]```)_ everytime a log will be written.
267
+ A `:proc` builtin will call the provided proc _(through `options[:proc]```)_ everytime a log will be written.
242
268
 
243
- The data will be provided as array _( ```[severity, time, progname, data]``` )_.
269
+ The data will be provided as array _( `[severity, time, progname, data]` )_.
244
270
 
245
271
  **Example:**
246
272
  ```ruby
@@ -255,7 +281,7 @@ logger.debug "some debug"
255
281
 
256
282
  ### memory Builtin
257
283
 
258
- A ```:memory``` builtin will always store the logged data within an _instance variable_ and can be accessed through the ```#logs``` or ```#logs_to_h``` methods.
284
+ A `:memory` builtin will always store the logged data within an _instance variable_ and can be accessed through the `#logs` or `#logs_to_h` methods.
259
285
 
260
286
  **Example:**
261
287
  ```ruby
@@ -276,7 +302,7 @@ logger.logs
276
302
 
277
303
  ### String Builtin
278
304
 
279
- Providing a ```String``` will always create and write to a new logfile.
305
+ Providing a `String` will always create and write to a new logfile.
280
306
 
281
307
  **Example:**
282
308
  ```ruby
@@ -313,7 +339,7 @@ noformat_logger.debug "some debug without color and mask - uses the default form
313
339
 
314
340
  ### Module Builtin
315
341
 
316
- Providing a ```module``` will also create and write to a new logfile.
342
+ Providing a `module` will also create and write to a new logfile.
317
343
  The path depends on the provided module name.
318
344
 
319
345
  **Example:**
@@ -331,13 +357,13 @@ logger.debug "some debug"
331
357
 
332
358
  ### other Builtin
333
359
 
334
- Providing any other Object must respond to ```#write```.
360
+ Providing any other Object must respond to `#write```.
335
361
 
336
362
  -----
337
363
 
338
364
  ## Formats
339
365
 
340
- The default formatter _(if no other was provided through ```opts[:formatter```)_ will provide the following PRE-defined formats:
366
+ The default formatter _(if no other was provided through `opts[:formatter```)_ will provide the following PRE-defined formats:
341
367
  _Also prints a colored output by default._
342
368
 
343
369
  ### default Format
@@ -447,7 +473,7 @@ logger = ::SimpleLogger.new(:stdout, payload: false)
447
473
  ### format
448
474
 
449
475
  Provide a other format.
450
- Possible values: ```:default, :passthrough, :plain, :memory, :datalog```
476
+ Possible values: `:default, :passthrough, :plain, :memory, :datalog```
451
477
  ```ruby
452
478
  logger = ::SimpleLogger.new(format: :default)
453
479
  logger = ::SimpleLogger.new(:memory, format: :passthrough)
@@ -465,7 +491,7 @@ logger.debug "debug 2"
465
491
 
466
492
  ### proc _(:proc-builtin ONLY)_
467
493
 
468
- Provide a callback for the ```:proc``` builtin.
494
+ Provide a callback for the `:proc` builtin.
469
495
  ```ruby
470
496
  logger = ::SimpleLogger.new(:proc, proc: lambda{|data| ... })
471
497
  ```
@@ -528,7 +554,7 @@ logger.debug({a: {custom: 'object'}})
528
554
 
529
555
  ### inspector
530
556
 
531
- Provide a other ```inspector``` method for the data-debug.
557
+ Provide a other `inspector` method for the data-debug.
532
558
 
533
559
  ```ruby
534
560
  logger = ::SimpleLogger.new(inspector: :to_s)
@@ -541,13 +567,13 @@ logger.debug({ a: 1, b: 2 })
541
567
 
542
568
  ## _defaults_
543
569
 
544
- Device default options are still available: ```shift_age, shift_size, progname, datetime_format, shift_period_suffix, binmode```
570
+ Device default options are still available: `shift_age, shift_size, progname, datetime_format, shift_period_suffix, binmode```
545
571
 
546
572
  -----
547
573
 
548
574
  ## Scenes
549
575
 
550
- The following PRE-defined scenes are available. _(You can define your own scenes by using the class method ```.scene```)_
576
+ The following PRE-defined scenes are available. _(You can define your own scenes by using the class method `.scene```)_
551
577
 
552
578
  ### debug(data, subject = 'Debug')
553
579
  ```ruby
@@ -560,7 +586,7 @@ The following PRE-defined scenes are available. _(You can define your own scenes
560
586
  # > ==========================================================================================================
561
587
  ```
562
588
 
563
- ### info, warn, error, fatal, success (data, subject = 'name')
589
+ ### info, warn, error, fatal, unknown, success (data, subject = 'name')
564
590
  ```ruby
565
591
  # info method (BASE)
566
592
  # severity: methods name
@@ -748,19 +774,19 @@ l.processed("Process Alpha", timer: true) do
748
774
  end
749
775
 
750
776
 
751
- # ╔ START :: Process Alpha
777
+ # ╔ START Process Alpha
752
778
  # ╟ find files
753
779
  # ╟ found 34 files
754
- # ║ ┌ START :: extracting ...
780
+ # ║ ┌ START extracting ...
755
781
  # ║ ├ 10% done
756
782
  # ║ ├ 20% done
757
783
  # ║ ├ 100% done
758
- # ║ └ END [SUCCESS] (duration: 0.000267545)
759
- # ║ ┌ START :: transforming ...
784
+ # ║ └ END ❯ extracting ... [SUCCESS] (0.000244804)
785
+ # ║ ┌ START transforming ...
760
786
  # ║ ├ bad memory
761
787
  # ║ ├ rolling back
762
- # ║ └ END [FAILED]
763
- # ╚ END [Process Alpha] (duration: 0.001040807)
788
+ # ║ └ END ❯ transforming ... [FAIL]
789
+ # ╚ END Process Alpha (0.001036969)
764
790
  ```
765
791
 
766
792
  ### _other useful methods_
@@ -768,6 +794,7 @@ end
768
794
  - line
769
795
  - print
770
796
  - nl
797
+ - model _(rails only)_
771
798
 
772
799
  -----
773
800
 
@@ -784,7 +811,7 @@ This project is intended to be a safe, welcoming space for collaboration, and co
784
811
 
785
812
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
786
813
 
787
- A copy of the [LICENSE](docs/LICENSE.txt) can be found @ the docs.
814
+ A copy of the [LICENSE](LICENSE.txt) can be found @ the docs.
788
815
 
789
816
  ## Code of Conduct
790
817
 
data/docs/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # RubySmart::SimpleLogger - CHANGELOG
2
2
 
3
+ ## [1.4.0] - 2024-07-31
4
+ * **[add]** 'null'-device / builtin
5
+ * **[add]** 'debugger'-builtin to send logs to the debugging gem
6
+ * **[add]** new logging method `model` _(for rails applications only)_
7
+ * **[ref]** `nil`-builtin to detect `Debugger` after checking for stdout
8
+ * **[ref]** `mask`-length to 120 _(was 100 by default)_
9
+ * **[ref]** `ruby_smart-support`-gem dependency to 1.5
10
+ * **[fix]** exception _(to build a new device)_ if a Logger was provided
11
+ * **[fix]** mask-reference manipulation on inherited classes
12
+
13
+ ## [1.3.0] - 2023-08-15
14
+ * **[add]** exception message within `processed`-scene
15
+ * **[add]** new logging option `tag`, to prefix a log-string with a [TAG]
16
+ * **[add]** logger options `processed: false` & `tagged: false` to prevent processing or tagging
17
+ * **[add]** `_tagged`-helper method
18
+ * **[add]** `__scene_subject_with_opts`-helper method to grep subject&opts from args (used for default severities)
19
+ * **[add]** additional box_chars for 'tagged' & 'feed' extensions - used @ `processed`-scene
20
+ * **[add]** `unknown`-scene
21
+ * **[ref]** `processed`-scene with better logging chars & homogenous syntax for humanized reading
22
+ * **[fix]** missing '_declr' for memory formatting (only on Strings)
23
+ * **[fix]** missing 'clr:false' option for memory devices
24
+ * **[fix]** exception while in `processed`-scene not logging the END-line
25
+ * **[fix]** re-using timer-methods with the same key, did not restart the 'total' measurement
26
+
3
27
  ## [1.2.2] - 2023-03-15
4
28
  * **[ref]** simplify device-generation for builtins
5
29
  * **[fix]** `ActionView::Helpers::DateHelper` require, which breaks rails loading process in some cases
@@ -4,7 +4,6 @@ module RubySmart
4
4
  module SimpleLogger
5
5
  module Devices
6
6
  class MemoryDevice
7
-
8
7
  attr_reader :logs
9
8
  attr_reader :status
10
9
 
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubySmart
4
+ module SimpleLogger
5
+ module Devices
6
+ class NullDevice
7
+ attr_reader :status
8
+
9
+ def initialize
10
+ @status = true
11
+ end
12
+
13
+ def write(*)
14
+ nil
15
+ end
16
+
17
+ alias_method :<<, :write
18
+
19
+ # disables writing
20
+ def close
21
+ @status = false
22
+ end
23
+
24
+ # enables writing
25
+ def reopen
26
+ @status = true
27
+ end
28
+
29
+ # clears all logs
30
+ def clear!
31
+ nil
32
+ end
33
+
34
+ # returns logs
35
+ # @return [Array] logs
36
+ def logs
37
+ []
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -14,8 +14,7 @@ module RubySmart
14
14
  # set / overwrite default opts
15
15
  # @param [Hash] opts
16
16
  def _opts_init!(opts)
17
- ##################################################################################
18
- # level
17
+ # -- level ---------------------------------------------------------------------------------------------------
19
18
 
20
19
  # initialize a default rails-dependent output
21
20
  if ::ThreadInfo.rails?
@@ -25,8 +24,7 @@ module RubySmart
25
24
  # clean & rewrite level (possible symbols) to real level
26
25
  opts[:level] = _level(opts[:level] || :debug)
27
26
 
28
- ##################################################################################
29
- # mask
27
+ # -- mask ----------------------------------------------------------------------------------------------------
30
28
 
31
29
  # set mask from options
32
30
  self.mask(opts[:mask]) if opts[:mask]
@@ -39,13 +37,18 @@ module RubySmart
39
37
  self.mask(length: ::ThreadInfo.winsize[1])
40
38
  end
41
39
 
42
- ##################################################################################
43
- # instance related
40
+ # -- instance related ----------------------------------------------------------------------------------------
44
41
 
45
42
  # ignore payload and send data directly to the logdev
46
- @ignore_payload = true if @ignore_payload.nil? && opts[:payload] == false
43
+ @ignore_payload = true if @ignore_payload.nil? && opts[:payload] == false
47
44
 
48
- # set the inspector to be used for data inspection.
45
+ # ignore processed logging and send data without 'leveling' & PCD-char to the logdev
46
+ @ignore_processed = true if @ignore_processed.nil? && opts[:processed] == false
47
+
48
+ # ignore tagged logging and send data without 'tags' to the logdev
49
+ @ignore_tagged = true if @ignore_tagged.nil? && opts[:tagged] == false
50
+
51
+ # set custom inspector (used for data inspection)
49
52
  # 'disable' inspector, if false was provided - which simply results in +#to_s+
50
53
  @inspector = (opts[:inspect] == false) ? :to_s : opts[:inspector]
51
54
 
@@ -113,7 +116,7 @@ module RubySmart
113
116
  opts[:format] ||= :plain
114
117
 
115
118
  # fix nl - which depends on other opts
116
- opts[:nl] = _nl(opts)
119
+ opts[:nl] = _nl(opts)
117
120
 
118
121
  # fix clr
119
122
  opts[:clr] = true if opts[:clr].nil?
@@ -129,11 +132,19 @@ module RubySmart
129
132
  when nil # builtin is nil - resolve optimal device for current environment
130
133
  if ::ThreadInfo.stdout?
131
134
  _resolve_device(:stdout, opts)
135
+ elsif ::ThreadInfo.debugger?
136
+ _resolve_device(:debugger, opts)
132
137
  elsif ::ThreadInfo.rails? && ::Rails.logger
133
138
  _resolve_device(:rails, opts)
134
139
  else
135
140
  _resolve_device(:memory, opts)
136
141
  end
142
+ when :null
143
+ ::RubySmart::SimpleLogger::Devices::NullDevice.new
144
+ when :debugger
145
+ raise "Unable to build SimpleLogger with 'debugger' builtin for not initialized Debugger!" unless ThreadInfo.debugger?
146
+
147
+ _resolve_device(::Debugger.logger, opts)
137
148
  when :stdout
138
149
  STDOUT
139
150
  when :stderr
@@ -145,27 +156,31 @@ module RubySmart
145
156
  if ThreadInfo.console? && ::Rails.logger.instance_variable_get(:@logdev).dev != STDOUT
146
157
  ::RubySmart::SimpleLogger::Devices::MultiDevice
147
158
  .register(_resolve_device(:stdout, opts))
148
- .register(::Rails.logger.instance_variable_get(:@logdev).dev)
159
+ .register(_resolve_device(::Rails.logger, opts))
149
160
  else
150
- ::Rails.logger.instance_variable_get(:@logdev).dev
161
+ _resolve_device(::Rails.logger, opts)
151
162
  end
152
163
  when :proc
153
164
  # force overwrite opts
154
165
  @ignore_payload = true
155
- opts[:nl] = false
156
- opts[:format] = :passthrough
166
+ opts[:nl] = false
167
+ opts[:format] = :passthrough
157
168
 
158
169
  ::RubySmart::SimpleLogger::Devices::ProcDevice.new(opts.delete(:proc))
159
170
  when :memory
160
171
  # force overwrite opts
161
172
  @ignore_payload = true
162
- opts[:format] = :memory
173
+ opts[:format] = :memory
174
+ # no color logging for memory devices
175
+ opts[:clr] = false
163
176
 
164
177
  ::RubySmart::SimpleLogger::Devices::MemoryDevice.new
165
178
  when Module, String
166
179
  # force overwrite opts
167
180
  opts[:clr] = false
168
181
  _logdev(opts, builtin)
182
+ when ::Logger
183
+ builtin.instance_variable_get(:@logdev).dev
169
184
  else
170
185
  _logdev(opts, builtin)
171
186
  end
@@ -275,6 +290,18 @@ module RubySmart
275
290
  end
276
291
  end
277
292
 
293
+ # 'tags' a provided string
294
+ # returns the string if no tag was provided or general tags are disabled
295
+ # @param [String] str
296
+ # @param [nil|Symbol|String] tag
297
+ # @return [String]
298
+ def _tagged(str, tag = nil)
299
+ # check for active tag
300
+ return str if tag.nil? || ignore_tagged?
301
+
302
+ "#{"[#{tag.to_s.upcase.bg_cyan}]"} #{str}"
303
+ end
304
+
278
305
  # colorizes a provided string
279
306
  # returns the string if no color was provided or invalid
280
307
  #
@@ -343,6 +370,19 @@ module RubySmart
343
370
  res_or_clr.to_sym
344
371
  end
345
372
  end
373
+
374
+ # resolves subject & opts from provided args.
375
+ # returns provided default subject, if not in args.
376
+ # @param [Object] args
377
+ # @param [String] subject
378
+ # @return [Array]
379
+ def _scene_subject_with_opts(args, subject = '')
380
+ if args[0].is_a?(Hash)
381
+ [subject, args[0]]
382
+ else
383
+ [args[0] || subject, args[1] || {}]
384
+ end
385
+ end
346
386
  end
347
387
  end
348
388
  end
@@ -13,17 +13,25 @@ module RubySmart
13
13
  # @option [String] :char - the character to be used as mask
14
14
  # @option [Integer] :length - the mask length (amount of mask chars be line)
15
15
  # @option [Symbol] :clr - the color to be used by printing the mask
16
- self.mask = { char: '=', length: 100, clr: :blue }
16
+ self.mask = { char: '=', length: 120, clr: :blue }
17
17
  end
18
18
  end
19
19
 
20
20
  module ClassMethods
21
21
  def mask
22
- class_variable_get('@@mask')
22
+ @mask
23
23
  end
24
24
 
25
25
  def mask=(mask)
26
- class_variable_set('@@mask', mask)
26
+ @mask = mask
27
+ end
28
+
29
+ # prevents to overwrite parent class through inheriting subclasses
30
+ def inherited(subclass)
31
+ super
32
+
33
+ # dup existing values
34
+ subclass.mask = self.mask.dup
27
35
  end
28
36
  end
29
37
 
@@ -12,10 +12,15 @@ module RubySmart
12
12
  base.class_eval do
13
13
  # set default box chars
14
14
  self.box_chars = {
15
- __default__: %w(╟ ├),
16
- __processed__: %w( ),
15
+ # control characters by provided +:pcd+
16
+ default: %w( ),
17
17
  start: %w(╔ ┌),
18
- end: %w(╚ └)
18
+ end: %w(╚ └),
19
+
20
+ # additional characters, added ad specific position
21
+ __processed__: %w(║ │),
22
+ __feed__: %w(═ ─),
23
+ __tagged__: %w(┄ ┄),
19
24
  }.freeze
20
25
  end
21
26
  end
@@ -33,18 +38,20 @@ module RubySmart
33
38
  module InstanceMethods
34
39
  # returns the current processed level.
35
40
  # by providing a handle it will either increase or decrease the current level.
36
- # @param [nil, Symbol] handle - optional handle to increase or decrease the current lvl (+:up+ / +:down+)
41
+ # @param [Symbol|Integer] handle - optional handle to increase or decrease the current lvl (+:up+ / +:down+)
37
42
  # @return [Integer]
38
43
  def processed_lvl(handle = nil)
39
44
  @processed_lvl ||= -1
40
45
 
41
46
  case handle
47
+ when :reset
48
+ @processed_lvl = -1
42
49
  when :up
43
50
  @processed_lvl += 1
44
51
  when :down
45
52
  @processed_lvl -= 1 if @processed_lvl >= 0
46
53
  else
47
- # nothing here ...
54
+ @processed_lvl = handle if handle.is_a?(Integer)
48
55
  end
49
56
 
50
57
  @processed_lvl
@@ -53,25 +60,54 @@ module RubySmart
53
60
  # returns true if the processed state is active.
54
61
  # @return [Boolean]
55
62
  def processed?
56
- processed_lvl >= 0
63
+ processed_lvl >= 0 && !@ignore_processed
57
64
  end
58
65
 
59
66
  private
60
67
 
61
68
  # transforms the provided data into a 'processed' string and forces the data to be transformed to string.
62
69
  # simple returns the provided data, if currently not processed.
63
- # @param [Object] data
70
+ # @param [String] data
64
71
  # @param [Hash] opts
65
- # @return [Object,String]
72
+ # @return [String]
66
73
  def _pcd(data, opts)
67
74
  # check for active pcd (processed)
68
75
  return data if opts[:pcd] == false || !processed?
69
76
 
70
- # resolve lvl, once
77
+ # resolve the current level - either directly through the options or the +processed_lvl+.
71
78
  lvl = opts[:lvl] || processed_lvl
72
79
 
73
- # create final string
74
- lvl.times.map { |i| "#{_pcd_box_char(:__processed__, i)} " }.join + _pcd_box_char(opts[:pcd], lvl) + " #{data}"
80
+ # prepares the out-string array
81
+ strs = []
82
+
83
+ # add level-charters with indent
84
+ lvl.times.each { |i|
85
+ # ║ │
86
+ strs << _pcd_box_char(:__processed__, i) + ' '
87
+ }
88
+
89
+ # add pcd-related control character
90
+ strs << _pcd_box_char(opts[:pcd], lvl)
91
+
92
+ # add pcd-operation string
93
+ if opts[:pcd].is_a?(Symbol)
94
+ # ╔ START ❯
95
+ # └ END ❯
96
+ strs << " #{opts[:pcd].to_s.upcase.rjust(5)} \u276F"
97
+ end
98
+
99
+ # check for tagged
100
+ # ┄
101
+ if opts[:tag]
102
+ strs << _pcd_box_char(:__tagged__, lvl)
103
+ else
104
+ strs << ' '
105
+ end
106
+
107
+ # add data
108
+ strs << data.to_s
109
+
110
+ strs.join
75
111
  end
76
112
 
77
113
  # returns the processed box character for provided key and position.
@@ -81,7 +117,7 @@ module RubySmart
81
117
  # @param [Integer] pos
82
118
  # @return [String]
83
119
  def _pcd_box_char(key, pos = 0)
84
- chars = self.class.box_chars[key] || self.class.box_chars[:__default__]
120
+ chars = self.class.box_chars[key] || self.class.box_chars[:default]
85
121
  chars[pos] || chars[-1]
86
122
  end
87
123
  end
@@ -53,7 +53,7 @@ module RubySmart
53
53
  # prevent logging nil data
54
54
  return false if data.nil?
55
55
 
56
- add level, _pcd(data, opts)
56
+ add level, _parse_data(data, opts)
57
57
  return true
58
58
  end
59
59
 
@@ -82,6 +82,14 @@ module RubySmart
82
82
  !!@ignore_payload
83
83
  end
84
84
 
85
+ # returns true if no tags should be created - instead the data will be send directly to the logdev
86
+ # forces the *simple_log* method to prevent building tags from opts
87
+ #
88
+ # @return [Boolean]
89
+ def ignore_tagged?
90
+ !!@ignore_tagged
91
+ end
92
+
85
93
  # resolve an inspector method for data inspection
86
94
  # @return [Symbol, nil]
87
95
  def inspector
@@ -107,7 +115,7 @@ module RubySmart
107
115
  str = ''
108
116
  if payload == self.class::PAYLOAD_DATA_KEY
109
117
  # checks, if we should inspect the data
110
- str << _parse_data(data, (opts[:inspect] ? (opts[:inspector] || self.inspector) : nil))
118
+ str << _parse_inspect_data(data, opts)
111
119
  else
112
120
  str << _parse_payload(payload, opts)
113
121
  end
@@ -121,13 +129,33 @@ module RubySmart
121
129
  true
122
130
  end
123
131
 
124
- # just parses the data and calls an inspection method, if provided
132
+ # parses the provided data to string.
133
+ # - calls an inspection method, if provided
134
+ # - tags the string, if provided
135
+ # - adds processed prefix-chars, if provided
125
136
  #
126
137
  # @param [Object] data
127
- # @param [Symbol, nil] inspector - the inspection method to be called (e.g. :ai, :inspect, :to_s) - if not provided it tries to auto-resolve
138
+ # @param [Hash] opts
139
+ # @return [String] stringified data
140
+ def _parse_data(data, opts)
141
+ _pcd(
142
+ _tagged(
143
+ data.to_s,
144
+ opts[:tag]
145
+ ),
146
+ opts
147
+ )
148
+ end
149
+
150
+ # parses the provided data to string, but calls a possible inspect method.
151
+ # @param [Object] data
152
+ # @param [Hash] opts
128
153
  # @return [String] stringified data
129
- def _parse_data(data, inspector = nil)
130
- (inspector ? data.send(inspector) : data).to_s
154
+ def _parse_inspect_data(data, opts)
155
+ _parse_data(
156
+ data.send(opts[:inspect] ? (opts[:inspector] || self.inspector) : :to_s),
157
+ opts
158
+ )
131
159
  end
132
160
 
133
161
  # parses a single payload with provided options
@@ -5,21 +5,23 @@ module RubySmart
5
5
  module Extensions
6
6
  module Timer
7
7
  def timer(action, key = :default, opts = {})
8
+ return if key.nil?
9
+
8
10
  @timers ||= {}
9
11
  @timers[key] ||= {
10
12
  start: nil,
11
13
  stop: nil,
12
- measure: 0
14
+ total: 0
13
15
  }
14
16
 
15
17
  case action
16
- when :restart
18
+ when :start, :restart
17
19
  @timers[key][:start] = Time.now
18
20
  @timers[key][:stop] = nil
19
- @timers[key][:measure] = 0
21
+ @timers[key][:total] = 0
20
22
 
21
23
  true
22
- when :start, :continue
24
+ when :continue
23
25
  @timers[key][:start] = Time.now
24
26
  @timers[key][:stop] = nil
25
27
 
@@ -27,13 +29,13 @@ module RubySmart
27
29
  when :stop
28
30
  return false if !@timers[key][:start] || @timers[key][:stop]
29
31
  @timers[key][:stop] = Time.now
30
- @timers[key][:measure] += @timers[key][:stop] - @timers[key][:start]
32
+ @timers[key][:total] += @timers[key][:stop] - @timers[key][:start]
31
33
 
32
34
  true
33
35
  when :pause
34
36
  return false if !@timers[key][:start] || @timers[key][:stop]
35
37
 
36
- @timers[key][:measure] += Time.now - @timers[key][:start]
38
+ @timers[key][:total] += Time.now - @timers[key][:start]
37
39
  @timers[key][:start] = nil
38
40
  @timers[key][:stop] = nil
39
41
 
@@ -50,7 +52,7 @@ module RubySmart
50
52
  current
51
53
  end
52
54
  when :current
53
- current = @timers[key][:measure]
55
+ current = @timers[key][:total]
54
56
  current += Time.now - @timers[key][:start] if @timers[key][:start] && @timers[key][:stop].nil?
55
57
  current
56
58
  else
@@ -33,7 +33,7 @@ module RubySmart
33
33
  plain: -> (_severity, _time, _progname, data) { _nl _declr(data.to_s) },
34
34
 
35
35
  # specialized array for memory-logging
36
- memory: -> (severity, time, _progname, data) { [severity.downcase.to_sym, time, data] },
36
+ memory: -> (severity, time, _progname, data) { [severity.downcase.to_sym, time, _declr(data)] },
37
37
 
38
38
  # specialized string as datalog with every provided data in additional brackets -> [data] [data] [data]
39
39
  datalog: -> (severity, time, _progname, data) {
@@ -202,7 +202,7 @@ module RubySmart
202
202
  # @param [String] str
203
203
  # @return [String]
204
204
  def _declr(str)
205
- if opts[:clr]
205
+ if opts[:clr] || !str.is_a?(String)
206
206
  str
207
207
  else
208
208
  str.gsub(/\e\[[\d;]+m/, '')
@@ -9,8 +9,8 @@ module RubySmart
9
9
 
10
10
  module VERSION
11
11
  MAJOR = 1
12
- MINOR = 2
13
- TINY = 2
12
+ MINOR = 4
13
+ TINY = 0
14
14
  PRE = nil
15
15
 
16
16
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -11,6 +11,7 @@ require_relative 'extensions/timer'
11
11
 
12
12
  require_relative 'devices/memory_device'
13
13
  require_relative 'devices/multi_device'
14
+ require_relative 'devices/null_device'
14
15
  require_relative 'devices/proc_device'
15
16
 
16
17
  require_relative 'formatter'
@@ -11,7 +11,8 @@ module RubySmart
11
11
  # > ================================================= [Debug] ================================================
12
12
  # > "DEBUGGED DATA" <- analyzed by awesome_print#ai method
13
13
  # > ==========================================================================================================
14
- base.scene :debug, { level: :debug, inspect: true, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, subject = 'Debug', opts = {}|
14
+ base.scene :debug, { level: :debug, inspect: true, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, *args|
15
+ subject, opts = _scene_subject_with_opts(args, 'Debug')
15
16
  self.log data, _scene_opt(:debug, { subject: subject }, opts)
16
17
  end
17
18
 
@@ -22,7 +23,8 @@ module RubySmart
22
23
  # > ================================================= [Info] =================================================
23
24
  # > DATA
24
25
  # > ==========================================================================================================
25
- base.scene :info, { level: :info, mask: { clr: :cyan }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, subject = 'Info', opts = {}|
26
+ base.scene :info, { level: :info, mask: { clr: :cyan }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, *args|
27
+ subject, opts = _scene_subject_with_opts(args, 'Info')
26
28
  self.log data, _scene_opt(:info, { subject: subject }, opts)
27
29
  end
28
30
 
@@ -33,7 +35,8 @@ module RubySmart
33
35
  # > ================================================= [Warn] =================================================
34
36
  # > DATA
35
37
  # > ==========================================================================================================
36
- base.scene :warn, { level: :warn, mask: { clr: :yellow }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, subject = 'Warn', opts = {}|
38
+ base.scene :warn, { level: :warn, mask: { clr: :yellow }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, *args|
39
+ subject, opts = _scene_subject_with_opts(args, 'Warn')
37
40
  self.log data, _scene_opt(:warn, { subject: subject }, opts)
38
41
  end
39
42
 
@@ -44,7 +47,8 @@ module RubySmart
44
47
  # > ================================================ [Error] =================================================
45
48
  # > DATA
46
49
  # > ==========================================================================================================
47
- base.scene :error, { level: :error, mask: { clr: :red }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, subject = 'Error', opts = {}|
50
+ base.scene :error, { level: :error, mask: { clr: :red }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, *args|
51
+ subject, opts = _scene_subject_with_opts(args, 'Error')
48
52
  self.log data, _scene_opt(:error, { subject: subject }, opts)
49
53
  end
50
54
 
@@ -55,10 +59,23 @@ module RubySmart
55
59
  # > ================================================ [Fatal] =================================================
56
60
  # > DATA
57
61
  # > ==========================================================================================================
58
- base.scene :fatal, { level: :fatal, mask: { clr: :bg_red }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, subject = 'Fatal', opts = {}|
62
+ base.scene :fatal, { level: :fatal, mask: { clr: :bg_red }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, *args|
63
+ subject, opts = _scene_subject_with_opts(args, 'Fatal')
59
64
  self.log data, _scene_opt(:fatal, { subject: subject }, opts)
60
65
  end
61
66
 
67
+ # unknown method (BASE)
68
+ # log level @ unknown
69
+ # prints: enclosed data
70
+ #
71
+ # > =============================================== [Unknown] ================================================
72
+ # > DATA
73
+ # > ==========================================================================================================
74
+ base.scene :unknown, { level: :unknown, mask: { clr: :gray }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, *args|
75
+ subject, opts = _scene_subject_with_opts(args, 'Unknown')
76
+ self.log data, _scene_opt(:unknown, { subject: subject }, opts)
77
+ end
78
+
62
79
  # success method
63
80
  # log level @ success (sub-level of info)
64
81
  # prints: enclosed data
@@ -66,7 +83,8 @@ module RubySmart
66
83
  # > ================================================ [Success] ================================================
67
84
  # > DATA
68
85
  # > ===========================================================================================================
69
- base.scene :success, { level: :success, mask: { clr: :green }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, subject = 'Success', opts = {}|
86
+ base.scene :success, { level: :success, mask: { clr: :green }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, *args|
87
+ subject, opts = _scene_subject_with_opts(args, 'Success')
70
88
  self.log data, _scene_opt(:success, { subject: subject }, opts)
71
89
  end
72
90
 
@@ -287,36 +305,80 @@ module RubySmart
287
305
  # log level @ debug
288
306
  # prints: a processed output with unicode box-chars (e.g. ║ )
289
307
  #
290
- # ╔ START :: job
308
+ # ╔ START job
291
309
  # ╟ doing some cool log
292
310
  # ╟ doing some extra log
293
- # ╚ END [job] (duration: 4.34223)
311
+ # ╚ END job [SUCCESS] (duration: 4.34223)
294
312
  base.scene :processed, { level: :debug } do |name, opts = {}, &block|
295
- # resolve the current process-level
313
+ # increase level
296
314
  lvl = processed_lvl(:up)
297
315
 
298
- # start the timer, if it should - directly sets a timer key to be reused in the +:clear+ method
299
- if (timer_key = (opts[:timer] ? "processed_#{lvl}" : nil))
300
- self.timer(:start, timer_key) if timer_key
316
+ # resolve a new time-key.
317
+ # The key depends on the current level - this should be possible, since processes on the same level should not be possible
318
+ timer_key = if opts[:timer]
319
+ "processed_#{lvl}"
320
+ else
321
+ nil
322
+ end
323
+
324
+ begin
325
+ # starts new time (if key was created)
326
+ self.timer(:start, timer_key)
327
+
328
+ # send START name as +data+ - the full log line is created through the +_pcd+ method.
329
+ self.log(name, _scene_opt(:processed, opts, { pcd: :start }))
330
+
331
+ # run the provided block and resolve result
332
+ result_str = case block.call
333
+ when true
334
+ '[SUCCESS]'.bg_green + ' '
335
+ when false
336
+ '[FAIL]'.bg_red + ' '
337
+ else
338
+ ''
339
+ end
340
+ rescue => e
341
+ self.fatal("#{e.message} @ #{e.backtrace_locations&.first}") unless opts[:silent]
342
+ # reraise exception
343
+ raise
344
+ ensure
345
+ result_str ||= ''
346
+
347
+ # send END name with result & possible time as +data+ - the full log line is created through the +_pcd+ method.
348
+ self.log("#{name} #{result_str}#{(timer_key ? "(#{self.timer(:clear, timer_key, humanized: true)})" : '')}", _scene_opt(:processed, opts, { pcd: :end }))
349
+
350
+ # reduce level
351
+ processed_lvl(:down)
301
352
  end
302
353
 
303
- self.log("START :: #{name}", _scene_opt(:processed, opts, { pcd: :start }))
304
-
305
- end_str = case block.call
306
- when true
307
- 'SUCCESS'
308
- when false
309
- 'FAILED'
310
- else
311
- name
312
- end
313
-
314
- self.log("END [#{end_str}] #{(timer_key ? "(duration: #{self.timer(:clear, timer_key, humanized: true)})" : '')}", _scene_opt(:processed, opts, { pcd: :end }))
315
-
316
- processed_lvl(:down)
317
-
318
354
  true
319
355
  end
356
+
357
+ # model method
358
+ # log level @ error/success/info
359
+ # prints: ActiveRecord::Base related data, depending on the models "save" state (also shows possible errors)
360
+ base.scene :model do |model, opts = {}|
361
+ # build model-logging string
362
+ mdl_string = "#{model.id.present? ? "##{model.id} - " : ''}#{model.to_s[0..49]}"
363
+
364
+ # resolve model's status
365
+ status = ((model.persisted? && model.errors.empty?) ? (model.previous_changes.blank? ? :skipped : :success) : :error)
366
+
367
+ # switch between status
368
+ case status
369
+ when :success
370
+ # show verbose logging for updated records
371
+ if opts[:verbose] != false && !model.previously_new_record?
372
+ log(:success, "#{mdl_string} (#{model.previous_changes.inspect})", tag: "#{model.class.name.upcase}|UPDATED")
373
+ else
374
+ log(:success, mdl_string, tag: "#{model.class.name.upcase}|#{(model.previously_new_record? ? 'CREATED' : 'UPDATED')}")
375
+ end
376
+ when :error
377
+ log(:error, "#{mdl_string} (#{model.errors.full_messages.join(', ').presence || '-'})", tag: "#{model.class.name.upcase}|ERROR")
378
+ else
379
+ log(:info, mdl_string, tag: "#{model.class.name.upcase}|#{status}")
380
+ end
381
+ end
320
382
  end
321
383
  end
322
384
  end
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['Tobias Gonsior']
9
9
  spec.email = ['info@ruby-smart.org']
10
10
 
11
- spec.summary = "A simple, multifunctional logging library for Ruby."
11
+ spec.summary = "A simple, multifunctional logging library for Ruby (and Rails)."
12
12
  spec.description = <<~DESC
13
13
  RubySmart::SimpleLogger is a fast, customizable logging library with multi-device support,
14
14
  special (PRE-defined) scenes for better logging visibility.
@@ -33,11 +33,13 @@ Gem::Specification.new do |spec|
33
33
 
34
34
  spec.require_paths = ['lib']
35
35
 
36
- spec.add_dependency 'ruby_smart-support', '~> 1.2'
36
+ spec.add_dependency 'ruby_smart-support', '~> 1.5'
37
37
 
38
38
  spec.add_development_dependency 'awesome_print', '~> 1.9'
39
39
  spec.add_development_dependency 'coveralls_reborn', '~> 0.25'
40
40
  spec.add_development_dependency 'rake', '~> 13.0'
41
41
  spec.add_development_dependency 'rspec', '~> 3.0'
42
42
  spec.add_development_dependency 'yard', '~> 0.9'
43
+ spec.add_development_dependency 'yard-activesupport-concern', '~> 0.0.1'
44
+ spec.add_development_dependency 'yard-relative_markdown_links', '>= 0.4'
43
45
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_smart-simple_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Gonsior
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-15 00:00:00.000000000 Z
11
+ date: 2024-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby_smart-support
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.2'
19
+ version: '1.5'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.2'
26
+ version: '1.5'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: awesome_print
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,34 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0.9'
97
+ - !ruby/object:Gem::Dependency
98
+ name: yard-activesupport-concern
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.0.1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.0.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: yard-relative_markdown_links
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0.4'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0.4'
97
125
  description: "RubySmart::SimpleLogger is a fast, customizable logging library with
98
126
  multi-device support, \nspecial (PRE-defined) scenes for better logging visibility.\n"
99
127
  email:
@@ -107,19 +135,20 @@ files:
107
135
  - ".rspec"
108
136
  - ".yardopts"
109
137
  - Gemfile
138
+ - LICENSE.txt
110
139
  - README.md
111
140
  - Rakefile
112
141
  - bin/console
113
142
  - bin/setup
114
143
  - docs/CHANGELOG.md
115
144
  - docs/CODE_OF_CONDUCT.md
116
- - docs/LICENSE.txt
117
145
  - lib/ruby_smart-debugger.rb
118
146
  - lib/ruby_smart-simple_logger.rb
119
147
  - lib/ruby_smart/simple_logger.rb
120
148
  - lib/ruby_smart/simple_logger/core_ext/ruby/string.rb
121
149
  - lib/ruby_smart/simple_logger/devices/memory_device.rb
122
150
  - lib/ruby_smart/simple_logger/devices/multi_device.rb
151
+ - lib/ruby_smart/simple_logger/devices/null_device.rb
123
152
  - lib/ruby_smart/simple_logger/devices/proc_device.rb
124
153
  - lib/ruby_smart/simple_logger/extensions/helper.rb
125
154
  - lib/ruby_smart/simple_logger/extensions/logs.rb
@@ -146,7 +175,7 @@ metadata:
146
175
  documentation_uri: https://rubydoc.info/gems/ruby_smart-simple_logger
147
176
  changelog_uri: https://github.com/ruby-smart/simple_logger/blob/main/docs/CHANGELOG.md
148
177
  allowed_push_host: https://rubygems.org
149
- post_install_message:
178
+ post_install_message:
150
179
  rdoc_options: []
151
180
  require_paths:
152
181
  - lib
@@ -161,8 +190,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
190
  - !ruby/object:Gem::Version
162
191
  version: '0'
163
192
  requirements: []
164
- rubygems_version: 3.3.26
165
- signing_key:
193
+ rubygems_version: 3.5.14
194
+ signing_key:
166
195
  specification_version: 4
167
- summary: A simple, multifunctional logging library for Ruby.
196
+ summary: A simple, multifunctional logging library for Ruby (and Rails).
168
197
  test_files: []
File without changes