Skip to content

Instantly share code, notes, and snippets.

@openmailbox
Created November 28, 2014 04:09
Show Gist options
  • Save openmailbox/6e19f97e44e45576004f to your computer and use it in GitHub Desktop.
Save openmailbox/6e19f97e44e45576004f to your computer and use it in GitHub Desktop.
Experimenting with method tracing via metaprogramming in Ruby.
module MethodTracing
class Tracer
class << self
attr_reader :tracers
end
@tracers = {}
attr_accessor :count
attr_reader :target
def self.attach_to(target)
const_name, method_name = target.split('#')
const = Object.const_get(const_name)
@tracers[target] = Tracer.new(target)
const.class_eval do
if self.instance_methods.include?(method_name.to_sym)
alias_method "orig_#{method_name}".to_sym, method_name.to_sym
end
define_method(method_name) do |*args|
MethodTracing::Tracer.increment(target)
self.send("orig_#{method_name}", *args) if self.class.instance_methods.include?("orig_#{method_name}")
super(*args) if defined?(super)
end
end
rescue NameError => e
unless const
Object.class_eval do
define_singleton_method(:inherited) do |name|
Tracer.attach_to(ENV['COUNT_CALLS_TO'])
end
end
else
puts e.message
puts e.backtrace.join("\n")
end
end
def self.increment(target)
@tracers[target].count += 1
end
def initialize(target)
@count = 0
@target = target
end
end
Tracer.attach_to(ENV['COUNT_CALLS_TO'])
at_exit do
Tracer.tracers.each do |target, tracer|
puts "#{target} called #{tracer.count} times."
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment