ruby_smart-simple_logger 1.0.0 → 1.1.1

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: 8b775a10b017444f9047871d41db7c386bb6510b2321c4cf71444eb6a33f8e22
4
- data.tar.gz: c4f786468dcf26311e72f4860c6859942cea284370ba733c5e80b5a4c5a47dfa
3
+ metadata.gz: c9d250fc038e12f5d76ede43d6714efb039be7b6093bd4ea8abca6dfc937d8cc
4
+ data.tar.gz: 52d4bc7495fea29db91b336161b7af454d55b9f22e76f1e83291264844686df7
5
5
  SHA512:
6
- metadata.gz: 460b10c4d0f27a6ab678bd2ad589b2f9986348a596e88b1f5c580bd08fd9c310af75b710758693902bbe76a7e838a6f9231fb37824e627677ca44ca65d52bc27
7
- data.tar.gz: 1c7ea37910757a6748a230a4579a5b848e78ffb03dd40c01f55c9cc035e91853a30e9230735e28627aa67bf549028320f35bb6ff9b0f1b579923699b47411742
6
+ metadata.gz: cf60c99604f5da1abd4bc4ffa5c536c233728c242c7c198849fd1838cacf856a0abaaef39f6cb1aa46fc9adbd85be329637f01e0844c39e43bdac660db311a20
7
+ data.tar.gz: 7c618af918fd6a19228f152fd456a8a4f2d99bbeceae1aec4d2aa6706f11f2138ba575390d68076f2d07e29fe09fbcdce75c64baed06a887becb752662f391bd
data/.gitignore CHANGED
@@ -6,6 +6,7 @@ Gemfile.lock
6
6
  # testing
7
7
  .rspec_status
8
8
  /spec/reports/
9
+ /log
9
10
 
10
11
  # documentation & coverage
