debug_logging 1.0.17 → 3.1.2

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.
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "debug_logging"
4
+ require 'bundler/setup'
5
+ require 'debug_logging'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "debug_logging"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
@@ -1,34 +1,42 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'debug_logging/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "debug_logging"
8
+ spec.name = 'debug_logging'
8
9
  spec.version = DebugLogging::VERSION
9
- spec.authors = ["Peter Boling"]
10
- spec.email = ["peter.boling@gmail.com"]
10
+ spec.authors = ['Peter Boling']
11
+ spec.email = ['peter.boling@gmail.com']
11
12
 
12
- spec.summary = %q{Drop-in debug logging useful when a call stack gets unruly}
13
- spec.description = %q{
13
+ spec.summary = 'Drop-in debug logging useful when a call stack gets unruly'
14
+ spec.description = '
14
15
  Unobtrusive debug logging for Ruby. NO LITTERING.
15
16
  Automatically log selected methods and their arguments as they are called at runtime!
16
- }
17
- spec.license = "MIT"
18
- spec.homepage = "https://github.com/pboling/debug_logging"
17
+ '
18
+ spec.license = 'MIT'
19
+ spec.homepage = 'https://github.com/pboling/debug_logging'
19
20
 
20
21
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
21
22
  f.match(%r{^(test|spec|features)/})
22
23
  end
23
- spec.bindir = "exe"
24
+ spec.bindir = 'exe'
24
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
- spec.require_paths = ["lib"]
26
- spec.required_ruby_version = ">= 2.0.0" # Uses named parameters
26
+ spec.require_paths = ['lib']
27
+ spec.required_ruby_version = '>= 2.4.0' # Uses magic comments
27
28
 
28
- spec.add_runtime_dependency "colorize", "~> 0.8"
29
- spec.add_development_dependency "rspec-pending_for"
30
- spec.add_development_dependency "bundler", "~> 1.14"
31
- spec.add_development_dependency "rake", "~> 12.2"
32
- spec.add_development_dependency "rspec", "~> 3.0"
33
- spec.add_development_dependency "activesupport", "~> 5.1"
29
+ spec.add_runtime_dependency 'colorize', '>= 0'
30
+ spec.add_development_dependency 'activesupport', '~> 5.2', '>= 5.2.4.4'
31
+ spec.add_development_dependency 'bundler', '>= 2'
32
+ spec.add_development_dependency 'byebug', '>= 11'
33
+ spec.add_development_dependency 'rake', '>= 13'
34
+ spec.add_development_dependency 'rspec', '>= 3'
35
+ spec.add_development_dependency 'rspec-pending_for', '>= 0'
36
+ spec.add_development_dependency 'rubocop', '~> 1.0'
37
+ spec.add_development_dependency 'rubocop-md'
38
+ spec.add_development_dependency 'rubocop-performance'
39
+ spec.add_development_dependency 'rubocop-rake'
40
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.0'
41
+ spec.add_development_dependency 'silent_stream', '>= 1'
34
42
  end
@@ -1,13 +1,15 @@
1
- require "logger"
2
- require "colorized_string"
3
- require "digest"
1
+ # frozen_string_literal: true
4
2
 
5
- require "debug_logging/version"
6
- require "debug_logging/configuration"
7
- require "debug_logging/argument_printer"
8
- require "debug_logging/instance_logger_modulizer"
9
- require "debug_logging/instance_logger"
10
- require "debug_logging/class_logger"
3
+ require 'logger'
4
+ require 'colorized_string'
5
+ require 'digest'
6
+
7
+ require 'debug_logging/version'
8
+ require 'debug_logging/configuration'
9
+ require 'debug_logging/argument_printer'
10
+ require 'debug_logging/instance_logger_modulizer'
11
+ require 'debug_logging/instance_logger'
12
+ require 'debug_logging/class_logger'
11
13
 
12
14
  ####################
13
15
  # #
@@ -62,12 +64,12 @@ module DebugLogging
62
64
  end
63
65
 
64
66
  #### API ####
65
- # Not used by this gem internally, but provides an external interface for
67
+ # Not used by this gem internally, but provides an external interface for
66
68
  # classes to also use this logging tool directly,
67
69
  # with configured options like benchmarking, colors, or leg level.
68
70
  def debug_log(message = nil, config_proxy = nil, &block)
69
71
  # If a, instance-method-level, or class-method-level custom config is not
