debug_logging 1.0.0 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 74f20737ddaf59151ab3118f196f2d811cfe4687
4
- data.tar.gz: 21a1c19d58110b20436788e74f94c2c5fdc62c10
3
+ metadata.gz: 95c155d2751e4ed8027d638174dd657f1205e009
4
+ data.tar.gz: 26c3390ea291a866f51c77b55961ae12c8439123
5
5
  SHA512:
6
- metadata.gz: 7ebb58f828a34bfa2be6c31228c977dd08e796070c2af386781efaf434d5453b7d333552908f47f8e3df5fe6a2a56148499f14d364c203cf1210309f54fa7378
7
- data.tar.gz: ee69b5dab10dbb4a5a076bd62ee0d3540747201d41e7bbf22b5b71d11321c2db5dce2bbb44cbc2afb08bd2bb93a5928a24cfce9e4872d49942c327f1907b77a3
6
+ metadata.gz: b58918fd56b134e8e1285a4b4551e1b722c58a3138c178dcea67b0250156cb13d34588d8ed5858112024753192ba9f399c3131e50794f68ac47c814045ce1407
7
+ data.tar.gz: 8f6addac4962c57b13dfa9b9140775a548b845ead6df02b0c47393b3723bf26adf997807b38f84f6b6b6eb0536d8e5c0475e25ba2577a0b33344d5031e9585b7
data/README.md CHANGED
@@ -79,6 +79,10 @@ end
79
79
  **All** of the above **config** is **inheritable** and **configurable** at the **per-class** level as well!
80
80
  Just prepend `debug_` to any config value you want to override in a class.
81
81
 
82
+ **All** of the above **config** is **inheritable** and **configurable** at the **per-method** level as well!
83
+ Just send along a hash of the config options when you call `logged` or `include DebugLogging::InstanceLogger.new(i_methods: [:drive, :stop])`. See the example class below:
84
+
85
+
82
86
  Every time a method is called, get logs, optionally with arguments, a benchmarck, and a unique invocation identifier:
83
87
 