11
12
  /.yardoc
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Documentation](https://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://rubydoc.info/gems/ruby_smart-simple_logger)
5
5
 
6
6
  [![Gem Version](https://badge.fury.io/rb/ruby_smart-simple_logger.svg?kill_cache=1)](https://badge.fury.io/rb/ruby_smart-simple_logger)
7
- [![License](https://img.shields.io/github/license/ruby-smart/simple_logger)](docs/LICENSE.txt)
7
+ [![License](https://img.shields.io/badge/license-MIT-green)](docs/LICENSE.txt)
8
8
 
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)
@@ -147,7 +147,7 @@ MyCustomLogger.info "Very nice here"
147
147
  # => creates a logfile @ log/my_app/tasks/special_task.log
148
148
  ```
149
149
 
150
- This is already done for the `SimpleLogger` module - so you can directly access the methods:
150
+ This is already done for the `SimpleLogger` _(or `Debugger`)_ module - so you can directly access the methods:
151
151
  ```ruby
152
152
  require 'simple_logger'
153
153
 
@@ -171,6 +171,14 @@ other_logger2 = SimpleLogger.new :rails
171
171
  other_logger2.info "directly logs to the rails logger"
172
172
  ```
173
173
 
174
+ Alternatives with 'Debugger':
175
+ ```ruby
176
+ require 'debugger'
177
+
178
+ Debugger.debug "some debug"
179
+ Debugger.error "that failed ..."
180
+ ```
181
+
174
182
  -----
175
183
 
176
184
  ## Builtins
@@ -294,7 +302,7 @@ noformat_logger.debug "some debug without color and mask - uses the default form
294
302
 
295
303
  ### Module Builtin
296
304
 
297
- Providing a ```Module``` will also create and write to a new logfile.
305
+ Providing a ```module``` will also create and write to a new logfile.
298
306
  The path depends on the provided module name.
299
307
 
300
308
  **Example:**
@@ -335,7 +343,9 @@ logger.debug "debug message"
335
343
  ### passthrough Format
336
344
 
337
345
  The **passthrough** format is mostly used to just 'passthrough' all args to the device _(proc, memory, file, etc.)_ without formatting anything.
338
- This will just provide an array of args.
346
+ This will simply provide an array of args.
347
+
348
+ _Using this format will prevent **newlines** and does not recognize the `:nl` / `:clr` option._
339
349
 
340
350
  ```ruby
341
351
  logger = ::SimpleLogger.new(:stdout, format: :passthrough, payload: false)
@@ -349,6 +359,8 @@ logger.debug "debug message"
349
359
  The **plain** format is only used to forward the provided **data**, without severity, time, etc.
350
360
  This is the default behaviour of the SimpleLogger - which is used to build `scene`, masks, ...
351
361
 
362
+ _Using this format will prevent **newlines** and does not recognize the `:nl` / `:clr` option._
363
+
352
364
  ```ruby
353
365
  logger = ::SimpleLogger.new(:stdout, format: :plain, payload: false)
354
366
 
@@ -368,6 +380,8 @@ payload_logger.debug "debug message"
368
380
 
369
381
  The **memory** format is only used by the memory-device to store severity, time & data as an array.
370
382
 
383
+ _Using this format will prevent **newlines** and does not recognize the `:nl` / `:clr` option._
384
+
371
385
  ```ruby
372
386
  logger = ::SimpleLogger.new(:stdout, format: :memory, payload: false)
373
387
 
@@ -419,7 +433,7 @@ logger = ::SimpleLogger.new(payload: false)
419
433
  logger = ::SimpleLogger.new(:stdout, payload: false)
420
434
  ```
421
435
 
422
- ### format _(for default formatter ONLY)_
436
+ ### format
423
437
 
424
438
  Provide a other format.
425
439
  Possible values: ```:default, :passthrough, :plain, :memory, :datalog```
@@ -428,7 +442,7 @@ logger = ::SimpleLogger.new(format: :default)
428
442
  logger = ::SimpleLogger.new(:memory, format: :passthrough)
429
443
  ```
430
444
 
431
- ### nl _(for default formatter ONLY)_
445
+ ### nl
432
446
 
433
447
  Enable / disable NewLine for formatter.
434
448
  ```ruby
@@ -445,7 +459,7 @@ Provide a callback for the ```:proc``` builtin.
445
459
  logger = ::SimpleLogger.new(:proc, proc: lambda{|data| ... })
446
460
  ```
447
461
 
448
- ### stdout _(:memory-builtin ONLY)_
462
+ ### stdout _(:memory & Module-builtin ONLY)_
449
463
 
450
464
  Enable STDOUT as MultiDevice for the memory builtin.
451
465
  ```ruby
@@ -454,8 +468,8 @@ logger = ::SimpleLogger.new(:memory, stdout: true)
454
468
  # same as above
455
469
  logger = ::SimpleLogger.new(
456
470
  ::SimpleLogger::Devices::MultiDevice.new.
457
- register(::SimpleLogger::Devices::MemoryDevice.new, ::SimpleLogger::Formatter.new(format: :memory, nl: false)).
458
- register(STDOUT, ::SimpleLogger::Formatter.new(format: :default, nl: true, clr: (opts[:clr] != nil)))
471
+ register(::SimpleLogger::Devices::MemoryDevice.new, ::SimpleLogger::Formatter.new(format: :memory)).
472
+ register(STDOUT, ::SimpleLogger::Formatter.new(format: :default, nl: true, clr: opts[:clr]))
459
473
  )
460
474
  ```
461
475
 
@@ -491,24 +505,6 @@ Provide a custom formatter instance.
491
505
  logger = ::SimpleLogger.new(formatter: My::Custom::Formatter.new)
492
506
  ```
493
507
 
494
- ### clr
495
-
496
- Disable color for payload and formatter.
497
-
498
- ```ruby
499
- logger = ::SimpleLogger.new(clr: false)
500
- ```
501
-
502
- ### payload
503
-
504
- Disable payload _(mask & scenes)_ for logger
505
-
506
- ```ruby
507
- logger = ::SimpleLogger.new(payload: false)
508
- logger.debug "some debug without payload"
509
- # some debug without payload
510
- ```
511
-
512
508
  ### inspect
513
509
 
514
510
  Disable inspect for logger
@@ -711,6 +707,51 @@ The following PRE-defined scenes are available. _(You can define your own scenes
711
707
  # 50 chars -> __________________________________________________
712
708
  ```
713
709
 
710
+ ### processed(name, opts)
711
+ ```ruby
712
+ require 'simple_logger'
713
+ l = SimpleLogger.new(:stdout, payload: false)
714
+
715
+ l.processed("Process Alpha", timer: true) do
716
+ l.info "find files"
717
+ l.info "found 34 files"
718
+
719
+ l.processed("extracting ...", timer: true) do
720
+ l.info "10% done"
721
+ l.info "20% done"
722
+ l.info "100% done"
723
+
724
+ # returns true to the processed state
725
+ true
726
+ end
727
+
728
+ l.processed("transforming ...") do
729
+ l.error "bad memory"
730
+ l.info "rolling back"
731
+ # returns false to the processed state
732
+ false
733
+ end
734
+
735
+ # returns nil to the processed state
736
+ nil
737
+ end
738
+
739
+
740
+ # ╔ START - Process Alpha
741
+ # ╟ find files
742
+ # ╟ found 34 files
743
+ # ║ ┌ START - extracting ...
744
+ # ║ ├ 10% done
745
+ # ║ ├ 20% done
746
+ # ║ ├ 100% done
747
+ # ║ └ END - SUCCESS (duration: 0.000267545)
748
+ # ║ ┌ START - transforming ...
749
+ # ║ ├ bad memory
750
+ # ║ ├ rolling back
751
+ # ║ └ END - FAILED
752
+ # ╚ END - Process Alpha (duration: 0.001040807)
753
+ ```
754
+
714
755
  ### _other useful methods_
715
756
 
716
757
  - line
data/docs/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # RubySmart::SimpleLogger - CHANGELOG
2
2
 
3
+ ## [1.1.1] - 2023-02-07
4
+ * **[fix]** 'ruby 2.6.x' kwargs for `::Logger::LogDevice` messed up with 'binmode'
5
+
6
+ ## [1.1.0] - 2023-02-07
7
+ * **[add]** `#processed` method for logger
8
+ * **[ref]** `Debugger` to enforce a 'DEBUG' severity
9
+ * **[ref]** `RubySmart::SimpleLogger::Formatter` with simplified formats
10
+ * **[ref]** 'default' format to only
11
+ * **[ref]** builtin for 'modules' to directly work with 'stdout' option
12
+ * **[ref]** handling of logger-newlines 'nl'-option
13
+ * **[fix]** 'inspector' detection
14
+ * **[fix]** `RubySmart::SimpleLogger::KlassLogger.new` not 'dup' klass_logger_opts (now prevents reference manipulation)
15
+
3
16
  ## [1.0.0] - 2023-01-29
4
17
  * **[add]** full documentation
5
18
  * **[add]** add colors, if gem `awesome_print` ist missing
data/docs/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2022 Ruby Smart
3
+ Copyright (c) 2023 Ruby Smart
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/lib/debugger.rb CHANGED
@@ -12,6 +12,9 @@ GemInfo.safe_require 'awesome_print'
12
12
  class Debugger
13
13
  extend ::RubySmart::SimpleLogger::KlassLogger
14
14
 
15
+ # force debugger to 'DEBUG' severity
16
+ self.klass_logger_opts = {level: ::RubySmart::SimpleLogger::Logger::DEBUG}
17
+
15
18
  # overwrite existing "debug" method (if Debase was loaded)
16
19
  def self.debug(*args)
17
20
  return false if args.none?
@@ -8,6 +8,10 @@ module RubySmart
8
8
  attr_reader :devices
9
9
  attr_reader :status
10
10
 
11
+ def self.register(*args)
12
+ new.register(*args)
13
+ end
14
+
11
15
  def initialize
12
16
  @devices = []
13
17
  @status = true
@@ -13,23 +13,22 @@ module RubySmart
13
13
 
14
14
  # prepare builtin defaults
15
15
  # @param [Hash] opts
16
- def _opts_builtin(opts)
17
- builtin = opts.delete(:builtin)
16
+ # @param [Object] builtin
17
+ def _opts_builtin(opts, builtin = nil)
18
+ builtin ||= opts.delete(:builtin)
18
19
 
19
20
  case builtin
20
21
  when nil
21
22
  # device is nil - resolve optimal device
22
- opts[:device] ||= if ::ThreadInfo.stdout?
23
- # colorize output
24
- opts[:clr] = true if opts[:clr].nil?
25
-
26
- STDOUT
27
- elsif ::ThreadInfo.rails? && ::Rails.logger
28
- ::RubySmart::SimpleLogger::Devices::MultiDevice.new.register(::Rails.logger.instance_variable_get(:@logdev).dev)
29
- else
30
- ::RubySmart::SimpleLogger::Devices::MemoryDevice.new
31
- end
23
+ if ::ThreadInfo.stdout?
24
+ _opts_builtin(opts, :stdout)
25
+ elsif ::ThreadInfo.rails? && ::Rails.logger
26
+ _opts_builtin(opts, :rails)
27
+ else
28
+ _opts_builtin(opts, :memory)
29
+ end
32
30
  when :stdout
31
+ # set device ONLY if unset in opts
33
32
  opts[:device] ||= STDOUT
34
33
  # colorize output
35
34
  opts[:clr] = true if opts[:clr].nil?
@@ -38,31 +37,67 @@ module RubySmart
38
37
  # colorize output
39
38
  opts[:clr] = true if opts[:clr].nil?
40
39
  when :rails
41
- opts[:device] ||= ::RubySmart::SimpleLogger::Devices::MultiDevice.new.register(::Rails.logger.instance_variable_get(:@logdev).dev)
40
+ # set device ONLY if unset in opts
41
+ opts[:device] ||= ::RubySmart::SimpleLogger::Devices::MultiDevice.register(::Rails.logger.instance_variable_get(:@logdev).dev)
42
42
  when :proc
43
43
  # auto sets related opts for proc device
44
44
  opts[:payload] = false
45
+ opts[:nl] = false
45
46
  opts[:format] ||= :passthrough
46
47
 
47
- # force set device
48
+ # set device ONLY if unset in opts
48
49
  opts[:device] ||= ::RubySmart::SimpleLogger::Devices::ProcDevice.new(opts[:proc])
49
50
  when :memory
50
51
  # auto sets related opts for memory device
51
52
  opts[:payload] = false
52
53
 
53
- # set device
54
+ # set device ONLY if unset in opts
54
55
  opts[:device] ||= if opts[:stdout]
55
- # IMPORTANT: There will be a 'default' formatter created, which will passthrough all data to the device
56
- opts[:format] ||= :passthrough
56
+ # store original format
57
+ stdout_format = opts[:format] || :plain
58
+
59
+ # force 'passthrough', as format, since this is required for multi-devices
60
+ opts[:format] = :passthrough
57
61
 
58
62
  # special case handling to additionally stdout logs
59
- ::RubySmart::SimpleLogger::Devices::MultiDevice.new.
60
- register(::RubySmart::SimpleLogger::Devices::MemoryDevice.new, ::RubySmart::SimpleLogger::Formatter.new(format: :memory, nl: false)).
61
- register(STDOUT, ::RubySmart::SimpleLogger::Formatter.new(format: :default, nl: true, clr: (opts[:clr] != nil)))
63
+ ::RubySmart::SimpleLogger::Devices::MultiDevice.new
64
+ .register(::RubySmart::SimpleLogger::Devices::MemoryDevice.new, ::RubySmart::SimpleLogger::Formatter.new(format: :memory))
65
+ .register(STDOUT, ::RubySmart::SimpleLogger::Formatter.new(format: stdout_format, nl: _nl(opts), clr: opts[:clr]))
62
66
  else
63
67
  opts[:format] ||= :memory
64
68
  ::RubySmart::SimpleLogger::Devices::MemoryDevice.new
65
69
  end
70
+ when Module
71
+ # set device ONLY if unset in opts
72
+ opts[:device] ||= if opts[:stdout]
73
+ # store original format
74
+ device_format = opts[:format] || :plain
75
+
76
+ # force 'passthrough', as format, since this is required for multi-devices
77
+ opts[:format] = :passthrough
78
+
79
+ # colorize output
80
+ opts[:clr] = true if opts[:clr].nil?
81
+
82
+ # special case handling to additionally stdout logs
83
+ ::RubySmart::SimpleLogger::Devices::MultiDevice.register(
84
+ if GemInfo.match?(RUBY_VERSION, '< 2.7')
85
+ ::Logger::LogDevice.new(_logdev(builtin),
86
+ shift_age: opts[:shift_age] || 0,
87
+ shift_size: opts[:shift_size] || 1048576,
88
+ shift_period_suffix: opts[:shift_period_suffix])
89
+ else
90
+ ::Logger::LogDevice.new(_logdev(builtin),
91
+ shift_age: opts[:shift_age] || 0,
92
+ shift_size: opts[:shift_size] || 1048576,
93
+ shift_period_suffix: opts[:shift_period_suffix],
94
+ binmode: opts[:binmode])
95
+ end,
96
+ ::RubySmart::SimpleLogger::Formatter.new(format: device_format, nl: _nl(opts), clr: false))
97
+ .register(STDOUT, ::RubySmart::SimpleLogger::Formatter.new(format: device_format, nl: _nl(opts), clr: opts[:clr]))
98
+ else
99
+ builtin
100
+ end
66
101
  else
67
102
  # forward provided device ONLY if unset in opts
68
103
  opts[:device] ||= builtin
@@ -141,25 +176,36 @@ module RubySmart
141
176
  # clean & rewrite level (possible symbols) to real level
142
177
  opts[:level] = _level(opts[:level] || :debug)
143
178
 
179
+ # clean & rewrite nl
180
+ opts[:nl] = _nl(opts)
181
+
182
+ # rewrite format
183
+ opts[:format] ||= :plain
184
+
144
185
  # provide custom formatter and forward special opts (format, nl, clr)
145
- opts[:formatter] ||= ::RubySmart::SimpleLogger::Formatter.new({ format: :plain, nl: false, clr: false }.merge(opts.slice(:format, :nl, :clr)))
186
+ opts[:formatter] ||= ::RubySmart::SimpleLogger::Formatter.new(opts)
146
187
 
147
188
  # ignore payload and send data directly to the logdev
148
189
  @ignore_payload = true if opts[:payload].is_a?(FalseClass)
149
190
 
150
- # set the inspector to be used for data inspection
151
- @inspector = opts[:inspector]
152
-
153
- # disable inspector
154
- @inspector = :to_s if opts[:inspect] == false
155
-
156
- # # build logdev
157
- # opts[:logdev] = _logdev(opts[:device])
191
+ # set the inspector to be used for data inspection.
192
+ # 'disable' inspector, if false was provided - which simply results in +#to_s+
193
+ @inspector = (opts[:inspect] === false) ? :to_s : opts[:inspector]
158
194
 
159
195
  # simple return opts
160
196
  opts
161
197
  end
162
198
 
199
+ # returns the +nl+ (new line) flag, depending on the provided options.
200
+ # recognizes +:nl+ and +:payload+ options.
201
+ # @param [Hash] opts
202
+ # @return [Boolean]
203
+ def _nl(opts)
204
+ return opts[:nl] unless opts[:nl].nil?
205
+
206
+ opts[:payload].is_a?(FalseClass)
207
+ end
208
+
163
209
  # merge all provided hashes into one single hash
164
210
  #
165
211
  # @example
@@ -20,6 +20,12 @@ module RubySmart
20
20
  m
21
21
  end
22
22
  end
23
+
24
+ # returns a hash with total amounts per logged type (key)
25
+ # @return [Hash]
26
+ def log_stats
27
+ logs_to_h.reduce({}) { |m, (sev, logs)| m[sev] = logs.count; m }
28
+ end
23
29
  end
24
30
  end
25
31
  end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module RubySmart
6
+ module SimpleLogger
7
+ module Extensions
8
+ module Processed
9
+ def self.included(base)
10
+ base.extend ClassMethods
11
+ base.include InstanceMethods
12
+ base.class_eval do
13
+ # set default box chars
14
+ self.box_chars = {
15
+ __default__: %w(╟ ├),
16
+ __processed__: %w(║ │),
17
+ start: %w(╔ ┌),
18
+ end: %w(╚ └)
19
+ }.freeze
20
+ end
21
+ end
22
+
23
+ module ClassMethods
24
+ def box_chars
25
+ class_variable_get('@@box_chars')
26
+ end
27
+
28
+ def box_chars=(chars)
29
+ class_variable_set('@@box_chars', chars)
30
+ end
31
+ end
32
+
33
+ module InstanceMethods
34
+ # returns the current processed level.
35
+ # 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+)
37
+ # @return [Integer]
38
+ def processed_lvl(handle = nil)
39
+ @processed_lvl ||= -1
40
+
41
+ case handle
42
+ when :up
43
+ @processed_lvl += 1
44
+ when :down
45
+ @processed_lvl -= 1 if @processed_lvl >= 0
46
+ else
47
+ # nothing here ...
48
+ end
49
+
50
+ @processed_lvl
51
+ end
52
+
53
+ # returns true if the processed state is active.
54
+ # @return [Boolean]
55
+ def processed?
56
+ processed_lvl >= 0
57
+ end
58
+
59
+ private
60
+
61
+ # transforms the provided data into a 'processed' string and forces the data to be transformed to string.
62
+ # simple returns the provided data, if currently not processed.
63
+ # @param [Object] data
64
+ # @param [Hash] opts
65
+ # @return [Object,String]
66
+ def _pcd(data, opts)
67
+ # check for active pcd (processed)
68
+ return data if opts[:pcd] == false || !processed?
69
+
70
+ # resolve lvl, once
71
+ lvl = opts[:lvl] || processed_lvl
72
+
73
+ # create final string
74
+ lvl.times.map { |i| "#{_pcd_box_char(:__processed__, i)} " }.join + _pcd_box_char(opts[:pcd], lvl) + " #{data}"
75
+ end
76
+
77
+ # returns the processed box character for provided key and position.
78
+ # returns the +:__default__+, if provided key was not found.
79
+ # returns the max-pos char, if current pos was not found.
80
+ # @param [Symbol] key
81
+ # @param [Integer] pos
82
+ # @return [String]
83
+ def _pcd_box_char(key, pos = 0)
84
+ chars = self.class.box_chars[key] || self.class.box_chars[:__default__]
85
+ chars[pos] || chars[-1]
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ 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, data
56
+ add level, _pcd(data, opts)
57
57
  return true
58
58
  end
59
59
 
@@ -207,7 +207,7 @@ module RubySmart
207
207
  txt = str.dup
208
208
 
209
209
  # SPECIAL: prevent subject being parsed longer as the mask#length
210
- opts[:subject] = opts[:subject][0, (mask[:length] - 4 - mask[:char].length * 2)] if opts[:subject] && mask[:length] && opts[:subject].length > mask[:length]
210
+ opts[:subject] = opts[:subject].to_s[0, (mask[:length] - 4 - mask[:char].length * 2)] if opts[:subject] && mask[:length] && opts[:subject].to_s.length > mask[:length]
211
211
 
212
212
  str.scan(/%\{(\w+)\}/) do |mm|
213
213
  next unless mm.length > 0 && mm[0]
@@ -19,30 +19,25 @@ module RubySmart
19
19
 
20
20
  # set default formats
21
21
  self.formats = {
22
- # the ruby default's logging format (except to format the severity to 7-chars)
23
- default: {
24
- str: "%s, [%s #%d] %7s -- %s: %s",
25
- cb: lambda { |severity, time, progname, data| [severity[0], format_datetime(time), $$, severity, progname, msg2str(data)] }
22
+ # the ruby default's logging format -except the reformatted severity to 7-chars (instead of 5)
23
+ default: -> (severity, time, progname, data) {
24
+ _nl data2array(data, false).map { |str|
25
+ str == '' ? str : _clr(format('%s, [%s #%d] %7s -- %s: ', severity[0], format_datetime(time), $$, severity, progname), severity) + _declr(str)
26
+ }
26
27
  },
27
- # all provided args as array
28
- passthrough: {
29
- str: false, # no formatting
30
- cb: lambda { |*args| args }
31
- },
32
- # the plain data (msg) only, no severity, etc.
33
- plain: {
34
- str: false, # no formatting
35
- cb: lambda { |_severity, _time, _progname, data| data }
36
- },
37
- # special array data for memory-logging
38
- memory: {
39
- str: false, # no formatting
40
- cb: lambda { |severity, time, _progname, data| [severity.downcase.to_sym, time, data] }
41
- },
42
- # special datalog data with all provided data in additional brackets -> [data] [data] [data]
43
- datalog: {
44
- str: "[%7s] [%s] [#%d] [%s]",
45
- cb: lambda { |severity, time, _progname, data| [severity, format_datetime(time, true), $$, msg2str(data, true)] }
28
+
29
+ # simply 'passthrough' all args, without any formatting
30
+ passthrough: -> (*args) { args },
31
+
32
+ # just forward the formatted data, without any other args (no severity, time, progname)
33
+ plain: -> (_severity, _time, _progname, data) { _nl _declr(data.to_s) },
34
+
35
+ # specialized array for memory-logging
36
+ memory: -> (severity, time, _progname, data) { [severity.downcase.to_sym, time, data] },
37
+
38
+ # specialized string as datalog with every provided data in additional brackets -> [data] [data] [data]
39
+ datalog: -> (severity, time, _progname, data) {
40
+ _nl _declr(format('[#%d] [%s] [%s] [%s]', $$, format_datetime(time, true), severity, data2datalog(data)))
46
41
  }
47
42
  }
48
43
 
@@ -66,23 +61,16 @@ module RubySmart
66
61
  opts[:nl] = true if opts[:nl].nil?
67
62
  opts[:format] = :default if opts[:format].nil?
68
63
 
69
- @opts = opts
64
+ # only store required options
65
+ @opts = opts.slice(:nl, :format, :clr)
70
66
  end
71
67
 
72
- # standard call method - used to format provided terms
68
+ # standard call method - used to format provided params
73
69
  def call(severity, time, progname, data)
74
- if current_format_str
75
- str = current_format_str % instance_exec(severity, time, progname, data, &current_format_cb)
76
- str << "\n" if opts[:nl]
77
-
78
- # check for colorized output
79
- (opts[:clr] && SEVERITY_COLORS[severity]) ? str.send(SEVERITY_COLORS[severity]) : str
80
- else
81
- instance_exec(severity, time, progname, data, &current_format_cb)
82
- end
70
+ instance_exec(severity, time, progname, data, &current_formatter)
83
71
  end
84
72
 
85
- # returns all formats
73
+ # returns all class formats
86
74
  # @return [Hash] formats
87
75
  def formats
88
76
  self.class.formats
@@ -109,25 +97,72 @@ module RubySmart
109
97
  @opts.merge!(opts)
110
98
  end
111
99
 
112
- # clears auto-generated / cached data
100
+ # clears current formatter
113
101
  def clear!
114
- @current_format = nil
102
+ @current_formatter = nil
115
103
  end
116
104
 
117
105
  private
118
106
 
119
- def current_format
120
- @current_format ||= self.formats.key?(opts[:format]) ? self.formats[opts[:format]] : self.formats.values.first
107
+ # returns the current formatter callback
108
+ # @return [Proc]
109
+ def current_formatter
110
+ @current_formatter ||= self.formats[opts[:format]] || self.formats.values.first
111
+ end
112
+
113
+ # splits-up the provided data into a flat array.
114
+ # each will be split by new-line char +\n+.
115
+ # @param [Object] data
116
+ # @param [Boolean] allow_array
117
+ # @return [Array<String>]
118
+ def data2array(data, allow_array = true)
119
+ case data
120
+ when ::String
121
+ data.split("\n", -1)
122
+ when ::Array
123
+ # prevent to split-up arrays into multiple lines for this format:
124
+ # a array should +not+ be multi-lined
125
+ return data2array(data.inspect) unless allow_array
126
+
127
+ data.map { |item| data2array(item) }.flatten
128
+ when ::Exception
129
+ [
130
+ "exception: #{data.class}",
131
+ data2array(data.message),
132
+ data.backtrace || []
133
+ ].flatten
134
+ else
135
+ data2array(data.inspect)
136
+ end
121
137
  end
122
138
 
123
- def current_format_str
124
- current_format[:str]
139
+ # splits-up the provided data into a single string with each data item in brackets -> [data] [data] [data]
140
+ # @param [Object] data
141
+ # @return [String]
142
+ def data2datalog(data)
143
+ data2array(data).join('] [')
125
144
  end
126
145
 
127
- def current_format_cb
128
- current_format[:cb]
146
+ # formats the provided format string with args.
147
+ # @param [String] format
148
+ # @param [Array] args
149
+ # @return [String]
150
+ def format(format, *args)
151
+ format % args
129
152
  end
130
153
 
154
+ # def current_format_str
155
+ # current_format[:str]
156
+ # end
157
+ #
158
+ # def current_format_cb
159
+ # current_format[:cb]
160
+ # end
161
+ #
162
+ # def current_format_data(data)
163
+ # (current_format[:data] ? current_format[:data].(data) : data).to_s.split("\n")
164
+ # end
165
+
131
166
  def format_datetime(time, short = false)
132
167
  if short
133
168
  time.strftime("%Y-%m-%d %H:%M:%S")
@@ -136,16 +171,41 @@ module RubySmart
136
171
  end
137
172
  end
138
173
 
139
- def msg2str(msg, join = false)
140
- case msg
141
- when ::String
142
- msg
143
- when ::Array
144
- join ? msg.join('] [') : msg.inspect
145
- when ::Exception
146
- "#{ msg.message } (#{ msg.class })\n" + (msg.backtrace || []).join("\n")
174
+ # returns the formatted string with a new-line.
175
+ # depends, on the +:nl+ option.
176
+ # @param [String, Array] data
177
+ # @return [String]
178
+ def _nl(data)
179
+ # convert to string
180
+ data = data.join("\n") if data.is_a?(Array)
181
+
182
+ # check for +nl+ flag
183
+ return data unless opts[:nl]
184
+
185
+ data + "\n"
186
+ end
187
+
188
+ # returns the formatted string with a color-code
189
+ # depends, on the +:clr+ option.
190
+ # @param [String] str
191
+ # @param [String<uppercase>] severity
192
+ # @return [String]
193
+ def _clr(str, severity)
194
+ if opts[:clr] && (clr = SEVERITY_COLORS[severity])
195
+ str.send(clr)
196
+ else
197
+ _declr(str)
198
+ end
199
+ end
200
+
201
+ # de-colorizes provided string
202
+ # @param [String] str
203
+ # @return [String]
204
+ def _declr(str)
205
+ if opts[:clr]
206
+ str
147
207
  else
148
- msg.inspect
208
+ str.gsub(/\e\[[\d;]+m/, '')
149
209
  end
150
210
  end
151
211
  end
@@ -9,8 +9,8 @@ module RubySmart
9
9
 
10
10
  module VERSION
11
11
  MAJOR = 1
12
- MINOR = 0
13
- TINY = 0
12
+ MINOR = 1
13
+ TINY = 1
14
14
  PRE = nil
15
15
 
16
16
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -15,12 +15,13 @@ module RubySmart
15
15
  end
16
16
 
17
17
  def klass_logger_opts=(opts)
18
+ clear!
18
19
  class_variable_set('@@klass_logger_opts', opts)
19
20
  end
20
21
 
21
22
  # delegate new method to logger
22
23
  def new(*args)
23
- args = [nil, self.klass_logger_opts] if args.length == 0
24
+ args = [nil, self.klass_logger_opts.dup] if args.length == 0
24
25
  RubySmart::SimpleLogger::Logger.new(*args)
25
26
  end
26
27
 
@@ -3,6 +3,7 @@
3
3
  require_relative 'extensions/helper'
4
4
  require_relative 'extensions/logs'
5
5
  require_relative 'extensions/mask'
6
+ require_relative 'extensions/processed'
6
7
  require_relative 'extensions/scene'
7
8
  require_relative 'extensions/severity'
8
9
  require_relative 'extensions/simple_log'
@@ -25,6 +26,7 @@ module RubySmart
25
26
  include Extensions::Helper
26
27
  include Extensions::Logs
27
28
  include Extensions::Mask
29
+ include Extensions::Processed
28
30
  include Extensions::Scene
29
31
  include Extensions::Severity
30
32
  include Extensions::SimpleLog
@@ -36,7 +38,7 @@ module RubySmart
36
38
  attr_reader :logdev
37
39
 
38
40
  # defines a uniq key to parse the data
39
- PAYLOAD_DATA_KEY = :_data
41
+ PAYLOAD_DATA_KEY = :__data__
40
42
 
41
43
  # initialize new Logger
42
44
  # @param [Object, Symbol, nil] builtin
@@ -11,7 +11,7 @@ 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, subject = 'Debug', opts = {}|
15
15
  self.log data, _scene_opt(:debug, { subject: subject }, opts)
16
16
  end
17
17
 
@@ -22,7 +22,7 @@ module RubySmart
22
22
  # > ================================================= [Info] =================================================
23
23
  # > DATA
24
24
  # > ==========================================================================================================
25
- base.scene :info, { level: :info, mask: { clr: :cyan }, payload: [[:mask, ' [%{subject}] '], :_data, :mask] } do |data, subject = 'Info', opts = {}|
25
+ base.scene :info, { level: :info, mask: { clr: :cyan }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, subject = 'Info', opts = {}|
26
26
  self.log data, _scene_opt(:info, { subject: subject }, opts)
27
27
  end
28
28
 
@@ -33,7 +33,7 @@ module RubySmart
33
33
  # > ================================================= [Warn] =================================================
34
34
  # > DATA
35
35
  # > ==========================================================================================================
36
- base.scene :warn, { level: :warn, mask: { clr: :yellow }, payload: [[:mask, ' [%{subject}] '], :_data, :mask] } do |data, subject = 'Warn', opts = {}|
36
+ base.scene :warn, { level: :warn, mask: { clr: :yellow }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, subject = 'Warn', opts = {}|
37
37
  self.log data, _scene_opt(:warn, { subject: subject }, opts)
38
38
  end
39
39
 
@@ -44,7 +44,7 @@ module RubySmart
44
44
  # > ================================================ [Error] =================================================
45
45
  # > DATA
46
46
  # > ==========================================================================================================
47
- base.scene :error, { level: :error, mask: { clr: :red }, payload: [[:mask, ' [%{subject}] '], :_data, :mask] } do |data, subject = 'Error', opts = {}|
47
+ base.scene :error, { level: :error, mask: { clr: :red }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, subject = 'Error', opts = {}|
48
48
  self.log data, _scene_opt(:error, { subject: subject }, opts)
49
49
  end
50
50
 
@@ -55,7 +55,7 @@ module RubySmart
55
55
  # > ================================================ [Fatal] =================================================
56
56
  # > DATA
57
57
  # > ==========================================================================================================
58
- base.scene :fatal, { level: :fatal, mask: { clr: :bg_red }, payload: [[:mask, ' [%{subject}] '], :_data, :mask] } do |data, subject = 'Fatal', opts = {}|
58
+ base.scene :fatal, { level: :fatal, mask: { clr: :bg_red }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, subject = 'Fatal', opts = {}|
59
59
  self.log data, _scene_opt(:fatal, { subject: subject }, opts)
60
60
  end
61
61
 
@@ -66,7 +66,7 @@ module RubySmart
66
66
  # > ================================================ [Success] ================================================
67
67
  # > DATA
68
68
  # > ===========================================================================================================
69
- base.scene :success, { level: :success, mask: { clr: :green }, payload: [[:mask, ' [%{subject}] '], :_data, :mask] } do |data, subject = 'Success', opts = {}|
69
+ base.scene :success, { level: :success, mask: { clr: :green }, payload: [[:mask, ' [%{subject}] '], :__data__, :mask] } do |data, subject = 'Success', opts = {}|
70
70
  self.log data, _scene_opt(:success, { subject: subject }, opts)
71
71
  end
72
72
 
@@ -273,15 +273,50 @@ module RubySmart
273
273
  perc = 0 if perc < 0
274
274
  perc = 100 if perc > 100
275
275
 
276
- pmask_left_length = (pmask_length * perc / 100)
276
+ pmask_left_length = (pmask_length * perc / 100)
277
277
  # reduce 1 char for the arrow '>'
278
- pmask_left_length -= 1 if pmask_left_length > 0
278
+ pmask_left_length -= 1 if pmask_left_length > 0
279
279
  pmask_right_length = pmask_length - pmask_left_length - 1
280
280
 
281
281
  progress_string = _clr(('=' * pmask_left_length) + '>', :green) + _clr('-' * pmask_right_length, :red)
282
- perc_string = perc.to_s.rjust(3,' ')
282
+ perc_string = perc.to_s.rjust(3, ' ')
283
283
  self.log nil, _scene_opt(:progress, { name: _clr(_lgth(name, 48), :cyan), perc: perc_string, progress: progress_string }, opts)
284
284
  end
285
+
286
+ # processed method
287
+ # log level @ info
288
+ # prints: a processed output with unicode box-chars (e.g. ║ )
289
+ #
290
+ # ╔ START job
291
+ # ╟ doing some cool log
292
+ # ╟ doing some extra log
293
+ # ╚ END job (duration: 4.34223)
294
+ base.scene :processed, { level: :info } do |name, opts = {}, &block|
295
+ # resolve the current process-level
296
+ lvl = processed_lvl(:up)
297
+
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
301
+ end
302
+
303
+ self.log("START - #{name}", _scene_opt(:processed, { pcd: :start }))
304
+
305
+ end_str = case block.call
306
+ when true
307
+ "END - SUCCESS"
308
+ when false
309
+ "END - FAILED"
310
+ else
311
+ "END - #{name}"
312
+ end
313
+
314
+ self.log("#{end_str} #{(timer_key ? "(duration: #{self.timer(:clear, timer_key, :humanized => true)})" : '')}", _scene_opt(:processed, { pcd: :end }))
315
+
316
+ processed_lvl(:down)
317
+
318
+ true
319
+ end
285
320
  end
286
321
  end
287
322
  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.0.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Gonsior
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-29 00:00:00.000000000 Z
11
+ date: 2023-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby_smart-support
@@ -124,6 +124,7 @@ files:
124
124
  - lib/ruby_smart/simple_logger/extensions/helper.rb
125
125
  - lib/ruby_smart/simple_logger/extensions/logs.rb
126
126
  - lib/ruby_smart/simple_logger/extensions/mask.rb
127
+ - lib/ruby_smart/simple_logger/extensions/processed.rb
127
128
  - lib/ruby_smart/simple_logger/extensions/scene.rb
128
129
  - lib/ruby_smart/simple_logger/extensions/severity.rb
129
130
  - lib/ruby_smart/simple_logger/extensions/simple_log.rb
@@ -160,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
161
  - !ruby/object:Gem::Version
161
162
  version: '0'
162
163
  requirements: []
163
- rubygems_version: 3.3.7
164
+ rubygems_version: 3.3.26
164
165
  signing_key:
165
166
  specification_version: 4
166
167
  summary: A simple, multifunctional logging library for Ruby.