Is there a simply way to get every method log itself before

Hi,

As a Ruby nubie, every once-in-a-while I’d like to write a trace
function and have every method execute that trace when the method’s
invoked. In that trace function, I’d like to be able, e.g. to write
the invoked method’s name, perhaps more.

Is there an easy way to do that?

BTW, I posted this question on the Ruby/Rails Newsgroup before I
realized it’s more appropriate here.

Thanks in Advance,
Richard

Richard wrote:

As a Ruby nubie, every once-in-a-while I’d like to write a trace
function and have every method execute that trace when the method’s
invoked. In that trace function, I’d like to be able, e.g. to write
the invoked method’s name, perhaps more.

I believe the answer to your question (though I’ve not done it myself)
lies in set_trace_func
http://phrogz.net/ProgrammingRuby/ref_m_kernel.html#Kernel.set_trace_func

Which links to an example in:
http://phrogz.net/ProgrammingRuby/ospace.html#tracingyourprogramsexecution

hemant [email protected] writes:

Goodness, you need needle.

Wow, it’s been a long time since I last heard that sentence. :stuck_out_tongue:

On 11/25/06, Phrogz [email protected] wrote:

Which links to an example in:
Reflection, ObjectSpace, and Distributed Ruby

Goodness, you need needle.

Get it from here:

http://needle.rubyforge.org/chapter-1.html

Hi Phrogz,

Thanks for pointing me to that kernel method. I’ve got to study the
example(s) and construct a few of my own to apply it well.

Great job!

Again, thanks,
Richard

Hi Hermant,

I liked Phrogz’s suggestion about using set_trace_func/, which I’m
going to study. But right now I think Needle will get me going faster.
So I’m going to work on that first. Thank you for taking the time to
post a message about it.

I’m going to be applying this in a Rails application, so I’ve got to
figure out where the top level of the generated app is, but I think
I’ll be able to figure it out.

Best wishes,
Richard

Hi Phrogz,

There’s nothing like having working code to really get one’s head into
new software. Thanks a lot for passing it along. Looks great!

I have started play with Needles on
http://needle.rubyforge.org/chapter-1.html. I got the first example
working … only had to stick in a “requires” stmt. I’m struggling
with the 2nd example.

I’ll follow both approaches for a little while.

Best wishes,
Richard

Richard wrote:

Thanks for pointing me to that kernel method. I’ve got to study the
example(s) and construct a few of my own to apply it well.

Here’s my own example, since I’ve never played with it before:

slim:~/Desktop gavinkistner$ ruby tmp.rb
Hello, Bob
Hello, Gavin

slim:~/Desktop gavinkistner$ ruby -d tmp.rb

Person#initialize called (line 3)
<end Person#initialize>

Person#initialize called (line 3)
<end Person#initialize>

Person#greet_first called (line 9)
–Person#greet called (line 6)
Hello, Bob
–<end Person#greet>
–Person#respond called (line 13)
----Person#greet called (line 6)
Hello, Gavin
----<end Person#greet>
–<end Person#respond>
<end Person#greet_first>

Object#recurse_down called (line 18)
–Object#recurse_down called (line 18)
----Object#recurse_down called (line 18)
------Object#recurse_down called (line 18)
--------Object#recurse_down called (line 18)
----------Object#recurse_down called (line 18)
------------Object#recurse_down called (line 18)
------------<end Object#recurse_down>
----------<end Object#recurse_down>
--------<end Object#recurse_down>
------<end Object#recurse_down>
----<end Object#recurse_down>
–<end Object#recurse_down>
<end Object#recurse_down>

slim:~/Desktop gavinkistner$ cat tmp.rb
class Person
attr_reader :name
def initialize( name )
@name = name
end
def greet( someone )
puts “Hello, #{someone.name}”
end
def greet_first( someone )
greet( someone )
someone.respond( self ) # Social Obligation!
end
def respond( someone )
greet( someone )
end
end

def recurse_down( count=6 )
if count > 0
recurse_down( count-1 )
end
end

if $DEBUG
set_trace_func lambda{ |event, file, line, id, binding, classname|
$indent ||= 0

# Only deal with events that occur inside this file
return unless file == __FILE__

# Only deal with calls to my functions
case event
  when 'call'
    print $indent==0 ? "\n" : '--'*$indent
    puts "#{classname}##{id} called (line #{line})"
    $indent += 1

  when 'return'
    $indent -= 1
    print "--" * $indent
    puts "<end #{classname}##{id}>"

end

}
end

gk = Person.new( ‘Gavin’ )
bk = Person.new( ‘Bob’ )
gk.greet_first( bk )

recurse_down

Hi Richard,

Richard wrote:

I’d like to write a trace function and have every method
execute that trace when the method’s invoked. In that
trace function, I’d like to be able, e.g. to write the
invoked method’s name, perhaps more.

Is there an easy way to do that?

BTW, I posted this question on the Ruby/Rails Newsgroup
before Irealized it’s more appropriate here.

Since you mentioned Rails, I’ll assume you’re using it. If not, this
won’t apply.

Check out the Class documentation ( http://api.rubyonrails.org , left
panel, middle section) for ActionController::Filters::ClassMethods.
You’re probably looking for an after_filter given that you may want to
store some stuff you ‘compute’ in the method.

hth,
Bill

Hi Bill,

I checked out the filter, and I see that I could create
MyMainController derived from ActionController::Base and have all my
controllers subclass MyMainController. That would allow me log the
name of subcontrollers and the state of some object before any methods
of those controllers is invoked, and likewise when the controllers are
closed.

But I don’t see how I could get any of the methods of those controllers
to report that they had been invoked and subsequently terminated.

In addition, I didn’t see a corresponding mechanism for views and
helpers.

Do you agree, or is my assessment simplistic?

Regards,
Richard

Hi Bill,

Thanks for responding.

Since you mentioned Rails, I’ll assume you’re using it.
You’re right on :slight_smile:

ActionController::Filters::ClassMethods … after_filter
I’ve used the before_filter, but I never noticed the after_filter, so
it’s nice to learn about it.

Hope, as a Rails newbie, I’d like to trace through every method
invoked in a simple Rails app and display “interesting” things, e.g.
the arguments it received and the the value it returned. But I want to
make that happen in an automated way, e.g. inject my debug routines at
the entry and exit points, which is what Aspect-Oriented Program is to
make easy to accomplish.

I’ve had some help in getting set_trace_func working, but I haven’t
figured out yet whether that will do what I want. And I’ve looked at
Needle but haven’t gotten Dependency Injection even coded yet.

The holy grail for me is automated temporary transform of my Rails app.
Is there a way that an after_filter could be specified at the top
level of a Rails app and have it operate on all the subordinate
methods?

Regards,
Richard