debug_logging 3.1.9 → 4.0.1

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.
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "date"
4
2
  require "time"
5
3
 
@@ -9,11 +7,13 @@ module DebugLogging
9
7
  "completed in #{format("%f", tms.real)}s (#{format("%f", tms.total)}s CPU)"
10
8
  end
11
9
 
12
- def debug_invocation_id_to_s(args: nil, config_proxy: nil)
13
- return "" unless args && config_proxy
10
+ def debug_invocation_id_to_s(args: nil, kwargs: nil, start_at: nil, config_proxy: nil)
11
+ return "" unless (args || kwargs) && config_proxy
14
12
 
15
13
  if config_proxy.debug_add_invocation_id
16
- invocation = " ~#{args.object_id}@#{(Time.now.to_f.to_s % "%#-21a")[4..-4]}~"
14
+ time = start_at ? Util.debug_time(start_at) : Time.now
15
+ unique_id = (time.to_f.to_s % "%#-21a")[4..-4]
16
+ invocation = " ~#{args.object_id}|#{kwargs.object_id}@#{unique_id}~"
17
17
  case config_proxy.debug_add_invocation_id
18
18
  when true
19
19
  invocation
@@ -25,21 +25,25 @@ module DebugLogging
25
25
  end
26
26
  end
27
27
 
28
- def debug_time_to_s(time_or_monotonic)
28
+ # @return [String]
29
+ def debug_time_to_s(time_or_monotonic, config_proxy: nil)
30
+ return "" unless config_proxy&.debug_add_timestamp
31
+ return config_proxy.debug_time_formatter_proc.call(Time.now) unless time_or_monotonic
32
+
33
+ time = Util.debug_time(time_or_monotonic)
34
+
35
+ config_proxy.debug_time_formatter_proc.call(time)
36
+ end
37
+
38
+ # A custom time format will never apply here, because ActiveSupport::Notifications have a required time format
39
+ def debug_event_time_to_s(time_or_monotonic)
29
40
  # Time format must match:
30
41
  # \d{4,}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4}
31
42
  # YYYY-MM-DD HH:mm:ss +00:00
32
43
  # strftime("%F %T %z")
33
- case time_or_monotonic
34
- when Float
35
- Time.at(time_or_monotonic).strftime("%F %T %z")
36
- when Time, DateTime
37
- time_or_monotonic.strftime("%F %T %z")
38
- when String
39
- Time.parse(time_or_monotonic).strftime("%F %T %z")
40
- else
41
- time_or_monotonic
42
- end
44
+ time_or_monotonic = Time.now if time_or_monotonic.nil? || (time_or_monotonic.respond_to?(:empty?) && time_or_monotonic.empty?)
45
+ time = Util.debug_time(time_or_monotonic)
46
+ DebugLogging::Constants::EVENT_TIME_FORMATTER.call(time)
43
47
  end
44
48
 
45
49
  def debug_invocation_to_s(klass: nil, separator: nil, method_to_log: nil, config_proxy: nil)
@@ -58,12 +62,14 @@ module DebugLogging
58
62
  "#{klass_string}#{separator}#{method_string}"
59
63
  end
60
64
 
61
- def debug_signature_to_s(args: nil, config_proxy: nil) # rubocop:disable Metrics/CyclomaticComplexity
62
- return "" unless args && config_proxy
65
+ def debug_signature_to_s(args: nil, kwargs: nil, config_proxy: nil) # rubocop:disable Metrics/CyclomaticComplexity
66
+ return "" unless (args || kwargs) && config_proxy
63
67
 
64
68
  printed_args = ""
65
69
 
66
70
  add_args_ellipsis = false
71
+ args = args.dup
72
+ args.push(kwargs) if kwargs
67
73
  if config_proxy.debug_last_hash_to_s_proc && args[-1].is_a?(Hash)
68
74
  add_other_args_ellipsis = false
69
75
  if args.length > 1
@@ -188,7 +194,7 @@ module DebugLogging
188
194
  proc_name: "add_payload",
189
195
  proc: config_proxy.debug_add_payload,
190
196
  args: payload,
191
- max_length: config_proxy.payload_max_length,
197
+ max_length: config_proxy.debug_payload_max_length,
192
198
  )
193
199
  printed_payload += printed
194
200
  printed_payload += config_proxy.debug_ellipsis if add_payload_ellipsis
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  module DebugLogging
4
2
  module ClassLogger
5
3
  def logged(*methods_to_log)
