Cutting down on logging statements

Hi,

As hacky ideas go, how does this sound? My code is peppered with logging
statements which I’d rather not wade through, so maybe I could define
all my methods with a leading underscore but call them without e.g.

def _my_method…

@n = my_method @a, @b, @c

and use method missing to wrap all the calls with logging and then
remove the underscore and recall the method.

I tried using the Aquarius lib but it didn’t work for me, so this is my
crazy idea for the day. Aside from putting all my money into buying
government debt.

Is it crazy?

Regards,
Iain

On 1 Dec 2010, at 14:48, Iain B. wrote:

and use method missing to wrap all the calls with logging and then remove the
underscore and recall the method.

I meant add the underscore…

Iain

On Wed, Dec 1, 2010 at 8:48 AM, Iain B. [email protected]
wrote:

and use method missing to wrap all the calls with logging and then remove

I’m not especially keen on method_missing, it seems difficult to
diagnose
when it has issues, and I always worry about it colliding with other
method_missings. It would also mean you’d have to hack respond_to as
well
(if you want to play nice, anyway). And it means you can’t override
methods,
for example:

class MyClass
def _foo(arg)
end
def to_s
“you will never see me”
end
def method_missing(meth,*args,&block)
if respond_to?("
#{meth}")
puts “LOGGING: ‘#{meth}’ RECEIVED #{args.inspect} WITH#{‘OUT’
unless
block} A BLOCK”
else
super
end
end
end

m = MyClass.new
m.foo(:bar) { }
puts m.to_s

>> LOGGING: ‘foo’ RECEIVED [:bar] WITH A BLOCK

>> #MyClass:0x0000010086ca80

Here is a different way, which allows you to exert a bit more control.
Note
that this won’t work on 1.8.6. Some other things you could do would be
to
have it hook into a callback so you can customize the logging for each
class, or even each method that uses it; or to allow additional args to
loggable method, which would then be the custom message (ie priority and
message).

alias :log :puts

module Loggable

def loggable( meth , &block )
define_actual meth , &block
define_loggable meth
end

def define_actual( meth , &block )
define_method “_#{meth}” , &block
end

def define_loggable(meth)
define_method meth do |*args,&block|
log “LOGGING: ‘#{meth}’ RECEIVED #{args.inspect} WITH#{‘OUT’
unless
block} A BLOCK”
send “_#{meth}” , *args , &block
end
end

end

class BreadBox

extend Loggable

def initialize
@slices = 0
end

a logging method

loggable :insert do |n|
@slices += n
end

a non-logging method

def remove(n)
@slices -= n
end

can log overridden methods

loggable :to_s do
“”
end

end

box = BreadBox.new
BreadBox.instance_methods(false) # => [:_insert, :insert, :remove,
:_to_s,
:to_s]
box.respond_to? :insert # => true
box.insert 5 # => 5
box.remove 3 # => 2
box.insert 7 # => 9
box.to_s # => “”

>> LOGGING: ‘insert’ RECEIVED [5] WITHOUT A BLOCK

>> LOGGING: ‘insert’ RECEIVED [7] WITHOUT A BLOCK

>> LOGGING: ‘to_s’ RECEIVED [] WITHOUT A BLOCK

Thanks Josh and Ben, I’ll peruse the code and the article and see what
fits best. Interesting stuff.

Regards,
Iain

On Wed, Dec 1, 2010 at 6:48 AM, Iain B. [email protected]
wrote:

Is it crazy?

Not… exactly.

If what you’re trying to accomplish is logging when a method is
entered, you may want to consider Kernel#set_trace_func. I’m not sure
what you’re doing so I don’t know if it’s the best solution. I wrote
about it years ago:

http://blog.bleything.net/2006/12/11/tracing-method-execution

Ben