debug_logging 4.0.1 → 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +237 -69
  4. data/CITATION.cff +20 -0
  5. data/CODE_OF_CONDUCT.md +79 -29
  6. data/CONTRIBUTING.md +242 -33
  7. data/FUNDING.md +74 -0
  8. data/LICENSE.md +12 -0
  9. data/README.md +491 -198
  10. data/RUBOCOP.md +71 -0
  11. data/SECURITY.md +15 -10
  12. data/certs/pboling.pem +27 -0
  13. data/lib/debug_logging/argument_printer.rb +34 -13
  14. data/lib/debug_logging/class_logger.rb +26 -56
  15. data/lib/debug_logging/class_notifier.rb +22 -38
  16. data/lib/debug_logging/colorized_string.rb +130 -0
  17. data/lib/debug_logging/configuration.rb +3 -2
  18. data/lib/debug_logging/finalize.rb +10 -8
  19. data/lib/debug_logging/hooks.rb +7 -5
  20. data/lib/debug_logging/instance_logger.rb +8 -2
  21. data/lib/debug_logging/instance_logger_modulizer.rb +19 -49
  22. data/lib/debug_logging/instance_notifier.rb +6 -0
  23. data/lib/debug_logging/instance_notifier_modulizer.rb +15 -31
  24. data/lib/debug_logging/lamb_dart/base.rb +46 -0
  25. data/lib/debug_logging/lamb_dart/log.rb +47 -0
  26. data/lib/debug_logging/lamb_dart/note.rb +30 -0
  27. data/lib/debug_logging/lamb_dart.rb +9 -0
  28. data/lib/debug_logging/lamb_dartable.rb +41 -0
  29. data/lib/debug_logging/lamb_darts/benchmarked.rb +19 -0
  30. data/lib/debug_logging/lamb_darts/enter_log.rb +16 -0
  31. data/lib/debug_logging/lamb_darts/error_handle.rb +28 -0
  32. data/lib/debug_logging/lamb_darts/exit_log.rb +15 -0
  33. data/lib/debug_logging/lamb_darts/notify.rb +17 -0
  34. data/lib/debug_logging/log_subscriber.rb +33 -26
  35. data/lib/debug_logging/util.rb +23 -19
  36. data/lib/debug_logging/version.rb +4 -1
  37. data/lib/debug_logging.rb +14 -9
  38. data/lib/simple_debug_logging.rb +18 -16
  39. data/sig/debug_logging/version.rbs +6 -0
  40. data.tar.gz.sig +0 -0
  41. metadata +129 -141
  42. metadata.gz.sig +0 -0
  43. data/LICENSE.txt +0 -21
