Last active
September 26, 2017 09:30
-
-
Save pboling/b7ac04d7c44bdd638713f7e74b59ef40 to your computer and use it in GitHub Desktop.
Unobtrusive Debug Logging that examines wonders of Ruby: Module < Class; include Module.new(*args); and more!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Simpler version of what the debug_logging gem does; see https://github.com/pboling/debug_logging | |
# | |
############# THIS IS A BAUBLE | |
############# FOR EXAMINING SEVERAL OF THE WONDERS OF RUBY | |
############# TO ACCOMPLISH SOMETHING PRACTICAL | |
############# For a more robust implementation use the gem debug_logging itself, | |
############# which makes use of these same principles. | |
# | |
# Automatically log Class.method(arguments) as they are called at runtime (instance or singleton)! | |
# | |
# NOTE: For a more advanced version see the debug_logging gem | |
# NOTE: The manner this is made to work for class methods is totally different than the way this is made to work for instance methods. | |
# NOTE: The instance method manner of logging works on Ruby 2.0+ | |
# NOTE: The class method manner of logging works on Ruby 2.1+ | |
require 'benchmark' | |
class SimpleDebugLogging < Module | |
def initialize(i_methods: nil) | |
@instance_methods_to_log = Array(i_methods) if i_methods | |
end | |
def included(base) | |
instance_method_logger = InstanceMethodLoggerModulizer.to_mod(@instance_methods_to_log) | |
base.send(:prepend, instance_method_logger) | |
base.send(:extend, ClassMethodLogger) | |
end | |
module ClassMethodLogger | |
def logged(*methods_to_log) | |
methods_to_log.each do |method_to_log| | |
original_method = method(method_to_log) | |
(class << self; self; end).class_eval do | |
define_method(method_to_log.to_sym) do |*args| | |
method_return_value = nil | |
invocation_id = " ~#{args.object_id}@#{Time.now.to_i}~" if args | |
puts "#{self}.#{method_to_log}(#{args.map {|x| x.inspect}.join(", ")})#{invocation_id}" | |
elapsed = Benchmark.realtime do | |
method_return_value = original_method.call(*args) | |
end | |
puts "#{self}.#{method_to_log} ~#{args.hash}~ complete in #{elapsed}s#{invocation_id}" | |
method_return_value | |
end | |
end | |
end | |
end | |
end | |
module InstanceMethodLoggerModulizer | |
def self.to_mod(methods_to_log = []) | |
Module.new do | |
Array(methods_to_log).each do |method_to_log| | |
define_method(method_to_log.to_sym) do |*args, &block| | |
method_return_value = nil | |
invocation_id = " ~#{args.object_id}@#{Time.now.to_i}~" if args | |
puts "#{self.class}##{method_to_log}(#{args.map {|x| x.inspect}.join(", ")})#{invocation_id}" | |
elapsed = Benchmark.realtime do | |
method_return_value = super(*args, &block) | |
end | |
puts "#{self.class}##{method_to_log} ~#{args.hash}~ complete in #{elapsed}s#{invocation_id}" | |
method_return_value | |
end | |
end | |
end | |
end | |
end | |
end | |
class UnobtrusivelyLogged | |
def initialize(**args); end | |
def an_instance_method(*args); end | |
def self.a_class_method(*args); self; end | |
include SimpleDebugLogging.new(i_methods: %i( initialzie an_instance_method )) | |
logged :a_class_method | |
end | |
# Output will be something like: | |
# UnobtrusivelyLogged.a_class_method() ~70156299674920@1506415414~ | |
# UnobtrusivelyLogged.a_class_method ~689933733604307372~ complete in 8.000002708286047e-06s ~70156299674920@1506415414~ | |
# UnobtrusivelyLogged#an_instance_method() ~70156299673760@1506415414~ | |
# UnobtrusivelyLogged#an_instance_method ~689933733604307372~ complete in 2.00001522898674e-06s ~70156299673760@1506415414~ | |
UnobtrusivelyLogged.a_class_method.new.an_instance_method | |
# UnobtrusivelyLogged.a_class_method(1, 2, "a", "b") ~70124887408680@1506418201~ | |
# UnobtrusivelyLogged.a_class_method ~-1310500302753052858~ complete in 2.9999646358191967e-06s ~70124887408680@1506418201~ | |
# UnobtrusivelyLogged#an_instance_method([55, 44, 33]) ~70124896074340@1506418201~ | |
# UnobtrusivelyLogged#an_instance_method ~180398559802792504~ complete in 2.00001522898674e-06s ~70124896074340@1506418201~ | |
UnobtrusivelyLogged.a_class_method(1, 2, 'a', 'b').new(a: :b, c: :b).an_instance_method([55,44,33]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment