debug_logging 3.1.2 → 3.1.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
- data/README.md +12 -4
- data/debug_logging.gemspec +1 -1
- data/lib/debug_logging.rb +9 -0
- data/lib/debug_logging/argument_printer.rb +5 -5
- data/lib/debug_logging/class_logger.rb +18 -39
- data/lib/debug_logging/class_notifier.rb +27 -37
- data/lib/debug_logging/errors.rb +7 -0
- data/lib/debug_logging/finalize.rb +20 -0
- data/lib/debug_logging/hooks.rb +82 -0
- data/lib/debug_logging/instance_logger.rb +3 -1
- data/lib/debug_logging/instance_logger_modulizer.rb +18 -38
- data/lib/debug_logging/instance_notifier.rb +6 -2
- data/lib/debug_logging/instance_notifier_modulizer.rb +24 -43
- data/lib/debug_logging/util.rb +75 -0
- data/lib/debug_logging/version.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6eee794d14ae44299b2737ff61beab4165c434132262861104d60b4da781445
|
4
|
+
data.tar.gz: c9fdb194a05fa751879a60bb73bd4eb3fe4507b0680b1ee437f5d88fa65b3fa0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8eeb20c2a01e99b3069f8b592f54271497a6835402e76d73edba964645c2b6600e83e3d497b7eddf5720087b89421e61caa7e5224124f5205fdde6f0b82d5426
|
7
|
+
data.tar.gz: fce74d216e19def9b2e8b208036138732fc82add3e889fdd3a09199dab285354c5863b1a11b12feb451faa9e39294507ec704e40031568272ac03a6c1be13077
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# DebugLogging
|
2
2
|
|
3
3
|
Unobtrusive, inheritable-overridable-configurable, drop-in debug logging, that won't leave a mess behind when it is time to remove it.
|
4
|
+
Supports ActiveSupport::Notifications (thanks [@jgillson](https://github.com/jgillson)). Optional ActiveRecord callback-style hooks that you can decorate your methods with. Hooks logic was taken from the [`slippy_method_hooks` gem](https://github.com/guckin/slippy_method_hooks), (thanks [@guckin](https://github.com/guckin)), and prefaced with `debug_` for this implementation. `DebugLogging::Finalize` is lightly modified from [this stackoverflow answer](https://stackoverflow.com/a/34559282).
|
4
5
|
|
5
6
|
## What do I mean by "unobtrusive"?
|
6
7
|
|
@@ -32,12 +33,15 @@ Unobtrusive, inheritable-overridable-configurable, drop-in debug logging, that w
|
|
32
33
|
* *colorization by class/method*
|
33
34
|
* *robust argument printer with customizable ellipsis*
|
34
35
|
* *unique invocation identifiers*
|
35
|
-
* *single line config, per class/instance/method config*
|
36
|
-
* *separate
|
36
|
+
* *simple single line global config, or per class/instance/method config*
|
37
|
+
* *separate loggers, if needed*
|
37
38
|
* *log method calls, also when exit scope*
|
38
39
|
* *Prevents heavy computation of strings with `logger.debug { 'log me' }` block format, since v1.0.12*
|
39
|
-
* *ActiveSupport::Notifications integration for instrumenting/logging events on class and instance methods, since v3.
|
40
|
-
* *Optional instance variable logging,
|
40
|
+
* *ActiveSupport::Notifications integration for instrumenting/logging events on class and instance methods, since v3.2*
|
41
|
+
* *Optional instance, and class-instance, variable logging, since v3.2*
|
42
|
+
* *ActiveRecord style callback-hooks (optional: `require 'debug_logging/hooks'` and `include DebugLogging::Hooks`), since v3.2*
|
43
|
+
* *All configuration is inheritable to, and overridable by, child classes, since v3.2*
|
44
|
+
* *[Class finalization hook](https://stackoverflow.com/a/34559282) (optional: `require 'debug_logging/finalize'` and `extend DebugLogging::Finalize`), since v3.2*
|
41
45
|
* **so many free ponies** 🎠🐴🎠🐴🎠🐴
|
42
46
|
|
43
47
|
## Next Level Magic
|
@@ -381,6 +385,10 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
381
385
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
382
386
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
383
387
|
|
388
|
+
### License Exceptions
|
389
|
+
|
390
|
+
* [`debug_logging/finalize`](https://stackoverflow.com/a/34559282) is licensed under https://creativecommons.org/licenses/by-sa/4.0/
|
391
|
+
|
384
392
|
[semver]: http://semver.org/
|
385
393
|
[pvc]: http://docs.rubygems.org/read/chapter/16#page74
|
386
394
|
[railsbling]: http://www.railsbling.com
|
data/debug_logging.gemspec
CHANGED
@@ -7,7 +7,7 @@ require 'debug_logging/version'
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
8
|
spec.name = 'debug_logging'
|
9
9
|
spec.version = DebugLogging::VERSION
|
10
|
-
spec.authors = ['Peter Boling']
|
10
|
+
spec.authors = ['Peter Boling', 'guckin']
|
11
11
|
spec.email = ['peter.boling@gmail.com']
|
12
12
|
|
13
13
|
spec.summary = 'Drop-in debug logging useful when a call stack gets unruly'
|
data/lib/debug_logging.rb
CHANGED
@@ -5,8 +5,12 @@ require 'colorized_string'
|
|
5
5
|
require 'digest'
|
6
6
|
|
7
7
|
require 'debug_logging/version'
|
8
|
+
require 'debug_logging/errors'
|
8
9
|
require 'debug_logging/configuration'
|
10
|
+
require 'debug_logging/util'
|
11
|
+
require 'debug_logging/finalize'
|
9
12
|
require 'debug_logging/argument_printer'
|
13
|
+
require 'debug_logging/hooks'
|
10
14
|
require 'debug_logging/instance_logger_modulizer'
|
11
15
|
require 'debug_logging/instance_logger'
|
12
16
|
require 'debug_logging/class_logger'
|
@@ -61,6 +65,11 @@ module DebugLogging
|
|
61
65
|
def self.extended(base)
|
62
66
|
base.send(:extend, ArgumentPrinter)
|
63
67
|
base.debug_config_reset(Configuration.new(**debug_logging_configuration.to_hash))
|
68
|
+
base.class_eval do
|
69
|
+
def base.inherited(subclass)
|
70
|
+
subclass.debug_config_reset(Configuration.new(**debug_config.to_hash))
|
71
|
+
end
|
72
|
+
end
|
64
73
|
end
|
65
74
|
|
66
75
|
#### API ####
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module DebugLogging
|
4
4
|
module ArgumentPrinter
|
5
|
-
def debug_benchmark_to_s(tms:
|
5
|
+
def debug_benchmark_to_s(tms:)
|
6
6
|
"completed in #{format('%f', tms.real)}s (#{format('%f', tms.total)}s CPU)"
|
7
7
|
end
|
8
8
|
|
@@ -73,17 +73,17 @@ module DebugLogging
|
|
73
73
|
else
|
74
74
|
printed_args += args[0..-2].map(&:inspect).join(', ').tap do |x|
|
75
75
|
add_args_ellipsis = x.length > config_proxy.debug_args_max_length
|
76
|
-
end
|
76
|
+
end[0..(config_proxy.debug_args_max_length)]
|
77
77
|
printed_args += config_proxy.debug_ellipsis if add_args_ellipsis
|
78
78
|
printed_args += ", #{config_proxy.debug_last_hash_to_s_proc.call(args[-1]).tap do |x|
|
79
79
|
add_last_hash_ellipsis = x.length > config_proxy.debug_last_hash_max_length
|
80
|
-
end
|
80
|
+
end[0..(config_proxy.debug_last_hash_max_length)]}"
|
81
81
|
printed_args += config_proxy.debug_ellipsis if add_last_hash_ellipsis
|
82
82
|
end
|
83
83
|
else
|
84
84
|
printed_args += String(config_proxy.debug_last_hash_to_s_proc.call(args[0])).tap do |x|
|
85
85
|
add_last_hash_ellipsis = x.length > config_proxy.debug_last_hash_max_length
|
86
|
-
end
|
86
|
+
end[0..(config_proxy.debug_last_hash_max_length)]
|
87
87
|
printed_args += config_proxy.debug_ellipsis if add_last_hash_ellipsis
|
88
88
|
end
|
89
89
|
else
|
@@ -95,7 +95,7 @@ module DebugLogging
|
|
95
95
|
else
|
96
96
|
args.map(&:inspect).join(', ').tap do |x|
|
97
97
|
add_args_ellipsis = x.length > config_proxy.debug_args_max_length
|
98
|
-
end
|
98
|
+
end[0..(config_proxy.debug_args_max_length)]
|
99
99
|
end
|
100
100
|
printed_args += config_proxy.debug_ellipsis if add_args_ellipsis
|
101
101
|
end
|
@@ -3,52 +3,31 @@
|
|
3
3
|
module DebugLogging
|
4
4
|
module ClassLogger
|
5
5
|
def logged(*methods_to_log)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
methods_to_log.each do |method_to_log|
|
19
|
-
# method name must be a symbol
|
20
|
-
method_to_log = method_to_log.to_sym
|
6
|
+
methods_to_log, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
|
7
|
+
method_names: methods_to_log,
|
8
|
+
payload: nil,
|
9
|
+
config: nil
|
10
|
+
)
|
11
|
+
Array(methods_to_log).each do |method_to_log|
|
12
|
+
method_to_log, method_payload, method_config_opts = DebugLogging::Util.extract_payload_and_config(
|
13
|
+
method_names: method_to_log,
|
14
|
+
payload: payload,
|
15
|
+
config: config_opts
|
16
|
+
)
|
21
17
|
original_method = method(method_to_log)
|
22
18
|
(class << self; self; end).class_eval do
|
23
19
|
define_method(method_to_log) do |*args, &block|
|
24
|
-
config_proxy =
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
else
|
31
|
-
DebugLogging::Configuration.new(**debug_config.to_hash.merge(config_opts))
|
32
|
-
end
|
33
|
-
proxy.register(method_to_log)
|
34
|
-
instance_variable_set(DebugLogging::Configuration.config_pointer('kl', method_to_log),
|
35
|
-
proxy)
|
36
|
-
proxy
|
37
|
-
end
|
20
|
+
config_proxy = DebugLogging::Util.config_proxy_finder(
|
21
|
+
scope: self,
|
22
|
+
config_opts: method_config_opts,
|
23
|
+
method_name: method_to_log,
|
24
|
+
proxy_ref: 'kl'
|
25
|
+
)
|
38
26
|
method_return_value = nil
|
39
27
|
log_prefix = nil
|
40
28
|
invocation_id = nil
|
41
29
|
config_proxy.log do
|
42
|
-
paydirt =
|
43
|
-
# TODO: Could make instance variable introspection configurable before or after method execution
|
44
|
-
if payload.key?(:instance_variables)
|
45
|
-
paydirt.merge!(payload.reject { |k| k == :instance_variables })
|
46
|
-
payload[:instance_variables].each do |k|
|
47
|
-
paydirt[k] = instance_variable_get("@#{k}") if instance_variable_defined?("@#{k}")
|
48
|
-
end
|
49
|
-
else
|
50
|
-
paydirt.merge!(payload)
|
51
|
-
end
|
30
|
+
paydirt = DebugLogging::Util.payload_instance_vaiable_hydration(scope: self, payload: method_payload)
|
52
31
|
log_prefix = debug_invocation_to_s(klass: to_s, separator: '.', method_to_log: method_to_log,
|
53
32
|
config_proxy: config_proxy)
|
54
33
|
invocation_id = debug_invocation_id_to_s(args: args, config_proxy: config_proxy)
|
@@ -3,51 +3,41 @@
|
|
3
3
|
module DebugLogging
|
4
4
|
module ClassNotifier
|
5
5
|
def notifies(*methods_to_notify)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
methods_to_notify.each do |method_to_notify|
|
19
|
-
# method name must be a symbol
|
20
|
-
method_to_notify = method_to_notify.to_sym
|
6
|
+
methods_to_notify, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
|
7
|
+
method_names: methods_to_notify,
|
8
|
+
payload: nil,
|
9
|
+
config: nil
|
10
|
+
)
|
11
|
+
Array(methods_to_notify).each do |method_to_notify|
|
12
|
+
method_to_notify, method_payload, method_config_opts = DebugLogging::Util.extract_payload_and_config(
|
13
|
+
method_names: method_to_notify,
|
14
|
+
payload: payload,
|
15
|
+
config: config_opts
|
16
|
+
)
|
21
17
|
original_method = method(method_to_notify)
|
22
18
|
(class << self; self; end).class_eval do
|
23
19
|
define_method(method_to_notify) do |*args, &block|
|
24
|
-
config_proxy =
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
proxy.log do
|
40
|
-
DebugLogging::LogSubscriber.log_event(ActiveSupport::Notifications::Event.new(*debug_args))
|
41
|
-
end
|
42
|
-
end
|
43
|
-
proxy
|
44
|
-
end
|
20
|
+
config_proxy = DebugLogging::Util.config_proxy_finder(
|
21
|
+
scope: self,
|
22
|
+
config_opts: method_config_opts,
|
23
|
+
method_name: method_to_notify,
|
24
|
+
proxy_ref: 'kn'
|
25
|
+
) do |proxy|
|
26
|
+
ActiveSupport::Notifications.subscribe(
|
27
|
+
DebugLogging::ArgumentPrinter.debug_event_name_to_s(method_to_notify: method_to_notify)
|
28
|
+
) do |*debug_args|
|
29
|
+
proxy.log do
|
30
|
+
DebugLogging::LogSubscriber.log_event(ActiveSupport::Notifications::Event.new(*debug_args))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
paydirt = DebugLogging::Util.payload_instance_vaiable_hydration(scope: self, payload: method_payload)
|
45
35
|
ActiveSupport::Notifications.instrument(
|
46
36
|
DebugLogging::ArgumentPrinter.debug_event_name_to_s(method_to_notify: method_to_notify),
|
47
37
|
{
|
48
38
|
debug_args: args,
|
49
39
|
config_proxy: config_proxy,
|
50
|
-
**
|
40
|
+
**paydirt
|
51
41
|
}
|
52
42
|
) do
|
53
43
|
if args.size == 1 && (harsh = args[0]) && harsh.is_a?(Hash)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# From: https://stackoverflow.com/a/34559282
|
4
|
+
# License: https://creativecommons.org/licenses/by-sa/4.0/
|
5
|
+
module DebugLogging
|
6
|
+
module Finalize
|
7
|
+
def self.extended(obj)
|
8
|
+
TracePoint.trace(:end) do |t|
|
9
|
+
if obj == t.self
|
10
|
+
if obj.respond_to?(:debug_finalize)
|
11
|
+
obj.debug_finalize
|
12
|
+
else
|
13
|
+
warn "#{obj} does not define a debug_finalize"
|
14
|
+
end
|
15
|
+
t.disable
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'debug_logging/errors'
|
2
|
+
require 'timeout'
|
3
|
+
|
4
|
+
module DebugLogging
|
5
|
+
module Hooks
|
6
|
+
def self.included(mod)
|
7
|
+
mod.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.extend(mod)
|
11
|
+
mod.extend(ClassMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def debug_time_box(time, *names, &blk)
|
16
|
+
names.each do |name|
|
17
|
+
meth = instance_method(name)
|
18
|
+
define_method(name) do |*args, &block|
|
19
|
+
begin
|
20
|
+
Timeout.timeout(time) do
|
21
|
+
meth.bind(self).call(*args, &block)
|
22
|
+
end
|
23
|
+
rescue Timeout::Error
|
24
|
+
error_args = [TimeoutError, 'execution expired', caller]
|
25
|
+
raise(*error_args) unless blk
|
26
|
+
|
27
|
+
instance_exec(*error_args, &blk)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def debug_rescue_on_fail(*names, &blk)
|
34
|
+
unless blk
|
35
|
+
raise NoBlockGiven,
|
36
|
+
'.rescue_on_fail must be called with a block',
|
37
|
+
caller
|
38
|
+
end
|
39
|
+
names.each do |name|
|
40
|
+
meth = instance_method(name)
|
41
|
+
define_method(name) do |*args, &block|
|
42
|
+
begin
|
43
|
+
meth.bind(self).call(*args, &block)
|
44
|
+
rescue StandardError => e
|
45
|
+
instance_exec(e, &blk)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def debug_before(*names, &blk)
|
52
|
+
unless blk
|
53
|
+
raise NoBlockGiven,
|
54
|
+
'.before must be called with a block',
|
55
|
+
caller
|
56
|
+
end
|
57
|
+
names.each do |name|
|
58
|
+
meth = instance_method(name)
|
59
|
+
define_method name do |*args, &block|
|
60
|
+
instance_exec(name, *args, block, &blk)
|
61
|
+
meth.bind(self).call(*args, &block)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def debug_after(*names, &blk)
|
67
|
+
unless blk
|
68
|
+
raise NoBlockGiven,
|
69
|
+
'.after must be called with a block',
|
70
|
+
caller
|
71
|
+
end
|
72
|
+
names.each do |name|
|
73
|
+
meth = instance_method(name)
|
74
|
+
define_method name do |*args, &block|
|
75
|
+
result = meth.bind(self).call(*args, &block)
|
76
|
+
instance_exec(result, &blk)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
module DebugLogging
|
4
4
|
class InstanceLogger < Module
|
5
|
-
def initialize(i_methods: nil, config: nil)
|
5
|
+
def initialize(i_methods: nil, payload: nil, config: nil)
|
6
6
|
super()
|
7
7
|
@config = config
|
8
|
+
@payload = payload
|
8
9
|
@instance_methods_to_log = Array(i_methods) if i_methods
|
9
10
|
end
|
10
11
|
|
@@ -13,6 +14,7 @@ module DebugLogging
|
|
13
14
|
|
14
15
|
base.send(:include, ArgumentPrinter)
|
15
16
|
instance_method_logger = DebugLogging::InstanceLoggerModulizer.to_mod(methods_to_log: @instance_methods_to_log,
|
17
|
+
payload: @payload,
|
16
18
|
config: @config)
|
17
19
|
base.send(:prepend, instance_method_logger)
|
18
20
|
end
|
@@ -2,52 +2,32 @@
|
|
2
2
|
|
3
3
|
module DebugLogging
|
4
4
|
module InstanceLoggerModulizer
|
5
|
-
def self.to_mod(methods_to_log: nil, config: nil)
|
5
|
+
def self.to_mod(methods_to_log: nil, payload: nil, config: nil)
|
6
6
|
Module.new do
|
7
|
+
methods_to_log, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
|
8
|
+
method_names: Array(methods_to_log),
|
9
|
+
payload: payload,
|
10
|
+
config: config
|
11
|
+
)
|
7
12
|
Array(methods_to_log).each do |method_to_log|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# method name must be a symbol
|
14
|
-
method_to_log = if method_to_log.is_a?(Array)
|
15
|
-
method_to_log.first&.to_sym
|
16
|
-
else
|
17
|
-
method_to_log.to_sym
|
18
|
-
end
|
13
|
+
method_to_log, method_payload, method_config_opts = DebugLogging::Util.extract_payload_and_config(
|
14
|
+
method_names: method_to_log,
|
15
|
+
payload: payload,
|
16
|
+
config: config_opts
|
17
|
+
)
|
19
18
|
define_method(method_to_log) do |*args, &block|
|
20
19
|
method_return_value = nil
|
21
|
-
config_proxy =
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
elsif !config_opts.empty?
|
28
|
-
Configuration.new(**self.class.debug_config.to_hash.merge(config_opts))
|
29
|
-
else
|
30
|
-
self.class.debug_config
|
31
|
-
end
|
32
|
-
proxy.register(method_to_log)
|
33
|
-
instance_variable_set(DebugLogging::Configuration.config_pointer('ilm', method_to_log),
|
34
|
-
proxy)
|
35
|
-
proxy
|
36
|
-
end
|
20
|
+
config_proxy = DebugLogging::Util.config_proxy_finder(
|
21
|
+
scope: self.class,
|
22
|
+
config_opts: method_config_opts,
|
23
|
+
method_name: method_to_log,
|
24
|
+
proxy_ref: 'ilm'
|
25
|
+
)
|
37
26
|
log_prefix = self.class.debug_invocation_to_s(klass: self.class.to_s, separator: '#',
|
38
27
|
method_to_log: method_to_log, config_proxy: config_proxy)
|
39
28
|
invocation_id = self.class.debug_invocation_id_to_s(args: args, config_proxy: config_proxy)
|
40
29
|
config_proxy.log do
|
41
|
-
paydirt =
|
42
|
-
# TODO: Could make instance variable introspection configurable before or after method execution
|
43
|
-
if payload.key?(:instance_variables)
|
44
|
-
paydirt.merge!(payload.reject { |k| k == :instance_variables })
|
45
|
-
payload[:instance_variables].each do |k|
|
46
|
-
paydirt[k] = instance_variable_get("@#{k}") if instance_variable_defined?("@#{k}")
|
47
|
-
end
|
48
|
-
else
|
49
|
-
paydirt.merge!(payload)
|
50
|
-
end
|
30
|
+
paydirt = DebugLogging::Util.payload_instance_vaiable_hydration(scope: self, payload: method_payload)
|
51
31
|
signature = self.class.debug_signature_to_s(args: args, config_proxy: config_proxy)
|
52
32
|
paymud = debug_payload_to_s(payload: paydirt, config_proxy: config_proxy)
|
53
33
|
"#{log_prefix}#{signature}#{invocation_id} debug: #{paymud}"
|
@@ -2,8 +2,10 @@
|
|
2
2
|
|
3
3
|
module DebugLogging
|
4
4
|
class InstanceNotifier < Module
|
5
|
-
def initialize(i_methods: nil)
|
5
|
+
def initialize(i_methods: nil, payload: nil, config: nil)
|
6
6
|
super()
|
7
|
+
@config = config
|
8
|
+
@payload = payload
|
7
9
|
@instance_methods_to_notify = Array(i_methods) if i_methods
|
8
10
|
end
|
9
11
|
|
@@ -11,7 +13,9 @@ module DebugLogging
|
|
11
13
|
return unless @instance_methods_to_notify
|
12
14
|
|
13
15
|
base.send(:include, ArgumentPrinter)
|
14
|
-
instance_method_notifier = DebugLogging::InstanceNotifierModulizer.to_mod(methods_to_notify: @instance_methods_to_notify
|
16
|
+
instance_method_notifier = DebugLogging::InstanceNotifierModulizer.to_mod(methods_to_notify: @instance_methods_to_notify,
|
17
|
+
payload: @payload,
|
18
|
+
config: @config)
|
15
19
|
base.send(:prepend, instance_method_notifier)
|
16
20
|
end
|
17
21
|
end
|
@@ -2,47 +2,35 @@
|
|
2
2
|
|
3
3
|
module DebugLogging
|
4
4
|
module InstanceNotifierModulizer
|
5
|
-
def self.to_mod(methods_to_notify: nil)
|
5
|
+
def self.to_mod(methods_to_notify: nil, payload: nil, config: nil)
|
6
6
|
Module.new do
|
7
|
-
|
8
|
-
|
7
|
+
methods_to_notify, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
|
8
|
+
method_names: Array(methods_to_notify),
|
9
|
+
payload: payload,
|
10
|
+
config: config
|
11
|
+
)
|
9
12
|
Array(methods_to_notify).each do |method_to_notify|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
method_to_notify = if method_to_notify.is_a?(Array)
|
17
|
-
method_to_notify.first&.to_sym
|
18
|
-
else
|
19
|
-
method_to_notify.to_sym
|
20
|
-
end
|
13
|
+
method_to_notify, method_payload, method_config_opts = DebugLogging::Util.extract_payload_and_config(
|
14
|
+
method_names: method_to_notify,
|
15
|
+
payload: payload,
|
16
|
+
config: config_opts
|
17
|
+
)
|
21
18
|
define_method(method_to_notify) do |*args, &block|
|
22
|
-
config_proxy =
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
)
|
35
|
-
proxy
|
36
|
-
end
|
37
|
-
paydirt = {}
|
38
|
-
if payload.key?(:instance_variables)
|
39
|
-
paydirt.merge!(payload.reject { |k| k == :instance_variables })
|
40
|
-
payload[:instance_variables].each do |k|
|
41
|
-
paydirt[k] = instance_variable_get("@#{k}") if instance_variable_defined?("@#{k}")
|
19
|
+
config_proxy = DebugLogging::Util.config_proxy_finder(
|
20
|
+
scope: self.class,
|
21
|
+
config_opts: method_config_opts,
|
22
|
+
method_name: method_to_notify,
|
23
|
+
proxy_ref: 'inm'
|
24
|
+
) do |config_proxy|
|
25
|
+
ActiveSupport::Notifications.subscribe(
|
26
|
+
DebugLogging::ArgumentPrinter.debug_event_name_to_s(method_to_notify: method_to_notify)
|
27
|
+
) do |*args|
|
28
|
+
config_proxy&.log do
|
29
|
+
DebugLogging::LogSubscriber.log_event(ActiveSupport::Notifications::Event.new(*args))
|
30
|
+
end
|
42
31
|
end
|
43
|
-
else
|
44
|
-
paydirt.merge!(payload)
|
45
32
|
end
|
33
|
+
paydirt = DebugLogging::Util.payload_instance_vaiable_hydration(scope: self, payload: method_payload)
|
46
34
|
ActiveSupport::Notifications.instrument(
|
47
35
|
DebugLogging::ArgumentPrinter.debug_event_name_to_s(method_to_notify: method_to_notify),
|
48
36
|
debug_args: args,
|
@@ -52,13 +40,6 @@ module DebugLogging
|
|
52
40
|
super(*args, &block)
|
53
41
|
end
|
54
42
|
end
|
55
|
-
ActiveSupport::Notifications.subscribe(
|
56
|
-
DebugLogging::ArgumentPrinter.debug_event_name_to_s(method_to_notify: method_to_notify)
|
57
|
-
) do |*args|
|
58
|
-
config_proxy&.log do
|
59
|
-
DebugLogging::LogSubscriber.log_event(ActiveSupport::Notifications::Event.new(*args))
|
60
|
-
end
|
61
|
-
end
|
62
43
|
end
|
63
44
|
end
|
64
45
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module DebugLogging
|
2
|
+
module Util
|
3
|
+
module_function
|
4
|
+
|
5
|
+
# methods_to_log may be an array of a single method name, followed by config options and payload,
|
6
|
+
# or it could be an array of method names followed by config options and payload to be shared by the whole set.
|
7
|
+
def extract_payload_and_config(method_names:, payload: nil, config: nil)
|
8
|
+
# When scoped config is present it will always be a new configuration instance per method
|
9
|
+
# When scoped config is not present it will reuse the class' configuration object
|
10
|
+
scoped_payload = (method_names.is_a?(Array) && method_names.last.is_a?(Hash) && method_names.pop.clone(freeze: false)) || {}
|
11
|
+
payload = if payload
|
12
|
+
payload.merge(scoped_payload)
|
13
|
+
else
|
14
|
+
scoped_payload
|
15
|
+
end
|
16
|
+
config_opts = config&.clone(freeze: false) || {}
|
17
|
+
unless payload.empty?
|
18
|
+
DebugLogging::Configuration::CONFIG_KEYS.each { |k| config_opts[k] = payload.delete(k) if payload.key?(k) }
|
19
|
+
end
|
20
|
+
method_names =
|
21
|
+
case method_names
|
22
|
+
when Symbol
|
23
|
+
method_names
|
24
|
+
when String
|
25
|
+
method_names.to_sym
|
26
|
+
when Array
|
27
|
+
if method_names.first.is_a?(Array)
|
28
|
+
# Array of arrays?
|
29
|
+
method_names.shift
|
30
|
+
elsif method_names.size == 1 && method_names.first.is_a?(Symbol)
|
31
|
+
# when set as i_methods: [[:i_with_dsplat_payload, { tags: %w[blue green] }], ...]
|
32
|
+
method_names.shift.to_sym
|
33
|
+
else
|
34
|
+
# Or an array of method name symbols?
|
35
|
+
# logged :meth1, :meth2, :meth3 without options is valid
|
36
|
+
method_names
|
37
|
+
end
|
38
|
+
end
|
39
|
+
[method_names, payload, config_opts]
|
40
|
+
end
|
41
|
+
|
42
|
+
def payload_instance_vaiable_hydration(scope:, payload:)
|
43
|
+
paydirt = {}
|
44
|
+
# TODO: Could make instance variable introspection configurable before or after method execution
|
45
|
+
if payload.key?(:instance_variables)
|
46
|
+
paydirt.merge!(payload.reject { |k| k == :instance_variables })
|
47
|
+
payload[:instance_variables].each do |k|
|
48
|
+
paydirt[k] = scope.send(:instance_variable_get, "@#{k}") if scope.send(:instance_variable_defined?, "@#{k}")
|
49
|
+
end
|
50
|
+
else
|
51
|
+
paydirt.merge!(payload)
|
52
|
+
end
|
53
|
+
paydirt
|
54
|
+
end
|
55
|
+
|
56
|
+
def config_proxy_finder(scope:, method_name:, proxy_ref:, config_opts: {}, &block)
|
57
|
+
if (proxy = scope.send(:instance_variable_get, DebugLogging::Configuration.config_pointer(proxy_ref,
|
58
|
+
method_name)))
|
59
|
+
proxy
|
60
|
+
else
|
61
|
+
base = scope.respond_to?(:debug_config) ? scope.debug_config : DebugLogging.debug_logging_configuration
|
62
|
+
proxy = if config_opts.empty?
|
63
|
+
base
|
64
|
+
else
|
65
|
+
DebugLogging::Configuration.new(**base.to_hash.merge(config_opts))
|
66
|
+
end
|
67
|
+
proxy.register(method_name)
|
68
|
+
scope.send(:instance_variable_set, DebugLogging::Configuration.config_pointer(proxy_ref, method_name),
|
69
|
+
proxy)
|
70
|
+
yield proxy if block
|
71
|
+
proxy
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: debug_logging
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Boling
|
8
|
+
- guckin
|
8
9
|
autorequire:
|
9
10
|
bindir: exe
|
10
11
|
cert_chain: []
|
11
|
-
date: 2020-12-
|
12
|
+
date: 2020-12-18 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: colorize
|
@@ -226,11 +227,15 @@ files:
|
|
226
227
|
- lib/debug_logging/class_logger.rb
|
227
228
|
- lib/debug_logging/class_notifier.rb
|
228
229
|
- lib/debug_logging/configuration.rb
|
230
|
+
- lib/debug_logging/errors.rb
|
231
|
+
- lib/debug_logging/finalize.rb
|
232
|
+
- lib/debug_logging/hooks.rb
|
229
233
|
- lib/debug_logging/instance_logger.rb
|
230
234
|
- lib/debug_logging/instance_logger_modulizer.rb
|
231
235
|
- lib/debug_logging/instance_notifier.rb
|
232
236
|
- lib/debug_logging/instance_notifier_modulizer.rb
|
233
237
|
- lib/debug_logging/log_subscriber.rb
|
238
|
+
- lib/debug_logging/util.rb
|
234
239
|
- lib/debug_logging/version.rb
|
235
240
|
- lib/simple_debug_logging.rb
|
236
241
|
homepage: https://github.com/pboling/debug_logging
|
@@ -252,7 +257,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
252
257
|
- !ruby/object:Gem::Version
|
253
258
|
version: '0'
|
254
259
|
requirements: []
|
255
|
-
rubygems_version: 3.1
|
260
|
+
rubygems_version: 3.2.1
|
256
261
|
signing_key:
|
257
262
|
specification_version: 4
|
258
263
|
summary: Drop-in debug logging useful when a call stack gets unruly
|