@@ -31,7 +29,7 @@ module DebugLogging
31
29
  paydirt = DebugLogging::Util.payload_instance_variable_hydration(scope: self, payload: method_payload)
32
30
  log_prefix = debug_invocation_to_s(
33
31
  klass: to_s,
34
- separator: ".",
32
+ separator: "::",
35
33
  method_to_log: method_to_log,
36
34
  config_proxy: config_proxy,
37
35
  )
@@ -1,8 +1,6 @@
1
- # frozen_string_literal: true
2
-
3
1
  module DebugLogging
4
2
  module ClassNotifier
5
- def notifies(*methods_to_notify)
3
+ def notified(*methods_to_notify)
6
4
  methods_to_notify, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
7
5
  method_names: methods_to_notify,
8
6
  payload: nil,
@@ -40,18 +38,16 @@ module DebugLogging
40
38
  **paydirt,
41
39
  },
42
40
  ) do
43
- begin
44
- if args.size == 1 && (harsh = args[0]) && harsh.is_a?(Hash)
45
- original_method.call(**harsh, &block)
46
- else
47
- original_method.call(*args, &block)
48
- end
49
- rescue StandardError => e
50
- if config_proxy.error_handler_proc
51
- config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_notify, args)
52
- else
53
- raise e
54
- end
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
55
51
  end
56
52
  end
57
53
  end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  module DebugLogging
4
2
  class Configuration
5
3
  include Constants
@@ -11,21 +9,29 @@ module DebugLogging
11
9
  # alias the readers to the debug_* prefix so an instance of this class
12
10
  # can have the same API granted by `extend DebugLogging`
13
11
  #
14
- # include DebugLogging::InstanceLogger.new(
15
- # i_methods: [:drive, :stop],
16
- # config: {
17
- # logger: Logger.new(STDOUT) # probably want to override to be the Rails.logger
18
- # log_level: :debug # at what level do the messages created by this gem sent at?
19
- # last_hash_to_s_proc: nil # e.g. ->(hash) { "keys: #{hash.keys}" }
20
- # last_hash_max_length: 1_000
21
- # args_to_s_proc: nil # e.g. ->(*record) { "record id: #{record.first.id}" }
22
- # args_max_length: 1_000
23
- # instance_benchmarks: false
24
- # class_benchmarks: false
25
- # add_invocation_id: true # invocation id allows you to identify a method call uniquely in a log
26
- # ellipsis: " ✂️ …".freeze
12
+ # extend DebugLogging::InstanceLogger
13
+ # i_logged [:drive, :stop],
14
+ # {
15
+ # logger: Logger.new($stdout), # probably want to override to be the Rails.logger
16
+ # log_level: :debug, # at what level do the messages created by this gem sent at?
17
+ # multiple_last_hashes: false,
18
+ # last_hash_to_s_proc: nil, # e.g. ->(hash) { "keys: #{hash.keys}" }
19
+ # last_hash_max_length: 1_000,
20
+ # args_to_s_proc: nil, # e.g. ->(*record) { "record id: #{record.first.id}" }
21
+ # args_max_length: 1_000,
22
+ # colorized_chain_for_method: false, # e.g. ->(colorized_string) { colorized_string.red.on_blue.underline }
23
+ # colorized_chain_for_class: false, # e.g. ->(colorized_string) { colorized_string.colorize(:light_blue ).colorize( :background => :red) }
24
+ # add_invocation_id: true, # allows unique identification of method call; association of entry and exit log lines
25
+ # ellipsis: " ✂️ …".freeze,
26
+ # mark_scope_exit: false,
27
+ # add_payload: true, # Can also be a proc returning a string, which will be called when printing the payload
28
+ # payload_max_length: 1_000,
29
+ # error_handler_proc: nil,
30
+ # time_formatter_proc: DebugLogging::Constants::DEFAULT_TIME_FORMATTER,
31
+ # add_timestamp: false,
32
+ # instance_benchmarks: false,
33
+ # class_benchmarks: false,
27
34
  # }
28
- # )
29
35
  #
30
36
  CONFIG_KEYS.each do |key|
31
37
  alias_method :"debug_#{key}", :"#{key}"
@@ -39,12 +45,13 @@ module DebugLogging
39
45
  "@debug_logging_config_#{type}_#{Digest::MD5.hexdigest(method_to_log.to_s)}".to_sym
40
46
  end
41
47
  end
48
+
42
49
  def initialize(**options)
43
50
  CONFIG_ATTRS.each do |key|
