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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +237 -69
- data/CITATION.cff +20 -0
- data/CODE_OF_CONDUCT.md +79 -29
- data/CONTRIBUTING.md +242 -33
- data/FUNDING.md +74 -0
- data/LICENSE.md +12 -0
- data/README.md +491 -198
- data/RUBOCOP.md +71 -0
- data/SECURITY.md +15 -10
- data/certs/pboling.pem +27 -0
- data/lib/debug_logging/argument_printer.rb +34 -13
- data/lib/debug_logging/class_logger.rb +26 -56
- data/lib/debug_logging/class_notifier.rb +22 -38
- data/lib/debug_logging/colorized_string.rb +130 -0
- data/lib/debug_logging/configuration.rb +3 -2
- data/lib/debug_logging/finalize.rb +10 -8
- data/lib/debug_logging/hooks.rb +7 -5
- data/lib/debug_logging/instance_logger.rb +8 -2
- data/lib/debug_logging/instance_logger_modulizer.rb +19 -49
- data/lib/debug_logging/instance_notifier.rb +6 -0
- data/lib/debug_logging/instance_notifier_modulizer.rb +15 -31
- data/lib/debug_logging/lamb_dart/base.rb +46 -0
- data/lib/debug_logging/lamb_dart/log.rb +47 -0
- data/lib/debug_logging/lamb_dart/note.rb +30 -0
- data/lib/debug_logging/lamb_dart.rb +9 -0
- data/lib/debug_logging/lamb_dartable.rb +41 -0
- data/lib/debug_logging/lamb_darts/benchmarked.rb +19 -0
- data/lib/debug_logging/lamb_darts/enter_log.rb +16 -0
- data/lib/debug_logging/lamb_darts/error_handle.rb +28 -0
- data/lib/debug_logging/lamb_darts/exit_log.rb +15 -0
- data/lib/debug_logging/lamb_darts/notify.rb +17 -0
- data/lib/debug_logging/log_subscriber.rb +33 -26
- data/lib/debug_logging/util.rb +23 -19
- data/lib/debug_logging/version.rb +4 -1
- data/lib/debug_logging.rb +14 -9
- data/lib/simple_debug_logging.rb +18 -16
- data/sig/debug_logging/version.rbs +6 -0
- data.tar.gz.sig +0 -0
- metadata +129 -141
- metadata.gz.sig +0 -0
- 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
|
|
6
|
-
|
|
7
|
-
|
|
|
8
|
-
| 3.x | ❌ |
|
|
9
|
-
| 2.x | ❌ |
|
|
10
|
-
| 1.x | ❌ |
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
|----------|-----------|
|
|
7
|
+
| 1.latest | ✅ |
|
|
11
8
|
|
|
12
|
-
##
|
|
9
|
+
## Security contact information
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
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,
|
|
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[
|
|
59
|
+
config_proxy.debug_colorized_chain_for_method.call(ColorizedString[decorated_method.to_s])
|
|
59
60
|
else
|
|
60
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
208
|
-
|
|
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 |
|
|
10
|
-
|
|
11
|
-
method_names:
|
|
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(
|
|
21
|
+
original_method = method(decorated_method)
|
|
16
22
|
(class << self; self; end).class_eval do
|
|
17
|
-
define_method(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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 |
|
|
10
|
-
|
|
11
|
-
method_names:
|
|
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(
|
|
21
|
+
original_method = method(decorated_method)
|
|
16
22
|
(class << self; self; end).class_eval do
|
|
17
|
-
define_method(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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,
|
|
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(
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if obj.
|
|
9
|
-
obj.debug_finalize
|
|
10
|
-
|
|
11
|
-
|
|
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
|
data/lib/debug_logging/hooks.rb
CHANGED
|
@@ -3,12 +3,14 @@ require "timeout"
|
|
|
3
3
|
|
|
4
4
|
module DebugLogging
|
|
5
5
|
module Hooks
|
|
6
|
-
|
|
7
|
-
mod
|
|
8
|
-
|
|
6
|
+
class << self
|
|
7
|
+
def included(mod)
|
|
8
|
+
mod.extend(ClassMethods)
|
|
9
|
+
end
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
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 |
|
|
38
|
+
Array(methods_to_log).map do |decorated_method|
|
|
33
39
|
DebugLogging::InstanceLoggerModulizer.to_mod(
|
|
34
|
-
methods_to_log: Array(
|
|
40
|
+
methods_to_log: Array(decorated_method),
|
|
35
41
|
payload: payload,
|
|
36
42
|
config: config_opts,
|
|
37
43
|
)
|