84
88
  ```ruby
@@ -98,18 +102,25 @@ class Car
98
102
 
99
103
  extend DebugLogging::ClassLogger
100
104
 
101
- logged def debug_make; new; end
105
+ logged def make; new; end
102
106
  def design(*args); new; end
103
107
  def safety(*args); new; end
108
+ def dealer_options(*args); new; end
104
109
  logged :design, :safety
110
+ # override options for any instance method(s), by passing a hash as the last argument
111
+ logged :dealer_options, { multiple_last_hashes: true }
112
+
105
113
 
106
114
  def drive(speed); speed; end
107
- def stop; 0; end
115
+ def stop(**opts); 0; end
108
116
 
109
117
  # For instance methods:
110
118
  # Option 2: add logging to all instance methods defined above (but *not* defined below)
111
119
  include DebugLogging::InstanceLogger.new(i_methods: debug_instance_methods(false))
112
120
 
121
+ # override options for any instance method(s)
122
+ include DebugLogging::InstanceLogger.new(i_methods: [:stop], config: { multiple_last_hashes: true })
123
+
113
124
  def will_not_be_logged; false; end
114
125
 
115
126
  end
@@ -1,27 +1,48 @@
1
1
  module DebugLogging
2
2
  module ArgumentPrinter
3
- def debug_arguments_to_s(args)
4
- if debug_last_hash_to_s_proc && args[-1].is_a?(Hash)
3
+ def debug_arguments_to_s(args: nil, config_proxy: nil)
4
+ printed_args = ""
5
+ add_args_ellipsis = false
6
+ if config_proxy.debug_last_hash_to_s_proc && args[-1].is_a?(Hash)
5
7
  if args.length > 1
6
- add_args_ellipsis = false
7
8
  add_last_hash_ellipsis = false
8
- printed_args = args[0..(-2)].map {|x| x.inspect}.join(", ").tap {|x| add_args_ellipsis = x.length > debug_args_max_length}[0..(debug_args_max_length)]
9
- printed_args << debug_ellipsis if add_args_ellipsis
10
- printed_args << ", " << debug_last_hash_to_s_proc.call(args[-1]).tap {|x| add_last_hash_ellipsis = x.length > debug_last_hash_max_length}[0..(debug_last_hash_max_length)]
11
- printed_args << debug_ellipsis if add_last_hash_ellipsis
9
+ if config_proxy.debug_multiple_last_hashes
10
+ last_hash_args, other_args = args.partition do |arg|
11
+ arg.is_a?(Hash)
12
+ end
13
+ other_args_string = other_args.map(&:inspect).join(", ").tap {|x| add_args_ellipsis = x.length > config_proxy.debug_args_max_length}[0..(config_proxy.debug_args_max_length)]
14
+ last_hash_args_string = last_hash_args.map do |arg|
15
+ String(config_proxy.
16
+ debug_last_hash_to_s_proc.
17
+ call(arg)).
18
+ tap {|x|
19
+ add_last_hash_ellipsis = x.length > config_proxy.debug_last_hash_max_length
20
+ }[0..(config_proxy.debug_last_hash_max_length)].
21
+ tap {|x|
22
+ x << config_proxy.debug_ellipsis if add_last_hash_ellipsis
23
+ }
24
+ end.join(", ")
25
+ printed_args << other_args_string if other_args_string
26
+ printed_args << ", " if !other_args_string.empty? && !last_hash_args_string.empty?
27
+ printed_args << last_hash_args_string if last_hash_args_string
28
+ else
29
+ 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)]
30
+ printed_args << config_proxy.debug_ellipsis if add_args_ellipsis
31
+ 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)]
32
+ printed_args << config_proxy.debug_ellipsis if add_last_hash_ellipsis
33
+ end
12
34
  else
13
- printed_args = debug_last_hash_to_s_proc.call(args[0]).tap {|x| add_last_hash_ellipsis = x.length > debug_last_hash_max_length}[0..(debug_last_hash_max_length)]
14
- printed_args << debug_ellipsis if add_last_hash_ellipsis
35
+ 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)]
36
+ printed_args << config_proxy.debug_ellipsis if add_last_hash_ellipsis
15
37
  end
16
38
  else
17
- add_args_ellipsis = false
18
39
  if args.length == 1 && args[0].is_a?(Hash)
19
40
  # handle double splat
20
- printed_args = ("**" << args.map {|x| x.inspect}.join(", ").tap {|x| add_args_ellipsis = x.length > debug_args_max_length})[0..(debug_args_max_length)]
41
+ 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)]
21
42
  else
22
- printed_args = args.map {|x| x.inspect}.join(", ").tap {|x| add_args_ellipsis = x.length > debug_args_max_length}[0..(debug_args_max_length)]
43
+ 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)]
23
44
  end
24
- printed_args << debug_ellipsis if add_args_ellipsis
45
+ printed_args << config_proxy.debug_ellipsis if add_args_ellipsis
25
46
  end
26
47
  "(#{printed_args})"
27
48
  end
@@ -1,16 +1,27 @@
1
1
  module DebugLogging
2
2
  module ClassLogger
3
3
  def logged(*methods_to_log)
4
+ opts = methods_to_log.last.is_a?(Hash) && methods_to_log.pop
5
+ if methods_to_log.first.is_a?(Array)
6
+ methods_to_log = methods_to_log.shift
7
+ else
8
+ # logged :meth1, :meth2, :meth3 is valid
9
+ end
4
10
  methods_to_log.each do |method_to_log|
5
11
  # method name must be a symbol
6
12
  method_to_log = method_to_log.to_sym
7
13
  original_method = method(method_to_log)
8
14
  (class << self; self; end).class_eval do
9
15
  define_method(method_to_log) do |*args|
16
+ config_proxy = if opts
17
+ Configuration.new(**(debug_config.to_hash.merge(opts)))
18
+ else
19
+ self
20
+ end
10
21
  method_return_value = nil
11
- invocation_id = " ~#{args.object_id}@#{Time.now.to_i}~" if debug_add_invocation_id
12
- debug_log "#{self}.#{method_to_log}#{debug_arguments_to_s(args)}#{invocation_id}"
13
- if debug_class_benchmarks
22
+ invocation_id = " ~#{args.object_id}@#{Time.now.to_i}~" if config_proxy.debug_add_invocation_id
23
+ debug_log "#{self}.#{method_to_log}#{debug_arguments_to_s(args: args, config_proxy: config_proxy)}#{invocation_id}"
24
+ if config_proxy.debug_class_benchmarks
14
25
  elapsed = Benchmark.realtime do
15
26
  method_return_value = original_method.call(*args)
16
27
  end
@@ -1,7 +1,9 @@
1
1
  module DebugLogging
2
2
  class Configuration
3
+ DEFAULT_ELLIPSIS = " ✂️ …".freeze
3
4
  attr_accessor :logger
4
5
  attr_accessor :log_level
6
+ attr_accessor :multiple_last_hashes
5
7
  attr_accessor :last_hash_to_s_proc
6
8
  attr_accessor :last_hash_max_length
7
9
  attr_accessor :args_max_length
@@ -9,16 +11,45 @@ module DebugLogging
9
11
  attr_accessor :class_benchmarks
10
12
  attr_accessor :add_invocation_id
11
13
  attr_accessor :ellipsis
12
- def initialize
13
- @logger = Logger.new(STDOUT)
14
- @log_level = :debug
15
- @last_hash_to_s_proc = nil
16
- @last_hash_max_length = 1_000
17
- @args_max_length = 1_000
18
- @instance_benchmarks = false
19
- @class_benchmarks = false
20
- @add_invocation_id = true
21
- @ellipsis = " ✂️ …".freeze
14
+ # alias the readers to the debug_* prefix so an instance of this class
15
+ # can have the same API granted by `extend DebugLogging`
16
+ #
17
+ # include DebugLogging::InstanceLogger.new(
18
+ # i_methods: [:drive, :stop],
19
+ # config: {
20
+ # logger: Logger.new(STDOUT) # probably want to override to be the Rails.logger
21
+ # log_level: :debug # at what level do the messages created by this gem sent at?
22
+ # last_hash_to_s_proc: nil # e.g. ->(hash) { "keys: #{hash.keys}" }
23
+ # last_hash_max_length: 1_000
24
+ # args_max_length: 1_000
25
+ # instance_benchmarks: false
26
+ # class_benchmarks: false
27
+ # add_invocation_id: true # invocation id allows you to identify a method call uniquely in a log
28
+ # ellipsis: " ✂️ …".freeze
29
+ # }
30
+ # )
31
+ #
32
+ alias :debug_logger :logger
33
+ alias :debug_log_level :log_level
34
+ alias :debug_multiple_last_hashes :multiple_last_hashes
35
+ alias :debug_last_hash_to_s_proc :last_hash_to_s_proc
36
+ alias :debug_last_hash_max_length :last_hash_max_length
37
+ alias :debug_args_max_length :args_max_length
38
+ alias :debug_instance_benchmarks :instance_benchmarks
39
+ alias :debug_class_benchmarks :class_benchmarks
40
+ alias :debug_add_invocation_id :add_invocation_id
41
+ alias :debug_ellipsis :ellipsis
42
+ def initialize(**options)
43
+ @logger = options.key?(:logger) ? options[:logger] : Logger.new(STDOUT)
44
+ @log_level = options.key?(:log_level) ? options[:log_level] : :debug
45
+ @multiple_last_hashes = options.key?(:multiple_last_hashes) ? options[:multiple_last_hashes] : false
46
+ @last_hash_to_s_proc = options.key?(:last_hash_to_s_proc) ? options[:last_hash_to_s_proc] : nil
47
+ @last_hash_max_length = options.key?(:last_hash_max_length) ? options[:last_hash_max_length] : 1_000
48
+ @args_max_length = options.key?(:args_max_length) ? options[:args_max_length] : 1_000
49
+ @instance_benchmarks = options.key?(:instance_benchmarks) ? options[:instance_benchmarks] : false
50
+ @class_benchmarks = options.key?(:class_benchmarks) ? options[:class_benchmarks] : false
51
+ @add_invocation_id = options.key?(:add_invocation_id) ? options[:add_invocation_id] : true
52
+ @ellipsis = options.key?(:ellipsis) ? options[:ellipsis] : DEFAULT_ELLIPSIS
22
53
  end
23
54
  def instance_benchmarks=(instance_benchmarks)
24
55
  require "benchmark" if instance_benchmarks
@@ -28,5 +59,19 @@ module DebugLogging
28
59
  require "benchmark" if class_benchmarks
29
60
  @class_benchmarks = class_benchmarks
30
61
  end
62
+ def to_hash
63
+ {
64
+ logger: logger,
65
+ log_level: log_level,
66
+ multiple_last_hashes: multiple_last_hashes,
67
+ last_hash_to_s_proc: last_hash_to_s_proc,
68
+ last_hash_max_length: last_hash_max_length,
69
+ args_max_length: args_max_length,
70
+ instance_benchmarks: instance_benchmarks,
71
+ class_benchmarks: class_benchmarks,
72
+ add_invocation_id: add_invocation_id,
73
+ ellipsis: ellipsis
74
+ }
75
+ end
31
76
  end
32
77
  end
@@ -1,14 +1,14 @@
1
1
  module DebugLogging
2
2
  class InstanceLogger < Module
3
- def initialize(i_methods: nil)
3
+ def initialize(i_methods: nil, config: nil)
4
+ @config = config
4
5
  @instance_methods_to_log = Array(i_methods) if i_methods
5
6
  end
6
7
  def included(base)
7
- if @instance_methods_to_log
8
- base.send(:include, ArgumentPrinter)
9
- instance_method_logger = DebugLogging::InstanceLoggerModulizer.to_mod(@instance_methods_to_log)
10
- base.send(:prepend, instance_method_logger)
11
- end
8
+ return unless @instance_methods_to_log
9
+ base.send(:include, ArgumentPrinter)
10
+ instance_method_logger = DebugLogging::InstanceLoggerModulizer.to_mod(methods_to_log: @instance_methods_to_log, config_proxy: @config)
11
+ base.send(:prepend, instance_method_logger)
12
12
  end
13
13
  end
14
14
  end
@@ -1,18 +1,24 @@
1
1
  module DebugLogging
2
2
  module InstanceLoggerModulizer
3
- def self.to_mod(methods_to_log = [])
3
+ def self.to_mod(methods_to_log: nil, config_proxy: nil)
4
4
  Module.new do
5
5
  Array(methods_to_log).each do |method_to_log|
6
6
  # method name must be a symbol
7
7
  define_method(method_to_log.to_sym) do |*args, &block|
8
+ config_proxy = if config_proxy.is_a?(Hash)
9
+ Configuration.new(**(self.class.debug_config.to_hash.merge(config_proxy)))
10
+ else
11
+ self.class
12
+ end
8
13
  method_return_value = nil
9
- invocation_id = " ~#{args.object_id}@#{Time.now.to_i}~" if self.class.debug_add_invocation_id && args
10
- self.class.debug_log "#{self.class}##{method_to_log}#{self.class.debug_arguments_to_s(args)}#{invocation_id}"
11
- if self.class.debug_instance_benchmarks
14
+ log_prefix = "#{self.class}##{method_to_log}"
15
+ invocation_id = " ~#{args.object_id}@#{Time.now.to_i}~" if config_proxy.debug_add_invocation_id && args
16
+ self.class.debug_log "#{log_prefix}#{self.class.debug_arguments_to_s(args: args, config_proxy: config_proxy)}#{invocation_id}"
17
+ if config_proxy.debug_instance_benchmarks
12
18
  elapsed = Benchmark.realtime do
13
19
  method_return_value = super(*args, &block)
14
20
  end
15
- self.class.debug_log "#{self.class}##{method_to_log} completed in #{sprintf("%f", elapsed)}s#{invocation_id}"
21
+ self.class.debug_log "#{log_prefix} completed in #{sprintf("%f", elapsed)}s#{invocation_id}"
16
22
  else
17
23
  method_return_value = super(*args, &block)
18
24
  end
@@ -1,3 +1,3 @@
1
1
  module DebugLogging
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
data/lib/debug_logging.rb CHANGED
@@ -62,6 +62,12 @@ module DebugLogging
62
62
  debug_logger.send(debug_log_level, message)
63
63
  end
64
64
 
65
+ # There are times when the class will need access to the configuration object,
66
+ # such as to override it per instance method
67
+ def debug_config
68
+ @debug_logging_configuration
69
+ end
70
+
65
71
  # For single statement global config in an initializer
66
72
  # e.g. DebugLogging.configuration.ellipsis = "..."
67
73
  def self.configuration
@@ -98,6 +104,12 @@ module DebugLogging
98
104
  def debug_log_level=(log_level)
99
105
  @debug_logging_configuration.log_level = log_level
100
106
  end
107
+ def debug_multiple_last_hashes
108
+ @debug_logging_configuration.multiple_last_hashes
109
+ end
110
+ def debug_multiple_last_hashes=(multiple_last_hashes)
111
+ @debug_logging_configuration.multiple_last_hashes = multiple_last_hashes
112
+ end
101
113
  def debug_last_hash_to_s_proc
102
114
  @debug_logging_configuration.last_hash_to_s_proc
103
115
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: debug_logging
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Boling
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-26 00:00:00.000000000 Z
11
+ date: 2017-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec-pending_for
@@ -124,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  version: '0'
125
125
  requirements: []
126
126
  rubyforge_project:
127
- rubygems_version: 2.6.8
127
+ rubygems_version: 2.6.11
128
128
  signing_key:
129
129
  specification_version: 4
130
130
  summary: Drop-in debug logging useful when a call stack gets unruly