70
- # passed in, then fall back to the class' default config, which is a
72
+ # passed in, then fall back to the class' default config, which is a
71
73
  # potentially customized copy of the default config for the whole app.
72
74
  config_proxy ||= debug_config
73
75
  config_proxy.log(message, &block)
@@ -103,87 +105,115 @@ module DebugLogging
103
105
  def debug_config_reset(config = Configuration.new)
104
106
  @debug_logging_configuration = config
105
107
  end
108
+
106
109
  def debug_enabled
107
110
  @debug_logging_configuration.enabled
108
111
  end
112
+
109
113
  def debug_enabled=(value)
110
114
  @debug_logging_configuration.enabled = value
111
115
  end
116
+
112
117
  def debug_logger
113
118
  @debug_logging_configuration.logger
114
119
  end
120
+
115
121
  def debug_logger=(logger)
116
122
  @debug_logging_configuration.logger = logger
117
123
  end
124
+
118
125
  def debug_log_level
119
126
  @debug_logging_configuration.log_level
120
127
  end
128
+
121
129
  def debug_log_level=(log_level)
122
130
  @debug_logging_configuration.log_level = log_level
123
131
  end
132
+
124
133
  def debug_multiple_last_hashes
125
134
  @debug_logging_configuration.multiple_last_hashes
126
135
  end
136
+
127
137
  def debug_multiple_last_hashes=(multiple_last_hashes)
128
138
  @debug_logging_configuration.multiple_last_hashes = multiple_last_hashes
129
139
  end
140
+
130
141
  def debug_last_hash_to_s_proc
131
142
  @debug_logging_configuration.last_hash_to_s_proc
132
143
  end
144
+
133
145
  def debug_last_hash_to_s_proc=(last_hash_to_s_proc)
134
146
  @debug_logging_configuration.last_hash_to_s_proc = last_hash_to_s_proc
135
147
  end
148
+
136
149
  def debug_last_hash_max_length
137
150
  @debug_logging_configuration.last_hash_max_length
138
151
  end
152
+
139
153
  def debug_last_hash_max_length=(last_hash_max_length)
140
154
  @debug_logging_configuration.last_hash_max_length = last_hash_max_length
141
155
  end
156
+
142
157
  def debug_args_max_length
143
158
  @debug_logging_configuration.args_max_length
144
159
  end
160
+
145
161
  def debug_args_max_length=(args_max_length)
146
162
  @debug_logging_configuration.args_max_length = args_max_length
147
163
  end
164
+
148
165
  def debug_instance_benchmarks
149
166
  @debug_logging_configuration.instance_benchmarks
150
167
  end
168
+
151
169
  def debug_instance_benchmarks=(instance_benchmarks)
152
170
  @debug_logging_configuration.instance_benchmarks = instance_benchmarks
153
171
  end
172
+
154
173
  def debug_class_benchmarks
155
174
  @debug_logging_configuration.class_benchmarks
156
175
  end
176
+
157
177
  def debug_class_benchmarks=(class_benchmarks)
158
178
  @debug_logging_configuration.class_benchmarks = class_benchmarks
159
179
  end
180
+
160
181
  def debug_colorized_chain_for_method
161
182
  @debug_logging_configuration.colorized_chain_for_method
162
183
  end
184
+
163
185
  def debug_colorized_chain_for_method=(colorized_chain_for_method)
164
186
  @debug_logging_configuration.colorized_chain_for_method = colorized_chain_for_method
165
187
  end
188
+
166
189
  def debug_colorized_chain_for_class
167
190
  @debug_logging_configuration.colorized_chain_for_class
168
191
  end
192
+
169
193
  def debug_colorized_chain_for_class=(colorized_chain_for_class)
170
194
  @debug_logging_configuration.colorized_chain_for_class = colorized_chain_for_class
171
195
  end
196
+
172
197
  def debug_add_invocation_id
173
198
  @debug_logging_configuration.add_invocation_id
174
199
  end
200
+
175
201
  def debug_add_invocation_id=(add_invocation_id)
176
202
  @debug_logging_configuration.add_invocation_id = add_invocation_id
177
203
  end
204
+
178
205
  def debug_mark_scope_exit
179
206
  @debug_logging_configuration.mark_scope_exit
180
207
  end
208
+
181
209
  def debug_mark_scope_exit=(mark_scope_exit)
182
210
  @debug_logging_configuration.mark_scope_exit = mark_scope_exit
183
211
  end
212
+
184
213
  def debug_ellipsis
185
214
  @debug_logging_configuration.ellipsis
186
215
  end