44
- send("#{key}=", get_attr_from_options(options, key))
51
+ send(:"#{key}=", get_attr_from_options(options, key))
45
52
  end
46
53
  CONFIG_READERS.each do |key|
47
- send("#{key}=", get_reader_from_options(options, key))
54
+ send(:"#{key}=", get_reader_from_options(options, key))
48
55
  end
49
56
  @methods_to_log = []
50
57
  end
@@ -63,7 +70,7 @@ module DebugLogging
63
70
  def loggable?
64
71
  return @loggable if defined?(@loggable)
65
72
 
66
- @loggable = logger.send("#{log_level}?")
73
+ @loggable = logger.send(:"#{log_level}?")
67
74
  end
68
75
 
69
76
  def benchmarkable_for?(benchmarks)
@@ -95,7 +102,7 @@ module DebugLogging
95
102
 
96
103
  def to_hash
97
104
  CONFIG_KEYS.each_with_object({}) do |key, hash|
98
- hash[key] = instance_variable_get("@#{key}")
105
+ hash[key] = instance_variable_get(:"@#{key}")
99
106
  end
100
107
  end
101
108
 
@@ -1,25 +1,27 @@
1
- # frozen_string_literal: true
2
-
3
1
  module DebugLogging
4
2
  module Constants
5
3
  DEFAULT_ELLIPSIS = " ✂️ …"
4
+ DEFAULT_TIME_FORMATTER = ->(time) { "[#{time.strftime("%Y%m%d %H:%M:%S")}] " }
5
+ EVENT_TIME_FORMATTER = ->(time) { time.strftime("%F %T %z") }
6
6
  CONFIG_ATTRS_DEFAULTS = {
7
7
  enabled: true,
8
- logger: Logger.new($stdout),
9
- log_level: :debug,
8
+ logger: Logger.new($stdout), # probably want to override to be the Rails.logger
9
+ log_level: :debug, # at what level do the messages created by this gem sent at?
10
10
  multiple_last_hashes: false,
11
- last_hash_to_s_proc: nil,
11
+ last_hash_to_s_proc: nil, # e.g. ->(hash) { "keys: #{hash.keys}" }
12
12
  last_hash_max_length: 1_000,
13
- args_to_s_proc: nil,
13
+ args_to_s_proc: nil, # e.g. ->(*record) { "record id: #{record.first.id}" }
14
14
  args_max_length: 1_000,
15
- colorized_chain_for_method: false,
16
- colorized_chain_for_class: false,
17
- add_invocation_id: true,
15
+ colorized_chain_for_method: false, # e.g. ->(colorized_string) { colorized_string.red.on_blue.underline }
16
+ colorized_chain_for_class: false, # e.g. ->(colorized_string) { colorized_string.colorize(:light_blue ).colorize( :background => :red) }
17
+ add_invocation_id: true, # allows unique identification of method call; association of entry and exit log lines
18
18
  ellipsis: DEFAULT_ELLIPSIS,
19
19
  mark_scope_exit: false,
20
20
  add_payload: true, # Can also be a proc returning a string, which will be called when printing the payload
21
21
  payload_max_length: 1_000,
22
22
  error_handler_proc: nil,
23
+ time_formatter_proc: DEFAULT_TIME_FORMATTER,
24
+ add_timestamp: false,
23
25
  }.freeze
24
26
  CONFIG_ATTRS = CONFIG_ATTRS_DEFAULTS.keys
25
27
  CONFIG_READERS_DEFAULTS = {
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # From: https://stackoverflow.com/a/34559282
4
2
  # License: https://creativecommons.org/licenses/by-sa/4.0/
5
3
  module DebugLogging
@@ -16,16 +16,14 @@ module DebugLogging
16
16
  names.each do |name|
17
17
  meth = instance_method(name)
18
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)
19
+ Timeout.timeout(time) do
20
+ meth.bind_call(self, *args, &block)
28
21
  end
22
+ rescue Timeout::Error
23
+ error_args = [TimeoutError, "execution expired", caller]
24
+ raise(*error_args) unless blk
25
+
26
+ instance_exec(*error_args, &blk)
29
27
  end
30
28
  end
31
29
  end
@@ -39,11 +37,9 @@ module DebugLogging
39
37
  names.each do |name|
40
38
  meth = instance_method(name)
41
39
  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
40
+ meth.bind_call(self, *args, &block)
41
+ rescue StandardError => e
42
+ instance_exec(e, &blk)
47
43
  end
