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 +4 -4
- data/README.md +13 -2
- data/lib/debug_logging/argument_printer.rb +34 -13
- data/lib/debug_logging/class_logger.rb +14 -3
- data/lib/debug_logging/configuration.rb +55 -10
- data/lib/debug_logging/instance_logger.rb +6 -6
- data/lib/debug_logging/instance_logger_modulizer.rb +11 -5
- data/lib/debug_logging/version.rb +1 -1
- data/lib/debug_logging.rb +12 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95c155d2751e4ed8027d638174dd657f1205e009
|
4
|
+
data.tar.gz: 26c3390ea291a866f51c77b55961ae12c8439123
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
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
|
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
|
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
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 "#{
|
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
|
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.
|
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-
|
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.
|
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
|