216
+
187
217
  def debug_ellipsis=(ellipsis)
188
218
  @debug_logging_configuration.ellipsis = ellipsis
189
219
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'debug_logging/log_subscriber'
4
+ require 'debug_logging/class_notifier'
5
+ require 'debug_logging/instance_notifier_modulizer'
6
+ require 'debug_logging/instance_notifier'
@@ -1,22 +1,30 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DebugLogging
2
4
  module ArgumentPrinter
3
5
  def debug_benchmark_to_s(tms: nil)
4
- "completed in #{sprintf("%f", tms.real)}s (#{sprintf("%f", tms.total)}s CPU)"
6
+ "completed in #{format('%f', tms.real)}s (#{format('%f', tms.total)}s CPU)"
5
7
  end
8
+
6
9
  def debug_invocation_id_to_s(args: nil, config_proxy: nil)
10
+ return '' unless args && config_proxy
11
+
7
12
  if config_proxy.debug_add_invocation_id
8
- invocation = " ~#{args.object_id}@#{(Time.now.to_f.to_s % '%#-21a')[4..(-4)]}~"
13
+ invocation = " ~#{args.object_id}@#{(Time.now.to_f.to_s % '%#-21a')[4..-4]}~"
9
14
  case config_proxy.debug_add_invocation_id
10
- when true then
15
+ when true
11
16
  invocation
12
17
  else
13
18
  config_proxy.debug_add_invocation_id.call(ColorizedString[invocation])
14
19
  end
15
20
  else
16
- ""
21
+ ''
17
22
  end
18
23
  end
24
+
19
25
  def debug_invocation_to_s(klass: nil, separator: nil, method_to_log: nil, config_proxy: nil)
26
+ return '' unless config_proxy
27
+
20
28
  klass_string = if config_proxy.debug_colorized_chain_for_class
21
29
  config_proxy.debug_colorized_chain_for_class.call(ColorizedString[klass.to_s])
22
30
  else
@@ -29,52 +37,90 @@ module DebugLogging
29
37
  end
30
38
  "#{klass_string}#{separator}#{method_string}"
31
39
  end
32
- def debug_signature_to_s(args: nil, config_proxy: nil)
33
- printed_args = ""
40
+
41
+ def debug_signature_to_s(args: nil, config_proxy: nil) # rubocop:disable Metrics/CyclomaticComplexity
42
+ return '' unless args && config_proxy
43
+
44
+ printed_args = ''
45
+
34
46
  add_args_ellipsis = false
35
47
  if config_proxy.debug_last_hash_to_s_proc && args[-1].is_a?(Hash)
48
+ add_last_hash_ellipsis = false
36
49
  if args.length > 1
37
- add_last_hash_ellipsis = false
38
50
  if config_proxy.debug_multiple_last_hashes
39
51
  last_hash_args, other_args = args.partition do |arg|
40
- arg.is_a?(Hash)
41
- end
42
- other_args_string = other_args.map(&:inspect).join(", ")[0..(config_proxy.debug_args_max_length)]
43
- # On the debug_multiple_last_hashes truthy branch we don't print the ellipsis after regular args
44
- # because it will go instead after the last hash (if needed)
45
- # ...join(", ").tap {|x| _add_args_ellipsis = x.length > config_proxy.debug_args_max_length}
52
+ arg.is_a?(Hash)
53
+ end
54
+ other_args_string = other_args.map(&:inspect).join(', ')[0..(config_proxy.debug_args_max_length)]
55
+ # On the debug_multiple_last_hashes truthy branch we don't print the ellipsis after regular args
56
+ # because it will go instead after the last hash (if needed)
57
+ # ...join(", ").tap {|x| _add_args_ellipsis = x.length > config_proxy.debug_args_max_length}
46
58
  last_hash_args_string = last_hash_args.map do |arg|