data/RUBOCOP.md ADDED
@@ -0,0 +1,71 @@
1
+ # RuboCop Usage Guide
2
+
3
+ ## Overview
4
+
5
+ A tale of two RuboCop plugin gems.
6
+
7
+ ### RuboCop Gradual
8
+
9
+ This project uses `rubocop_gradual` instead of vanilla RuboCop for code style checking. The `rubocop_gradual` tool allows for gradual adoption of RuboCop rules by tracking violations in a lock file.
10
+
11
+ ### RuboCop LTS
12
+
13
+ This project uses `rubocop-lts` to ensure, on a best-effort basis, compatibility with Ruby >= 1.9.2.
14
+ RuboCop rules are meticulously configured by the `rubocop-lts` family of gems to ensure that a project is compatible with a specific version of Ruby. See: https://rubocop-lts.gitlab.io for more.
15
+
16
+ ## Checking RuboCop Violations
17
+
18
+ To check for RuboCop violations in this project, always use:
19
+
20
+ ```bash
21
+ bundle exec rake rubocop_gradual:check
22
+ ```
23
+
24
+ **Do not use** the standard RuboCop commands like:
25
+ - `bundle exec rubocop`
26
+ - `rubocop`
27
+
28
+ ## Understanding the Lock File
29
+
30
+ The `.rubocop_gradual.lock` file tracks all current RuboCop violations in the project. This allows the team to:
31
+
32
+ 1. Prevent new violations while gradually fixing existing ones
33
+ 2. Track progress on code style improvements
34
+ 3. Ensure CI builds don't fail due to pre-existing violations
35
+
36
+ ## Common Commands
37
+
38
+ - **Check violations**
39
+ - `bundle exec rake rubocop_gradual`
40
+ - `bundle exec rake rubocop_gradual:check`
41
+ - **(Safe) Autocorrect violations, and update lockfile if no new violations**
42
+ - `bundle exec rake rubocop_gradual:autocorrect`
43
+ - **Force update the lock file (w/o autocorrect) to match violations present in code**
44
+ - `bundle exec rake rubocop_gradual:force_update`
45
+
46
+ ## Workflow
47
+
48
+ 1. Before submitting a PR, run `bundle exec rake rubocop_gradual:autocorrect`
49
+ a. or just the default `bundle exec rake`, as autocorrection is a pre-requisite of the default task.
50
+ 2. If there are new violations, either:
51
+ - Fix them in your code
52
+ - Run `bundle exec rake rubocop_gradual:force_update` to update the lock file (only for violations you can't fix immediately)
53
+ 3. Commit the updated `.rubocop_gradual.lock` file along with your changes
54
+
55
+ ## Never add inline RuboCop disables
56
+
57
+ Do not add inline `rubocop:disable` / `rubocop:enable` comments anywhere in the codebase (including specs, except when following the few existing `rubocop:disable` patterns for a rule already being disabled elsewhere in the code). We handle exceptions in two supported ways:
58
+
59
+ - Permanent/structural exceptions: prefer adjusting the RuboCop configuration (e.g., in `.rubocop.yml`) to exclude a rule for a path or file pattern when it makes sense project-wide.
60
+ - Temporary exceptions while improving code: record the current violations in `.rubocop_gradual.lock` via the gradual workflow:
61
+ - `bundle exec rake rubocop_gradual:autocorrect` (preferred; will autocorrect what it can and update the lock only if no new violations were introduced)
62
+ - If needed, `bundle exec rake rubocop_gradual:force_update` (as a last resort when you cannot fix the newly reported violations immediately)
63
+
64
+ In general, treat the rules as guidance to follow; fix violations rather than ignore them. For example, RSpec conventions in this project expect `described_class` to be used in specs that target a specific class under test.
65
+
66
+ ## Benefits of rubocop_gradual
67
+
68
+ - Allows incremental adoption of code style rules
69
+ - Prevents CI failures due to pre-existing violations
70
+ - Provides a clear record of code style debt
71
+ - Enables focused efforts on improving code quality over time
data/SECURITY.md CHANGED
@@ -2,15 +2,20 @@
2
2
 
3
3
  ## Supported Versions
4
4
 
5
- | Version | Supported |
6
- |---------|-----------|
7
- | 4.x | ✅ |
8
- | 3.x | ❌ |
9
- | 2.x | ❌ |
10
- | 1.x | ❌ |
5
+ | Version | Supported |
6
+ |----------|-----------|
7
+ | 1.latest | ✅ |
11
8
 
12
- ## Reporting a Vulnerability
9
+ ## Security contact information
13
10
 
14
- Peter Boling is the primary maintainer of this gem. Please find a way
15
- to [contact him directly](https://railsbling.com/contact) to report the issue. Include as much relevant information as
16
- possible.
11
+ To report a security vulnerability, please use the
12
+ [Tidelift security contact](https://tidelift.com/security).
13
+ Tidelift will coordinate the fix and disclosure.
14
+
15
+ ## Additional Support
16
+
17
+ If you are interested in support for versions older than the latest release,
18
+ please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate,
19
+ or find other sponsorship links in the [README].
20
+
21
+ [README]: README.md
data/certs/pboling.pem ADDED
@@ -0,0 +1,27 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl
3
+ ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW
4
+ A2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM
5
+ DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
6
+ LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA
7
+ uoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61
8
+ LRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5
9
+ mZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN
10
+ coEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV
11
+ FMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj
12
+ yGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1
13
+ to/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD
14
+ qbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj
15
+ fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ
16
+ HlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG
17
+ A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD
18
+ ggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9
19
+ wmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR
20
+ L8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm
21
+ GUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k
22
+ kNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq
23
+ QekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA
24
+ 0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p
25
+ DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt
26
+ L9nRqA==
27
+ -----END CERTIFICATE-----
@@ -8,7 +8,8 @@ module DebugLogging
8
8
  end
9
9
 
10
10
  def debug_invocation_id_to_s(args: nil, kwargs: nil, start_at: nil, config_proxy: nil)
11
- return "" unless (args || kwargs) && config_proxy
11
+ return "" unless config_proxy
12
+ return "" unless args || kwargs
12
13
 
13
14
  if config_proxy.debug_add_invocation_id
14
15
  time = start_at ? Util.debug_time(start_at) : Time.now
@@ -46,7 +47,7 @@ module DebugLogging
46
47
  DebugLogging::Constants::EVENT_TIME_FORMATTER.call(time)
47
48
  end
48
49
 
49
- def debug_invocation_to_s(klass: nil, separator: nil, method_to_log: nil, config_proxy: nil)
50
+ def debug_invocation_to_s(klass: nil, separator: nil, decorated_method: nil, config_proxy: nil)
50
51
  return "" unless config_proxy
51
52
 
52
53
  klass_string = if config_proxy.debug_colorized_chain_for_class
@@ -55,21 +56,22 @@ module DebugLogging
55
56
  klass.to_s
56
57
  end
57
58
  method_string = if config_proxy.debug_colorized_chain_for_method
58
- config_proxy.debug_colorized_chain_for_method.call(ColorizedString[method_to_log.to_s])
59
+ config_proxy.debug_colorized_chain_for_method.call(ColorizedString[decorated_method.to_s])
59
60
  else
60
- method_to_log.to_s
61
+ decorated_method.to_s
61
62
  end
62
63
  "#{klass_string}#{separator}#{method_string}"
63
64
  end
64
65
 
65
66
  def debug_signature_to_s(args: nil, kwargs: nil, config_proxy: nil) # rubocop:disable Metrics/CyclomaticComplexity
66
- return "" unless (args || kwargs) && config_proxy
67
+ return "" unless config_proxy
68
+ return "" unless args || kwargs
67
69
 
68
70
  printed_args = ""
69
71
 
70
72
  add_args_ellipsis = false
71
73
  args = args.dup
72
- args.push(kwargs) if kwargs
74
+ args.push(kwargs) if kwargs&.keys && !kwargs&.keys&.length&.zero?
73
75
  if config_proxy.debug_last_hash_to_s_proc && args[-1].is_a?(Hash)
74
76
  add_other_args_ellipsis = false
75
77
  if args.length > 1
@@ -86,7 +88,7 @@ module DebugLogging
86
88
  )
87
89
  printed
88
90
  else
89
- other_args.map(&:inspect).join(", ").tap do |x|
91
+ debug_args_to_s(other_args).tap do |x|
90
92
  add_other_args_ellipsis = x.length > config_proxy.debug_args_max_length
91
93
  end[0..(config_proxy.debug_args_max_length)]
92
94
  end
@@ -120,7 +122,7 @@ module DebugLogging
120
122
  )
121
123
  printed
122
124
  else
123
- other_args.map(&:inspect).join(", ").tap do |x|
125
+ debug_args_to_s(other_args).tap do |x|
124
126
  add_other_args_ellipsis = x.length > config_proxy.debug_args_max_length
125
127
  end[0..(config_proxy.debug_args_max_length)]
126
128
  end
@@ -156,11 +158,11 @@ module DebugLogging
156
158
  printed
157
159
  elsif args.length == 1 && args[0].is_a?(Hash)
158
160
  # handle double splat
159
- "**#{args.map(&:inspect).join(", ").tap do |x|
161
+ "**#{debug_args_to_s(args).tap do |x|
160
162
  add_args_ellipsis = x.length > config_proxy.debug_args_max_length
161
163
  end }"[0..(config_proxy.debug_args_max_length)]
