object_tracker 2.0.0 → 2.1.0
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 +4 -4
- data/lib/object_tracker.rb +82 -42
- data/lib/object_tracker/log_formatter.rb +9 -0
- data/lib/object_tracker/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3fc6c464b675df1affa9690508114fb9ac137606
|
4
|
+
data.tar.gz: f8a2e38b99381cab9cd899670bad36d3d14fab7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1518da9f3f6c230a8caf600a6b6cc7403625a57bb0b2ad58d64d39cfc0d51d1ca48909ba957ab083bcb2e33b8be16130e06e75283b9e4bd05fd2f45c5d3f7c5b
|
7
|
+
data.tar.gz: 2dd55ed1e2aa7d4e96f4a5d86e0fa7dc37a21de24ed4c5c0e1931ff130dfb766bda5d784f345d740256294d9003cd133d1cd97b370ee4b063d19cafad9903ad0
|
data/lib/object_tracker.rb
CHANGED
@@ -1,19 +1,29 @@
|
|
1
|
+
require 'logger'
|
1
2
|
require 'benchmark'
|
2
3
|
require 'object_tracker/version'
|
3
4
|
|
4
5
|
module ObjectTracker
|
5
6
|
autoload :TrackerMethod, 'object_tracker/tracker_method'
|
7
|
+
autoload :LogFormatter, 'object_tracker/log_formatter'
|
6
8
|
|
7
9
|
# @param method_names [Array<Symbol>] method names to track
|
8
10
|
# @option :except [Array<Symbol>] method names to NOT track
|
9
|
-
# @option :before [Proc] proc to call before method execution (e.g. ->(
|
10
|
-
# @option :after [Proc] proc to call after method execution (e.g. ->(
|
11
|
+
# @option :before [Proc] proc to call before method execution (e.g. ->(name, context, args) {})
|
12
|
+
# @option :after [Proc] proc to call after method execution (e.g. ->(name, context, args, duration) {})
|
11
13
|
def track_all!(method_names = [], **options)
|
12
14
|
ObjectTracker.(self, method_names, **options)
|
13
15
|
self
|
14
16
|
end
|
15
17
|
|
16
18
|
class << self
|
19
|
+
attr_writer :logger
|
20
|
+
|
21
|
+
def logger
|
22
|
+
@logger ||= Logger.new(STDOUT).tap do |config|
|
23
|
+
config.formatter = LogFormatter.new
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
17
27
|
def reserved_tracker_methods
|
18
28
|
@__reserved_methods ||= begin
|
19
29
|
names = [:__send__]
|
@@ -32,94 +42,124 @@ module ObjectTracker
|
|
32
42
|
# @param obj [Object] class or instance to track
|
33
43
|
# @param method_names [Array<Symbol>] method names to track
|
34
44
|
# @option :except [Array<Symbol>] method names to NOT track
|
35
|
-
# @option :before [Proc] proc to call before method execution (e.g. ->(
|
36
|
-
# @option :after [Proc] proc to call after method execution (e.g. ->(
|
45
|
+
# @option :before [Proc] proc to call before method execution (e.g. ->(name, context, args) {})
|
46
|
+
# @option :after [Proc] proc to call after method execution (e.g. ->(name, context, args, duration) {})
|
37
47
|
def self.call(obj, method_names = [], except: [], **options)
|
38
|
-
class_methods =
|
39
|
-
|
40
|
-
reserved = obj.respond_to?(:reserved_tracker_methods) ? obj.reserved_tracker_methods : ObjectTracker.reserved_tracker_methods
|
41
|
-
obj_instance = obj.respond_to?(:allocate) ? obj.allocate : obj
|
42
|
-
if Array(method_names).any?
|
43
|
-
Array(method_names).each do |method_name|
|
44
|
-
if obj.methods.include?(method_name)
|
45
|
-
class_methods << TrackerMethod.new(obj, method_name)
|
46
|
-
elsif obj.respond_to?(:instance_method)
|
47
|
-
inst_methods << TrackerMethod.new(obj_instance, method_name)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
else
|
51
|
-
if obj.respond_to?(:instance_methods)
|
52
|
-
(obj.instance_methods - reserved - Array(except)).each do |method_name|
|
53
|
-
inst_methods << TrackerMethod.new(obj_instance, method_name)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
(obj.methods - reserved - Array(except)).each do |method_name|
|
57
|
-
class_methods << TrackerMethod.new(obj, method_name)
|
58
|
-
end
|
59
|
-
end
|
48
|
+
class_methods, inst_methods = ObjectTracker.build_tracker_methods(obj, method_names, except: except)
|
49
|
+
name = obj.to_s
|
60
50
|
obj.send :extend, ObjectTracker.define_tracker_mod(obj, :TrackerExt, ObjectTracker.build_tracker_mod(class_methods, options))
|
61
51
|
if inst_methods.any?
|
62
|
-
|
52
|
+
# Silence all the noise about comparing class name and checking object behavior
|
53
|
+
ObjectTracker.with_error_logging do
|
54
|
+
obj.send :prepend, ObjectTracker.define_tracker_mod(obj, :InstanceTrackerExt, ObjectTracker.build_tracker_mod(inst_methods, options))
|
55
|
+
end
|
63
56
|
end
|
57
|
+
logger.info { "following #{name}" }
|
64
58
|
obj
|
65
59
|
end
|
66
60
|
|
67
61
|
def self.define_tracker_mod(context, name, mod)
|
68
62
|
context = context.class unless context.respond_to?(:const_set)
|
63
|
+
if context.const_defined?(name, false)
|
64
|
+
context.send :remove_const, name
|
65
|
+
end
|
69
66
|
context.const_set name, mod
|
70
67
|
end
|
71
68
|
|
72
69
|
# @param trackers [Array<TrackerMethod>]
|
73
70
|
# @option :mod [Module] module to add tracking to, will be mixed into self
|
74
|
-
# @option :before [Proc] proc to call before method execution (e.g. ->(
|
75
|
-
# @option :after [Proc] proc to call after method execution (e.g. ->(
|
71
|
+
# @option :before [Proc] proc to call before method execution (e.g. ->(name, context, args) {})
|
72
|
+
# @option :after [Proc] proc to call after method execution (e.g. ->(name, context, args, duration) {})
|
76
73
|
def self.build_tracker_mod(trackers, mod: Module.new, before: nil, after: nil)
|
77
74
|
ObjectTracker.tracker_hooks[:before] << before if before
|
78
75
|
ObjectTracker.tracker_hooks[:after] << after if after
|
79
76
|
Array(trackers).each do |tracker|
|
80
77
|
mod.module_eval <<-RUBY, __FILE__, __LINE__
|
81
78
|
def #{tracker.name}(*args)
|
82
|
-
ObjectTracker.call_tracker_hooks(:before, "#{tracker.display_name}", self,
|
83
|
-
result, message = ObjectTracker.call_with_tracking("#{tracker.display_name}", args, "#{tracker.source}") { super }
|
84
|
-
|
79
|
+
ObjectTracker.call_tracker_hooks(:before, "#{tracker.display_name}", self, args)
|
80
|
+
result, message, duration = ObjectTracker.call_with_tracking("#{tracker.display_name}", args, "#{tracker.source}") { super }
|
81
|
+
ObjectTracker.logger.debug { message + " (%.5f)" % duration }
|
85
82
|
result
|
86
83
|
ensure
|
87
|
-
ObjectTracker.call_tracker_hooks(:after, "#{tracker.display_name}", self,
|
84
|
+
ObjectTracker.call_tracker_hooks(:after, "#{tracker.display_name}", self, args, duration)
|
88
85
|
end
|
89
86
|
RUBY
|
90
87
|
end
|
91
88
|
mod
|
92
89
|
end
|
93
90
|
|
91
|
+
#
|
92
|
+
# Private
|
93
|
+
#
|
94
|
+
|
95
|
+
def self.build_tracker_methods(obj, method_names, except: [])
|
96
|
+
class_methods, inst_methods = [], []
|
97
|
+
reserved = obj.respond_to?(:reserved_tracker_methods) ? obj.reserved_tracker_methods : ObjectTracker.reserved_tracker_methods
|
98
|
+
obj_instance = obj.respond_to?(:allocate) ? obj.allocate : obj
|
99
|
+
if Array(method_names).any?
|
100
|
+
Array(method_names).each do |method_name|
|
101
|
+
if obj.methods.include?(method_name)
|
102
|
+
class_methods << TrackerMethod.new(obj, method_name)
|
103
|
+
elsif obj.respond_to?(:instance_method)
|
104
|
+
inst_methods << TrackerMethod.new(obj_instance, method_name)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
else
|
108
|
+
if obj.respond_to?(:instance_methods)
|
109
|
+
(obj.instance_methods - reserved - Array(except)).each do |method_name|
|
110
|
+
inst_methods << TrackerMethod.new(obj_instance, method_name)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
(obj.methods - reserved - Array(except)).each do |method_name|
|
114
|
+
class_methods << TrackerMethod.new(obj, method_name)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
return class_methods, inst_methods
|
118
|
+
end
|
119
|
+
|
94
120
|
# @note If we don't rescue, watch out for segfaults o.0
|
95
|
-
def self.call_tracker_hooks(key, method_name, context,
|
121
|
+
def self.call_tracker_hooks(key, method_name, context, args, duration = nil)
|
96
122
|
tracker_hooks[key].each do |hook|
|
97
|
-
|
123
|
+
begin
|
124
|
+
if duration
|
125
|
+
hook.call(context, method_name, args, duration)
|
126
|
+
else
|
127
|
+
hook.call(context, method_name, args)
|
128
|
+
end
|
129
|
+
rescue Exception
|
130
|
+
next
|
131
|
+
end
|
98
132
|
end
|
99
133
|
end
|
100
134
|
|
101
|
-
def self.call_with_tracking(
|
135
|
+
def self.call_with_tracking(msg, args, source)
|
102
136
|
result = nil
|
103
|
-
msg
|
104
|
-
msg
|
105
|
-
msg << "[#{source}]"
|
137
|
+
msg += ObjectTracker.format_args(args) unless args.empty?
|
138
|
+
msg += " [#{source}]"
|
106
139
|
bm = Benchmark.measure do
|
107
140
|
result = yield rescue nil
|
108
141
|
end
|
109
|
-
[result, msg
|
142
|
+
[result, msg, bm.real]
|
110
143
|
end
|
111
144
|
|
112
145
|
def self.format_args(args)
|
113
|
-
result = "["
|
146
|
+
result = " with ["
|
114
147
|
args.each do |arg|
|
115
148
|
result << (arg ? arg.to_s : "nil")
|
116
149
|
result << ", "
|
117
150
|
end
|
118
151
|
result.sub! /,\s\z/, ""
|
119
|
-
result << "]
|
152
|
+
result << "]"
|
120
153
|
end
|
121
154
|
|
122
155
|
def self.tracker_hooks
|
123
156
|
@__tracker_hooks ||= Hash.new { |me, key| me[key] = [] }
|
124
157
|
end
|
158
|
+
|
159
|
+
def self.with_error_logging
|
160
|
+
old_log_level, logger.level = logger.level, Logger::ERROR
|
161
|
+
yield
|
162
|
+
ensure
|
163
|
+
logger.level = old_log_level if old_log_level
|
164
|
+
end
|
125
165
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: object_tracker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Buckley
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -47,6 +47,7 @@ extensions: []
|
|
47
47
|
extra_rdoc_files: []
|
48
48
|
files:
|
49
49
|
- lib/object_tracker.rb
|
50
|
+
- lib/object_tracker/log_formatter.rb
|
50
51
|
- lib/object_tracker/tracker_method.rb
|
51
52
|
- lib/object_tracker/version.rb
|
52
53
|
- object_tracker.gemspec
|