48
44
  end
49
45
  end
@@ -58,7 +54,7 @@ module DebugLogging
58
54
  meth = instance_method(name)
59
55
  define_method(name) do |*args, &block|
60
56
  instance_exec(name, *args, block, &blk)
61
- meth.bind(self).call(*args, &block)
57
+ meth.bind_call(self, *args, &block)
62
58
  end
63
59
  end
64
60
  end
@@ -72,7 +68,7 @@ module DebugLogging
72
68
  names.each do |name|
73
69
  meth = instance_method(name)
74
70
  define_method(name) do |*args, &block|
75
- result = meth.bind(self).call(*args, &block)
71
+ result = meth.bind_call(self, *args, &block)
76
72
  instance_exec(result, &blk)
77
73
  end
78
74
  end
@@ -1,24 +1,50 @@
1
- # frozen_string_literal: true
2
-
3
1
  module DebugLogging
4
- class InstanceLogger < Module
5
- def initialize(i_methods: nil, payload: nil, config: nil)
6
- super()
7
- @config = config
8
- @payload = payload
9
- @instance_methods_to_log = Array(i_methods) if i_methods
10
- end
11
-
12
- def included(base)
13
- return unless @instance_methods_to_log
14
-
15
- base.send(:include, ArgumentPrinter)
16
- instance_method_logger = DebugLogging::InstanceLoggerModulizer.to_mod(
17
- methods_to_log: @instance_methods_to_log,
18
- payload: @payload,
19
- config: @config,
2
+ module InstanceLogger
3
+ # NOTE: These params can be passed in / hidden in a last hash of *args
4
+ # NOTE: They can also be passed in discretely for each method, by passing *args as an array of arrays
5
+ # TODO: Refactor to use modern Ruby 3 *args, **kwargs instead
6
+ # @param logger [Logger] Logger.new($stdout), # probably want to override to be the Rails.logger
7
+ # @param log_level [Symbol] default: :debug, at what level do the messages created by this gem sent at?
8
+ # @param multiple_last_hashes [true, false] default: false,
9
+ # @param last_hash_to_s_proc [nil, Proc] default: nil, e.g. ->(hash) { "keys: #{hash.keys}" }
10
+ # @param last_hash_max_length [Integer] default: 1_000,
11
+ # @param args_to_s_proc [nil, Proc] default: nil, e.g. ->(*record) { "record id: #{record.first.id}" }
12
+ # @param args_max_length [Integer] default: 1_000,
13
+ # @param colorized_chain_for_method [false, Proc] default: false, e.g. ->(colorized_string) { colorized_string.red.on_blue.underline }
14
+ # @param colorized_chain_for_class [false, Proc] default: false, e.g. ->(colorized_string) { colorized_string.colorize(:light_blue ).colorize( :background => :red) }
15
+ # @param add_invocation_id [true, false] default: true, allows unique identification of method call; association of entry and exit log lines
16
+ # @param ellipsis [String] default: " ✂️ …".freeze,
17
+ # @param mark_scope_exit [true, false] default: false,
18
+ # @param add_payload [true, false, Proc] default: true, # Can also be a proc returning a string, which will be called when printing the payload
19
+ # @param payload_max_length [Integer] default: 1_000,
20
+ # @param error_handler_proc [nil, Proc] default: nil,
21
+ # @param time_formatter_proc [nil, Proc] default: DebugLogging::Constants::DEFAULT_TIME_FORMATTER,
22
+ # @param add_timestamp [true, false] default: false,
23
+ # @param instance_benchmarks [true, false] default: false,
24
+ # @param class_benchmarks [true, false] default: false,
25
+ def i_logged(*methods_to_log)
26
+ methods_to_log, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
27
+ method_names: methods_to_log,
28
+ payload: nil,
29
+ config: nil,
20
30
  )
21
- base.send(:prepend, instance_method_logger)
31
+ instance_method_modules =
32
+ Array(methods_to_log).map do |method_to_log|
33
+ DebugLogging::InstanceLoggerModulizer.to_mod(
34
+ methods_to_log: Array(method_to_log),
35
+ payload: payload,
36
+ config: config_opts,
37
+ )
38
+ end
39
+ wrapped_in_logs = Module.new do
40
+ singleton_class.send(:define_method, :included) do |host_class|
41
+ instance_method_modules.each do |mod|
42
+ host_class.prepend(mod)
43
+ end
44
+ end
45
+ end
46
+
47
+ send(:include, wrapped_in_logs)
22
48
  end