162
164
  else
163
- args.map(&:inspect).join(", ").tap do |x|
165
+ debug_args_to_s(args).tap do |x|
164
166
  add_args_ellipsis = x.length > config_proxy.debug_args_max_length
165
167
  end[0..(config_proxy.debug_args_max_length)]
166
168
  end
@@ -187,7 +189,7 @@ module DebugLogging
187
189
 
188
190
  case config_proxy.debug_add_payload
189
191
  when true
190
- payload.inspect
192
+ debug_value_to_s(payload)
191
193
  else
192
194
  printed_payload = ""
193
195
  printed, add_payload_ellipsis = debug_safe_proc(
@@ -204,8 +206,27 @@ module DebugLogging
204
206
 
205
207
  module_function
206
208
 
207
- def debug_event_name_to_s(method_to_notify: nil)
208
- "#{method_to_notify}.log"
209
+ def debug_args_to_s(args)
210
+ args.map { |arg| debug_value_to_s(arg) }.join(", ")
211
+ end
212
+
213
+ def debug_value_to_s(value)
214
+ case value
215
+ when Hash
216
+ "{#{value.map { |key, inner_value| "#{debug_hash_key_to_s(key)}: #{debug_value_to_s(inner_value)}" }.join(", ")}}"
217
+ when Array
218
+ "[#{value.map { |inner_value| debug_value_to_s(inner_value) }.join(", ")}]"
219
+ else
220
+ value.inspect
221
+ end
222
+ end
223
+
224
+ def debug_hash_key_to_s(key)
225
+ key.is_a?(Symbol) ? key.to_s : key.inspect
226
+ end
227
+
228
+ def debug_event_name_to_s(decorated_method: nil)
229
+ "#{decorated_method}.log"
209
230
  end
210
231
  end
211
232
  end
@@ -1,72 +1,42 @@
1
1
  module DebugLogging
2
2
  module ClassLogger
3
+ class << self
4
+ def extended(base)
5
+ base.extend(LambDartable::Log)
6
+ end
7
+ end
8
+
3
9
  def logged(*methods_to_log)
4
10
  methods_to_log, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
5
11
  method_names: methods_to_log,
6
12
  payload: nil,
7
13
  config: nil,
8
14
  )
