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

I meant *add* the underscore...

Iain

···

On 1 Dec 2010, at 14:48, Iain Barnett wrote:

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

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
    "<BreadBox slices=#{@slices}>"
  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 # => "<BreadBox slices=9>"

# >> LOGGING: 'insert' RECEIVED [5] WITHOUT A BLOCK
# >> LOGGING: 'insert' RECEIVED [7] WITHOUT A BLOCK
# >> LOGGING: 'to_s' RECEIVED WITHOUT A BLOCK

···

On Wed, Dec 1, 2010 at 8:48 AM, Iain Barnett <iainspeed@gmail.com> wrote:

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

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

···

On Wed, Dec 1, 2010 at 6:48 AM, Iain Barnett <iainspeed@gmail.com> wrote:

Is it crazy?

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

Regards,
Iain