47
- config_proxy.debug_last_hash_to_s_proc.call(arg).to_s.
48
- tap {|x|
49
- add_last_hash_ellipsis = x.length > config_proxy.debug_last_hash_max_length
50
- }[0..(config_proxy.debug_last_hash_max_length)].
51
- tap {|x|
52
- x << config_proxy.debug_ellipsis if add_last_hash_ellipsis
53
- }
54
- end.join(", ")
55
- printed_args << other_args_string if other_args_string
56
- printed_args << ", " if !other_args_string.empty? && !last_hash_args_string.empty?
57
- printed_args << last_hash_args_string if last_hash_args_string
59
+ arr = []
60
+ arr << config_proxy.debug_last_hash_to_s_proc.call(arg).to_s
61
+ .tap do |x|
62
+ add_last_hash_ellipsis = x.length > config_proxy.debug_last_hash_max_length
63
+ end
64
+ if add_last_hash_ellipsis
65
+ arr[-1] = arr[-1][0..(config_proxy.debug_last_hash_max_length)]
66
+ arr << config_proxy.debug_ellipsis
67
+ end
68
+ arr
69
+ end.flatten.join(', ')
70
+ printed_args += other_args_string if other_args_string
71
+ printed_args += ', ' if !other_args_string.empty? && !last_hash_args_string.empty?
72
+ printed_args += last_hash_args_string if last_hash_args_string && !last_hash_args_string.empty?
58
73
  else
59
- printed_args << args[0..(-2)].map {|x| x.inspect}.join(", ").tap {|x| add_args_ellipsis = x.length > config_proxy.debug_args_max_length}[0..(config_proxy.debug_args_max_length)]
60
- printed_args << config_proxy.debug_ellipsis if add_args_ellipsis
61
- printed_args << ", " << config_proxy.debug_last_hash_to_s_proc.call(args[-1]).tap {|x| add_last_hash_ellipsis = x.length > config_proxy.debug_last_hash_max_length}[0..(config_proxy.debug_last_hash_max_length)]
62
- printed_args << config_proxy.debug_ellipsis if add_last_hash_ellipsis
74
+ printed_args += args[0..-2].map(&:inspect).join(', ').tap do |x|
75
+ add_args_ellipsis = x.length > config_proxy.debug_args_max_length
76
+ end [0..(config_proxy.debug_args_max_length)]
77
+ printed_args += config_proxy.debug_ellipsis if add_args_ellipsis
78
+ printed_args += ", #{config_proxy.debug_last_hash_to_s_proc.call(args[-1]).tap do |x|
79
+ add_last_hash_ellipsis = x.length > config_proxy.debug_last_hash_max_length
80
+ end [0..(config_proxy.debug_last_hash_max_length)]}"
81
+ printed_args += config_proxy.debug_ellipsis if add_last_hash_ellipsis
63
82
  end
64
83
  else
65
- printed_args << String(config_proxy.debug_last_hash_to_s_proc.call(args[0])).tap {|x| add_last_hash_ellipsis = x.length > config_proxy.debug_last_hash_max_length}[0..(config_proxy.debug_last_hash_max_length)]
66
- printed_args << config_proxy.debug_ellipsis if add_last_hash_ellipsis
84
+ printed_args += String(config_proxy.debug_last_hash_to_s_proc.call(args[0])).tap do |x|
85
+ add_last_hash_ellipsis = x.length > config_proxy.debug_last_hash_max_length
86
+ end [0..(config_proxy.debug_last_hash_max_length)]
87
+ printed_args += config_proxy.debug_ellipsis if add_last_hash_ellipsis
67
88
  end
68
89
  else
69
- if args.length == 1 && args[0].is_a?(Hash)
70
- # handle double splat
71
- printed_args << ("**" << args.map {|x| x.inspect}.join(", ").tap {|x| add_args_ellipsis = x.length > config_proxy.debug_args_max_length})[0..(config_proxy.debug_args_max_length)]
90
+ printed_args += if args.length == 1 && args[0].is_a?(Hash)
91
+ # handle double splat
92
+ ("**#{args.map(&:inspect).join(', ').tap do |x|
93
+ add_args_ellipsis = x.length > config_proxy.debug_args_max_length
94
+ end }")[0..(config_proxy.debug_args_max_length)]
95
+ else
96
+ args.map(&:inspect).join(', ').tap do |x|
97
+ add_args_ellipsis = x.length > config_proxy.debug_args_max_length
98
+ end [0..(config_proxy.debug_args_max_length)]
99
+ end
100
+ printed_args += config_proxy.debug_ellipsis if add_args_ellipsis
101
+ end
102
+ "(#{printed_args})"
103
+ end
104
+
105
+ def debug_payload_to_s(payload: nil, config_proxy: nil)
106
+ return '' unless payload && config_proxy
107
+
108
+ if payload
109
+ case config_proxy.debug_add_payload
110
+ when true
111
+ payload.inspect
72
112
  else
73
- printed_args << args.map {|x| x.inspect}.join(", ").tap {|x| add_args_ellipsis = x.length > config_proxy.debug_args_max_length}[0..(config_proxy.debug_args_max_length)]
113
+ config_proxy.debug_add_payload.call(**payload)
74
114
  end