9
- Array(methods_to_log).each do |method_to_log|
10
- method_to_log, method_payload, method_config_opts = DebugLogging::Util.extract_payload_and_config(
11
- method_names: method_to_log,
15
+ Array(methods_to_log).each do |decorated_method|
16
+ decorated_method, method_payload, method_config_opts = DebugLogging::Util.extract_payload_and_config(
17
+ method_names: decorated_method,
12
18
  payload: payload,
13
19
  config: config_opts,
14
20
  )
15
- original_method = method(method_to_log)
21
+ original_method = method(decorated_method)
16
22
  (class << self; self; end).class_eval do
17
- define_method(method_to_log) do |*args, &block|
18
- config_proxy = DebugLogging::Util.config_proxy_finder(
19
- scope: self,
20
- config_opts: method_config_opts,
21
- method_name: method_to_log,
22
- proxy_ref: "kl",
23
+ define_method(decorated_method) do |*args, **kwargs, &block|
24
+ lamb_dart = LambDart::Log.new(
25
+ klass: self,
26
+ method_config_opts:,
27
+ method_payload:,
28
+ args:,
29
+ kwargs:,
30
+ decorated_method:,
23
31
  )
24
- method_return_value = nil
25
- log_prefix = nil
26
- invocation_id = nil
27
- begin
28
- config_proxy.log do
29
- paydirt = DebugLogging::Util.payload_instance_variable_hydration(scope: self, payload: method_payload)
30
- log_prefix = debug_invocation_to_s(
31
- klass: to_s,
32
- separator: "::",
33
- method_to_log: method_to_log,
34
- config_proxy: config_proxy,
35
- )
36
- invocation_id = debug_invocation_id_to_s(args: args, config_proxy: config_proxy)
37
- signature = debug_signature_to_s(args: args, config_proxy: config_proxy)
38
- paymud = debug_payload_to_s(payload: paydirt, config_proxy: config_proxy)
39
- "#{log_prefix}#{signature}#{invocation_id} debug: #{paymud}"
40
- end
41
- if config_proxy.benchmarkable_for?(:debug_class_benchmarks)
42
- tms = Benchmark.measure do
43
- method_return_value = if args.size == 1 && (harsh = args[0]) && harsh.is_a?(Hash)
44
- original_method.call(**harsh, &block)
45
- else
46
- original_method.call(*args, &block)
47
- end
48
- end
49
- config_proxy.log do
50
- "#{log_prefix} #{debug_benchmark_to_s(tms: tms)}#{invocation_id}"
51
- end
52
- else
53
- method_return_value = if args.size == 1 && (harsh = args[0]) && harsh.is_a?(Hash)
54
- original_method.call(**harsh, &block)
55
- else
56
- original_method.call(*args, &block)
57
- end
58
- if config_proxy.exit_scope_markable? && invocation_id && !invocation_id.empty?
59
- config_proxy.log do
60
- "#{log_prefix} completed#{invocation_id}"
61
- end
62
- end
63
- end
64
- method_return_value
65
- rescue StandardError => e
66
- if config_proxy.error_handler_proc
67
- config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_log, args)
68
- else
69
- raise e
32
+ real_mccoy = ->() {
33
+ original_method.call(*args, **kwargs, &block)
34
+ }
35
+ _dl_ld_enter_log(lamb_dart) do
36
+ _dl_ld_error_handle(lamb_dart) do
37
+ return _dl_ld_benchmarked(lamb_dart) { real_mccoy.call } if lamb_dart.bench?
38
+
39
+ _dl_ld_exit_log(lamb_dart) { real_mccoy.call }
70
40
  end
71
41
  end
72
42
  end
@@ -1,53 +1,37 @@
1
1
  module DebugLogging
2
2
  module ClassNotifier
3
+ class << self
4
+ def extended(base)
5
+ base.extend(LambDartable::Note)
6
+ end
7
+ end
8
+
3
9
  def notified(*methods_to_notify)
4
10
  methods_to_notify, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
5
11
  method_names: methods_to_notify,
6
12
  payload: nil,
7
13
  config: nil,
8
14
  )
