debug_logging 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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