75
- printed_args << config_proxy.debug_ellipsis if add_args_ellipsis
115
+ else
116
+ ''
76
117
  end
77
- "(#{printed_args})"
118
+ end
119
+
120
+ module_function
121
+
122
+ def debug_event_name_to_s(method_to_notify: nil)
123
+ "#{method_to_notify}.log"
78
124
  end
79
125
  end
80
126
  end
@@ -1,9 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DebugLogging
2
4
  module ClassLogger
3
5
  def logged(*methods_to_log)
4
6
  # When opts are present it will always be a new configuration instance per method
5
7
  # When opts are not present it will reuse the class' configuration object
6
- opts = methods_to_log.last.is_a?(Hash) && methods_to_log.pop
8
+ payload = methods_to_log.last.is_a?(Hash) && methods_to_log.pop.dup || {}
9
+ config_opts = {}
10
+ unless payload.empty?
11
+ DebugLogging::Configuration::CONFIG_KEYS.each { |k| config_opts[k] = payload.delete(k) if payload.key?(k) }
12
+ end
7
13
  if methods_to_log.first.is_a?(Array)
8
14
  methods_to_log = methods_to_log.shift
9
15
  else
@@ -15,36 +21,58 @@ module DebugLogging
15
21
  original_method = method(method_to_log)
16
22
  (class << self; self; end).class_eval do
17
23
  define_method(method_to_log) do |*args, &block|
18
- config_proxy = if (proxy = instance_variable_get(DebugLogging::Configuration.config_pointer('k', method_to_log)))
24
+ config_proxy = if (proxy = instance_variable_get(DebugLogging::Configuration.config_pointer('kl',
25
+ method_to_log)))
19
26
  proxy
20
27
  else
21
- proxy = if opts
22
- Configuration.new(**(debug_config.to_hash.merge(opts)))
23
- else
28
+ proxy = if config_opts.empty?
24
29
  debug_config
30
+ else
31
+ DebugLogging::Configuration.new(**debug_config.to_hash.merge(config_opts))
25
32
  end
26
33
  proxy.register(method_to_log)
27
- instance_variable_set(DebugLogging::Configuration.config_pointer('k', method_to_log), proxy)
34
+ instance_variable_set(DebugLogging::Configuration.config_pointer('kl', method_to_log),
35
+ proxy)
28
36
  proxy
29
37
  end
30
38
  method_return_value = nil
31
39
  log_prefix = nil
32
40
  invocation_id = nil
33
41
  config_proxy.log do
34
- log_prefix = debug_invocation_to_s(klass: to_s, separator: ".", method_to_log: method_to_log, config_proxy: config_proxy)
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
52
+ log_prefix = debug_invocation_to_s(klass: to_s, separator: '.', method_to_log: method_to_log,
53
+ config_proxy: config_proxy)
35
54
  invocation_id = debug_invocation_id_to_s(args: args, config_proxy: config_proxy)
36
55
  signature = debug_signature_to_s(args: args, config_proxy: config_proxy)
37
- "#{log_prefix}#{signature}#{invocation_id}"
56
+ paymud = debug_payload_to_s(payload: paydirt, config_proxy: config_proxy)
57
+ "#{log_prefix}#{signature}#{invocation_id} debug: #{paymud}"
38
58
  end
39
59
  if config_proxy.benchmarkable_for?(:debug_class_benchmarks)
40
60
  tms = Benchmark.measure do
41
- method_return_value = original_method.call(*args, &block)
61
+ method_return_value = if args.size == 1 && (harsh = args[0]) && harsh.is_a?(Hash)
62
+ original_method.call(**harsh, &block)
63
+ else
64
+ original_method.call(*args, &block)
65
+ end
42
66
  end
43
67
  config_proxy.log do
44
68
  "#{log_prefix} #{debug_benchmark_to_s(tms: tms)}#{invocation_id}"
45
69
  end
46
70
  else
47
- method_return_value = original_method.call(*args, &block)
71
+ method_return_value = if args.size == 1 && (harsh = args[0]) && harsh.is_a?(Hash)
72
+ original_method.call(**harsh, &block)
73
+ else
74
+ original_method.call(*args, &block)
75
+ end
48
76
  if config_proxy.exit_scope_markable? && invocation_id && !invocation_id.empty?
49
77
  config_proxy.log do
50
78
  "#{log_prefix} completed#{invocation_id}"