23
49
  end
24
50
  end
@@ -1,65 +1,69 @@
1
- # frozen_string_literal: true
2
-
3
1
  module DebugLogging
4
2
  module InstanceLoggerModulizer
5
- def self.to_mod(methods_to_log: nil, payload: nil, config: nil)
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
- )
12
- Array(methods_to_log).each do |method_to_log|
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,
3
+ class << self
4
+ def to_mod(methods_to_log: nil, payload: nil, config: nil)
5
+ Module.new do
6
+ methods_to_log, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
7
+ method_names: Array(methods_to_log),
8
+ payload:,
9
+ config:,
17
10
  )
18
- define_method(method_to_log) do |*args, &block|
19
- method_return_value = nil
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",
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:,
15
+ config: config_opts,
25
16
  )
26
- log_prefix = self.class.debug_invocation_to_s(
27
- klass: self.class.to_s,
28
- separator: "#",
29
- method_to_log: method_to_log,
30
- config_proxy: config_proxy,
31
- )
32
- invocation_id = self.class.debug_invocation_id_to_s(args: args, config_proxy: config_proxy)
33
- config_proxy.log do
34
- paydirt = DebugLogging::Util.payload_instance_variable_hydration(scope: self, payload: method_payload)
35
- signature = self.class.debug_signature_to_s(args: args, config_proxy: config_proxy)
36
- paymud = debug_payload_to_s(payload: paydirt, config_proxy: config_proxy)
37
- "#{log_prefix}#{signature}#{invocation_id} debug: #{paymud}"
38
- end
39
- if config_proxy.benchmarkable_for?(:debug_instance_benchmarks)
40
- tms = Benchmark.measure do
41
- method_return_value = super(*args, &block)
42
- end
17
+ define_method(method_to_log) do |*args, **kwargs, &block|
18
+ method_return_value = nil
19
+ config_proxy = DebugLogging::Util.config_proxy_finder(
20
+ scope: self.class,
21
+ config_opts: method_config_opts,
22
+ method_name: method_to_log,
23
+ proxy_ref: "ilm",
24
+ )
25
+ log_prefix = self.class.debug_invocation_to_s(
26
+ klass: self.class.to_s,
27
+ separator: "#",
28
+ method_to_log: method_to_log,
29
+ config_proxy: config_proxy,
30
+ )
31
+ start_at = Time.now
32
+ start_timestamp = self.class.debug_time_to_s(start_at, config_proxy:)
33
+ invocation_id = self.class.debug_invocation_id_to_s(args:, kwargs:, start_at:, config_proxy:)
43
34
  config_proxy.log do
44
- "#{log_prefix} #{self.class.debug_benchmark_to_s(tms: tms)}#{invocation_id}"
35
+ paydirt = DebugLogging::Util.payload_instance_variable_hydration(scope: self, payload: method_payload)
36
+ signature = self.class.debug_signature_to_s(args:, kwargs:, config_proxy:)
37
+ paymud = debug_payload_to_s(payload: paydirt, config_proxy:)
38
+ "#{start_timestamp}#{log_prefix}#{signature}#{invocation_id} debug: #{paymud}"
45
39
  end
46
- else
47
- begin
48
- method_return_value = super(*args, &block)
49
- rescue StandardError => e
50
- if config_proxy.error_handler_proc
51
- config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_log, args)
52
- else
53
- raise e
40
+ if config_proxy.benchmarkable_for?(:debug_instance_benchmarks)
41
+ tms = Benchmark.measure do
42
+ method_return_value = super(*args, **kwargs, &block)
54
43
  end
55
- end
56
- if config_proxy.exit_scope_markable? && invocation_id && !invocation_id.empty?
44
+ end_timestamp = self.class.debug_time_to_s(Time.now, config_proxy:)
57
45
  config_proxy.log do
58
- "#{log_prefix} completed#{invocation_id}"
46
+ "#{end_timestamp}#{log_prefix} #{self.class.debug_benchmark_to_s(tms: tms)}#{invocation_id}"
47
+ end
48
+ else
49
+ begin
50
+ method_return_value = super(*args, **kwargs, &block)
51
+ rescue StandardError => e
52
+ if config_proxy.error_handler_proc
53
+ config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_log, args, kwargs)
54
+ else
55
+ raise e
56
+ end
57
+ end
58
+ if config_proxy.exit_scope_markable? && invocation_id && !invocation_id.empty?
59
+ end_timestamp = self.class.debug_time_to_s(Time.now, config_proxy:)
60
+ config_proxy.log do
61
+ "#{end_timestamp}#{log_prefix} completed#{invocation_id}"
62
+ end
59
63
  end
60
64
  end
65
+ method_return_value
61
66
  end
62
- method_return_value
63
67
  end
64
68
  end
65
69
  end
@@ -1,24 +1,24 @@
1
- # frozen_string_literal: true
2
-
3
1
  module DebugLogging
4
- class InstanceNotifier < Module
5
- def initialize(i_methods: nil, payload: nil, config: nil)
6
- super()
7
- @config = config
8
- @payload = payload
9
- @instance_methods_to_notify = Array(i_methods) if i_methods
10
- end
11
-
12
- def included(base)
13
- return unless @instance_methods_to_notify
14
-
15
- base.send(:include, ArgumentPrinter)
2
+ module InstanceNotifier
3
+ def i_notified(*methods_to_log)
4
+ method_names, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
5
+ method_names: methods_to_log,
6
+ payload: nil,
7
+ config: nil,
8
+ )
16
9
  instance_method_notifier = DebugLogging::InstanceNotifierModulizer.to_mod(
17
- methods_to_notify: @instance_methods_to_notify,
18
- payload: @payload,
19
- config: @config,
10
+ methods_to_notify: Array(method_names),
11
+ payload: payload,
12
+ config: config_opts,
20
13
  )
21
- base.send(:prepend, instance_method_notifier)
14
+
15
+ wrapped_in_notifier = Module.new do
16
+ singleton_class.send(:define_method, :included) do |host_class|
17
+ host_class.prepend(instance_method_notifier)
18
+ end
19
+ end
20
+
21
+ send(:include, wrapped_in_notifier)
22
22
  end
23
23
  end
24
24
  end
@@ -1,51 +1,45 @@
1
- # frozen_string_literal: true
2
-
3
1
  module DebugLogging
4
2
  module InstanceNotifierModulizer
5
- def self.to_mod(methods_to_notify: nil, payload: nil, config: nil)
6
- Module.new do
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
- )
12
- Array(methods_to_notify).each do |method_to_notify|
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,
3
+ class << self
4
+ def to_mod(methods_to_notify: nil, payload: nil, config: nil)
5
+ Module.new do
6
+ methods_to_notify, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
7
+ method_names: Array(methods_to_notify),
8
+ payload:,
9
+ config:,
17
10
  )
18
- define_method(method_to_notify) do |*args, &block|
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))
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:,
15
+ config: config_opts,
16
+ )
17
+ define_method(method_to_notify) do |*args, **kwargs, &block|
18
+ config_proxy = DebugLogging::Util.config_proxy_finder(
19
+ scope: self.class,
20
+ config_opts: method_config_opts,
21
+ method_name: method_to_notify,
22
+ proxy_ref: "inm",
23
+ ) do |config_proxy|
24
+ ActiveSupport::Notifications.subscribe(
25
+ DebugLogging::ArgumentPrinter.debug_event_name_to_s(method_to_notify:),
26
+ ) do |*subscribe_args|
27
+ config_proxy&.log do
28
+ DebugLogging::LogSubscriber.log_event(ActiveSupport::Notifications::Event.new(*subscribe_args))
29
+ end
30
30
  end
31
31
  end
32
- end
33
- paydirt = DebugLogging::Util.payload_instance_variable_hydration(scope: self, payload: method_payload)
34
- ActiveSupport::Notifications.instrument(
35
- DebugLogging::ArgumentPrinter.debug_event_name_to_s(method_to_notify: method_to_notify),
36
- debug_args: args,
37
- config_proxy: config_proxy,
38
- **paydirt,
39
- ) do
40
- begin
41
- # TODO: I need to split logic based on Ruby version.
42
- # TODO: Use VersionGem's minimum Ruby version check
43
- # TODO: Switch between positional, and kwargs argument handling
44
- # See: https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
45
- super(*args, &block)
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:),
35
+ debug_args: kwargs.empty? ? args : args + [kwargs],
36
+ config_proxy: config_proxy,
37
+ **paydirt,
38
+ ) do
39
+ super(*args, **kwargs, &block)
46
40
  rescue StandardError => e
47
41
  if config_proxy.error_handler_proc
48
- config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_notify, args)
42
+ config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_notify, args, kwargs)
49
43
  else
50
44
  raise e
51
45
  end