9
- Array(methods_to_notify).each do |method_to_notify|
10
- method_to_notify, method_payload, method_config_opts = DebugLogging::Util.extract_payload_and_config(
11
- method_names: method_to_notify,
15
+ Array(methods_to_notify).each do |decorated_method|
16
+ decorated_method, method_payload, method_config_opts = DebugLogging::Util.extract_payload_and_config(
17
+ method_names: decorated_method,
12
18
  payload: payload,
13
19
  config: config_opts,
14
20
  )
15
- original_method = method(method_to_notify)
21
+ original_method = method(decorated_method)
16
22
  (class << self; self; end).class_eval do
17
- define_method(method_to_notify) do |*args, &block|
18
- config_proxy = DebugLogging::Util.config_proxy_finder(
19
- scope: self,
20
- config_opts: method_config_opts,
21
- method_name: method_to_notify,
22
- proxy_ref: "kn",
23
- ) do |proxy|
24
- ActiveSupport::Notifications.subscribe(
25
- DebugLogging::ArgumentPrinter.debug_event_name_to_s(method_to_notify: method_to_notify),
26
- ) do |*debug_args|
27
- proxy.log do
28
- DebugLogging::LogSubscriber.log_event(ActiveSupport::Notifications::Event.new(*debug_args))
29
- end
30
- end
31
- end
32
- paydirt = DebugLogging::Util.payload_instance_variable_hydration(scope: self, payload: method_payload)
33
- ActiveSupport::Notifications.instrument(
34
- DebugLogging::ArgumentPrinter.debug_event_name_to_s(method_to_notify: method_to_notify),
35
- {
36
- debug_args: args,
37
- config_proxy: config_proxy,
38
- **paydirt,
39
- },
40
- ) do
41
- if args.size == 1 && (harsh = args[0]) && harsh.is_a?(Hash)
42
- original_method.call(**harsh, &block)
43
- else
44
- original_method.call(*args, &block)
45
- end
46
- rescue StandardError => e
47
- if config_proxy.error_handler_proc
48
- config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_notify, args)
49
- else
50
- raise e
23
+ define_method(decorated_method) do |*args, **kwargs, &block|
24
+ lamb_dart = LambDart::Note.new(
25
+ klass: self,
26
+ method_config_opts:,
27
+ method_payload:,
28
+ args:,
29
+ kwargs:,
30
+ decorated_method:,
31
+ )
32
+ _dl_ld_notify(lamb_dart) do
33
+ _dl_ld_error_handle(lamb_dart) do
34
+ original_method.call(*args, **kwargs, &block)
51
35
  end
52
36
  end
53
37
  end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DebugLogging
4
+ class ColorizedString < String
5
+ FOREGROUND_CODES = {
6
+ black: 30,
7
+ red: 31,
8
+ green: 32,
9
+ yellow: 33,
10
+ blue: 34,
11
+ magenta: 35,
12
+ cyan: 36,
13
+ white: 37,
14
+ light_black: 90,
15
+ light_red: 91,
16
+ light_green: 92,
17
+ light_yellow: 93,
18
+ light_blue: 94,
19
+ light_magenta: 95,
20
+ light_cyan: 96,
21
+ light_white: 97,
22
+ default: 39,
23
+ }.freeze
24
+ BACKGROUND_CODES = FOREGROUND_CODES.transform_values { |code| code + 10 }.merge(default: 49).freeze
25
+ FORMAT_CODES = {
26
+ bold: 1,
27
+ italic: 3,
28
+ underline: 4,
29
+ blink: 5,
30
+ reverse_color: 7,
31
+ conceal: 8,
32
+ hide: 8,
33
+ strikethrough: 9,
34
+ double_underline: 21,
35
+ }.freeze
36
+
37
+ class << self
38
+ def [](value)
39
+ new(value.to_s)
40
+ end
41
+ end
42
+
43
+ def initialize(value, foreground: nil, background: nil, formats: [])
44
+ @raw = value.to_s
45
+ @foreground = foreground
46
+ @background = background
47
+ @formats = formats.dup
48
+ super(render)
49
+ end
50
+
51
+ def colorize(color = nil, options = {})
52
+ options = color if color.is_a?(Hash)
53
+ foreground = options.fetch(:color, nil) || options.fetch("color", nil)
54
+ foreground ||= color unless color.is_a?(Hash)
55
+ background = options.fetch(:background, nil) || options.fetch("background", nil)
56
+ formats = Array(options[:mode]) + Array(options[:modes])
57
+
58
+ self.class.new(
59
+ @raw,
60
+ foreground: foreground ? normalized_color(foreground) : @foreground,
61
+ background: background ? normalized_color(background) : @background,
62
+ formats: merge_formats(formats),
63
+ )
64
+ end
65
+
66
+ def colorized?
67
+ @foreground || @background || @formats.any?
68
+ end
69
+
70
+ def uncolorize
71
+ @raw.dup
72
+ end
73
+
74
+ FOREGROUND_CODES.each_key do |color|
75
+ next if color == :default
76
+
77
+ define_method(color) do
78
+ colorize(color)
79
+ end
80
+
81
+ define_method(:"on_#{color}") do
82
+ colorize(background: color)
83
+ end
84
+ end
85
+ alias_method :on_gray, :on_light_black
86
+ alias_method :on_grey, :on_light_black
87
+
88
+ FORMAT_CODES.each_key do |format|
89
+ define_method(format) do
90
+ self.class.new(@raw, foreground: @foreground, background: @background, formats: merge_formats([format]))
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def background_code
97
+ BACKGROUND_CODES.fetch(@background, 49)
98
+ end
99
+
100
+ def foreground_code
101
+ FOREGROUND_CODES.fetch(@foreground, 39)
102
+ end
103
+
104
+ def style_codes
105
+ format_codes = @formats.map { |format| FORMAT_CODES.fetch(format) }
106
+ format_codes = [0] if format_codes.empty?
107
+ [*format_codes, foreground_code, background_code]
108
+ end
109
+
110
+ def normalized_color(color)
111
+ color.to_s.tr(" ", "_").downcase.to_sym
112
+ end
113
+
114
+ def merge_formats(formats)
115
+ normalized_formats = formats.filter_map do |format|
116
+ normalized = format.to_sym
117
+ normalized if FORMAT_CODES.key?(normalized)
118
+ end
119
+ @formats | normalized_formats
120
+ end
121
+
122
+ def render
123
+ return @raw.dup unless colorized?
124
+
125
+ "\e[#{style_codes.join(";")}m#{@raw}\e[0m"
126
+ end
127
+ end
128
+ end
129
+
130
+ ColorizedString = DebugLogging::ColorizedString unless Object.const_defined?(:ColorizedString)
@@ -1,6 +1,7 @@
1
1
  module DebugLogging
