Module: ObjectTracker
- Defined in:
- lib/object_tracker.rb,
lib/object_tracker/version.rb,
lib/object_tracker/log_formatter.rb,
lib/object_tracker/tracker_method.rb
Defined Under Namespace
Classes: LogFormatter, TrackerMethod
Constant Summary collapse
- VERSION =
'2.1.1'.freeze
Class Attribute Summary collapse
Class Method Summary collapse
-
.build_tracker_methods(obj, method_names, except: []) ⇒ Object
Private.
- .build_tracker_mod(trackers, mod: Module.new, before: nil, after: nil) ⇒ Object
-
.call(obj, method_names = [], except: [], **options) ⇒ Object
Utilities (not extended or mixed in).
- .call_tracker_hooks(key, method_name, context, args, duration = nil) ⇒ Object
- .call_with_tracking(msg, args, source) ⇒ Object
- .define_tracker_mod(context, name, mod) ⇒ Object
- .format_args(args) ⇒ Object
- .reserved_tracker_methods ⇒ Object
- .tracker_hooks ⇒ Object
- .with_error_logging ⇒ Object
Instance Method Summary collapse
Class Attribute Details
.logger ⇒ Object
21 22 23 24 25 |
# File 'lib/object_tracker.rb', line 21 def logger @logger ||= Logger.new(STDOUT).tap do |config| config.formatter = LogFormatter.new end end |
Class Method Details
.build_tracker_methods(obj, method_names, except: []) ⇒ Object
Private
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/object_tracker.rb', line 95 def self.build_tracker_methods(obj, method_names, except: []) class_methods, inst_methods = [], [] reserved = obj.respond_to?(:reserved_tracker_methods) ? obj.reserved_tracker_methods : ObjectTracker.reserved_tracker_methods obj_instance = obj.respond_to?(:allocate) ? obj.allocate : obj if Array(method_names).any? Array(method_names).each do |method_name| if obj.methods.include?(method_name) class_methods << TrackerMethod.new(obj, method_name) elsif obj.respond_to?(:instance_method) inst_methods << TrackerMethod.new(obj_instance, method_name) end end else if obj.respond_to?(:instance_methods) (obj.instance_methods - reserved - Array(except)).each do |method_name| inst_methods << TrackerMethod.new(obj_instance, method_name) end end (obj.methods - reserved - Array(except)).each do |method_name| class_methods << TrackerMethod.new(obj, method_name) end end return class_methods, inst_methods end |
.build_tracker_mod(trackers, mod: Module.new, before: nil, after: nil) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/object_tracker.rb', line 73 def self.build_tracker_mod(trackers, mod: Module.new, before: nil, after: nil) ObjectTracker.tracker_hooks[:before] << before if before ObjectTracker.tracker_hooks[:after] << after if after Array(trackers).each do |tracker| mod.module_eval <<-RUBY, __FILE__, __LINE__ def #{tracker.name}(*args) ObjectTracker.call_tracker_hooks(:before, "#{tracker.display_name}", self, args) result, message, duration = ObjectTracker.call_with_tracking("#{tracker.display_name}", args, "#{tracker.source}") { super } ObjectTracker.logger.debug { message + " (%.5f)" % duration } result ensure ObjectTracker.call_tracker_hooks(:after, "#{tracker.display_name}", self, args, duration) end RUBY end mod end |
.call(obj, method_names = [], except: [], **options) ⇒ Object
Note:
Alias to .()
Utilities (not extended or mixed in)
Tracks method calls to the given object
47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/object_tracker.rb', line 47 def self.call(obj, method_names = [], except: [], **) class_methods, inst_methods = ObjectTracker.build_tracker_methods(obj, method_names, except: except) name = obj.to_s obj.send :extend, ObjectTracker.define_tracker_mod(obj, :TrackerExt, ObjectTracker.build_tracker_mod(class_methods, )) if inst_methods.any? # Silence all the noise about comparing class name and checking object behavior ObjectTracker.with_error_logging do obj.send :prepend, ObjectTracker.define_tracker_mod(obj, :InstanceTrackerExt, ObjectTracker.build_tracker_mod(inst_methods, )) end end logger.info { "following #{name}" } obj end |
.call_tracker_hooks(key, method_name, context, args, duration = nil) ⇒ Object
Note:
If we don’t rescue, watch out for segfaults o.0
121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/object_tracker.rb', line 121 def self.call_tracker_hooks(key, method_name, context, args, duration = nil) tracker_hooks[key].each do |hook| begin if duration hook.call(context, method_name, args, duration) else hook.call(context, method_name, args) end rescue Exception next end end end |
.call_with_tracking(msg, args, source) ⇒ Object
135 136 137 138 139 140 141 142 143 |
# File 'lib/object_tracker.rb', line 135 def self.call_with_tracking(msg, args, source) result = nil msg += ObjectTracker.format_args(args) unless args.empty? msg += " [#{source}]" bm = Benchmark.measure do result = yield rescue nil end [result, msg, bm.real] end |
.define_tracker_mod(context, name, mod) ⇒ Object
61 62 63 64 65 66 67 |
# File 'lib/object_tracker.rb', line 61 def self.define_tracker_mod(context, name, mod) context = context.class unless context.respond_to?(:const_set) if context.const_defined?(name, false) context.send :remove_const, name end context.const_set name, mod end |
.format_args(args) ⇒ Object
145 146 147 148 149 150 151 152 153 |
# File 'lib/object_tracker.rb', line 145 def self.format_args(args) result = " with [" args.each do |arg| result << (arg ? arg.to_s : "nil") result << ", " end result.sub! /,\s\z/, "" result << "]" end |
.reserved_tracker_methods ⇒ Object
27 28 29 30 31 32 33 |
# File 'lib/object_tracker.rb', line 27 def reserved_tracker_methods @__reserved_methods ||= begin names = [:__send__] names.concat [:default_scope, :current_scope=] if defined?(Rails) names end end |
.tracker_hooks ⇒ Object
155 156 157 |
# File 'lib/object_tracker.rb', line 155 def self.tracker_hooks @__tracker_hooks ||= Hash.new { |me, key| me[key] = [] } end |
.with_error_logging ⇒ Object
159 160 161 162 163 164 |
# File 'lib/object_tracker.rb', line 159 def self.with_error_logging old_log_level, logger.level = logger.level, Logger::ERROR yield ensure logger.level = old_log_level if old_log_level end |
Instance Method Details
#track_all!(method_names = [], **options) ⇒ Object
13 14 15 16 |
# File 'lib/object_tracker.rb', line 13 def track_all!(method_names = [], **) ObjectTracker.(self, method_names, **) self end |