2
2
  class Configuration
3
3
  include Constants
4
+
4
5
  # For reference, log levels as integers mapped to symbols:
5
6
  # LEVELS = { 0 => :debug, 1 => :info, 2 => :warn, 3 => :error, 4 => :fatal, 5 => :unknown }
6
7
  attr_accessor(*CONFIG_ATTRS)
@@ -38,11 +39,11 @@ module DebugLogging
38
39
  end
39
40
 
40
41
  class << self
41
- def config_pointer(type, method_to_log)
42
+ def config_pointer(type, decorated_method)
42
43
  # Methods names that do not match the following regex can't be part of an ivar name
43
44
  # /[a-zA-Z_][a-zA-Z0-9_]*/
44
45
  # Thus we have to use a different form of the method name that is compatible with ivar name conventions
45
- "@debug_logging_config_#{type}_#{Digest::MD5.hexdigest(method_to_log.to_s)}".to_sym
46
+ "@debug_logging_config_#{type}_#{Digest::MD5.hexdigest(decorated_method.to_s)}".to_sym
46
47
  end
47
48
  end
48
49
 
@@ -2,15 +2,17 @@
2
2
  # License: https://creativecommons.org/licenses/by-sa/4.0/
3
3
  module DebugLogging
4
4
  module Finalize
5
- def self.extended(obj)
6
- TracePoint.trace(:end) do |t|
7
- if obj == t.self
8
- if obj.respond_to?(:debug_finalize)
9
- obj.debug_finalize
10
- else
11
- warn("#{obj} does not define a debug_finalize")
5
+ class << self
6
+ def extended(obj)
7
+ TracePoint.trace(:end) do |t|
8
+ if obj == t.self
9
+ if obj.respond_to?(:debug_finalize)
10
+ obj.debug_finalize
11
+ else
12
+ warn("#{obj} does not define a debug_finalize")
13
+ end
14
+ t.disable
12
15
  end
13
- t.disable
14
16
  end
15
17
  end
16
18
  end
@@ -3,12 +3,14 @@ require "timeout"
3
3
 
4
4
  module DebugLogging
5
5
  module Hooks
6
- def self.included(mod)
7
- mod.extend(ClassMethods)
8
- end
6
+ class << self
7
+ def included(mod)
8
+ mod.extend(ClassMethods)
9
+ end
9
10
 
10
- def self.extend(mod)
11
- mod.extend(ClassMethods)
11
+ def extended(mod)
12
+ mod.extend(ClassMethods)
13
+ end
12
14
  end
13
15
 
14
16
  module ClassMethods
@@ -1,5 +1,11 @@
1
1
  module DebugLogging
2
2
  module InstanceLogger
3
+ class << self
4
+ def extended(base)
5
+ base.include(LambDartable::Log)
6
+ end
7
+ end
8
+
3
9
  # NOTE: These params can be passed in / hidden in a last hash of *args
4
10
  # NOTE: They can also be passed in discretely for each method, by passing *args as an array of arrays
5
11
  # TODO: Refactor to use modern Ruby 3 *args, **kwargs instead
@@ -29,9 +35,9 @@ module DebugLogging
29
35
  config: nil,
30
36
  )
31
37
  instance_method_modules =
32
- Array(methods_to_log).map do |method_to_log|
38
+ Array(methods_to_log).map do |decorated_method|
33
39
  DebugLogging::InstanceLoggerModulizer.to_mod(
34
- methods_to_log: Array(method_to_log),
40
+ methods_to_log: Array(decorated_method),
35
41
  payload: payload,
36
42
  config: config_opts,
37
43
  )