# Using binding + set\_trace\_func to capture execution state

**URL:** <https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807>\
**Category:** ruby-talk\
**Created:** [3 July 2012 01:11 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807 "2012-07-03T01:11:11Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [3 July 2012 01:11 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/1 "2012-07-03T01:11:11Z")

</div>

Hi guys, I'm interested in building a program that will display the  
callgraph trace of a program and at the same time will allow you to  
inspect the variables in your program \*after\* the execution has ended  
(diff from using debugger to halt execution and inspecting the state).

Initially I thought I could use set\_trace\_func and store the binding in  
a table and just retrieve that binding later on to evaluate the  
resulting expression of my target variable, but it's not behaving as I  
expected. In the code provided below, I thought running it would output  
"1 3 5", but I get "5 5 5" instead.

What am I missing here? Is there another way to go about what I'm trying  
to do? Thanks!

binding\_table = {}

def hello  
&nbsp;&nbsp;x = 1  
&nbsp;&nbsp;x = 3  
&nbsp;&nbsp;x = 5  
end

set\_trace\_func proc { |event, file, line, id, binding, classname|  
&nbsp;&nbsp;if event == "line"  
&nbsp;&nbsp;&nbsp;&nbsp;binding\_table[line] = binding  
&nbsp;&nbsp;end  
}

hello

set\_trace\_func nil

puts eval("x", binding\_table[4])  
puts eval("x", binding\_table[5])  
puts eval("x", binding\_table[6])

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Peter\_Zotov](https://avatars.discourse-cdn.com/v4/letter/p/bbce88/32.png) [@Peter\_Zotov](https://rubytalk.org/u/Peter_Zotov)\
**Post date:** [3 July 2012 03:59 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/2 "2012-07-03T03:59:24Z")

</div>

Reginald Tan писал 03.07.2012 05:11:

> Hi guys, I'm interested in building a program that will display the  
> callgraph trace of a program and at the same time will allow you to  
> inspect the variables in your program \*after\* the execution has ended  
> (diff from using debugger to halt execution and inspecting the state).
> 
> Initially I thought I could use set\_trace\_func and store the binding in  
> a table and just retrieve that binding later on to evaluate the  
> resulting expression of my target variable, but it's not behaving as I  
> expected. In the code provided below, I thought running it would output  
> "1 3 5", but I get "5 5 5" instead.
> 
> What am I missing here? Is there another way to go about what I'm trying  
> to do? Thanks!
> 
> binding\_table = {}
> 
> def hello  
> &nbsp;&nbsp;x = 1  
> &nbsp;&nbsp;x = 3  
> &nbsp;&nbsp;x = 5  
> end
> 
> set\_trace\_func proc { |event, file, line, id, binding, classname|  
> &nbsp;&nbsp;if event == "line"  
> &nbsp;&nbsp;&nbsp;&nbsp;binding\_table[line] = binding  
> &nbsp;&nbsp;end  
> }
> 
> hello
> 
> set\_trace\_func nil
> 
> puts eval("x", binding\_table[4])  
> puts eval("x", binding\_table[5])  
> puts eval("x", binding\_table[6])

Oh, it's very simple. The `binding' object denotes the variable scope. The  
scope doesn't change in this case; the values do.

You can think of a Binding this way (long story short, it's implemented  
\_very roughly\_ like that in Rubinius):

class Binding  
&nbsp;&nbsp;&nbsp;attr\_accessor :locals

&nbsp;&nbsp;&nbsp;def initialize  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@locals = {}  
&nbsp;&nbsp;&nbsp;end  
end

... and of variable access this way:

def func  
&nbsp;&nbsp;&nbsp;binding.locals[:x] = 1 # x = 1  
&nbsp;&nbsp;&nbsp;p binding.locals[:x] # p x  
&nbsp;&nbsp;&nbsp;binding.locals[:x] = 2 # x = 2  
end

Now the answer should be obvious.

To achieve your goal you'd need to copy the state of variables at each  
tracefunc invocation. Even worse, as the objects themselves may change,  
you will need to do a deep copy each time (otherwise you'll pluck into  
exactly the same problem with object instance variables). I would suggest  
marshalling the objects and writing them to something like tmpfs, then  
using a special tool to navigate the captured information.

This is going to consume a lot of memory. I repeat: a lot. Like tens  
of gigabytes for a complex thing like... Sinatra. And probably terabytes  
for Rails.

> **···**
>
> --  
> &nbsp;&nbsp;&nbsp;WBR, Peter Zotov.

---

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [10 September 2012 19:55 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/3 "2012-09-10T19:55:19Z")

</div>

Reginald,

Have you made any progress with this?

I've been wanting to do a similar thing, so I'm curious how far you've  
gotten. I have a rough prototype that uses set\_trace\_func to get the  
local\_variables and their values. Instead of storing the binding, I'm  
just outputting the variables I care about within my set\_trace\_func  
proc. I'm just using #inspect now, but I suppose any view would do.

To alleviate the problem of too much data, I'm simply whitelisting the  
exact methods that I care about exploring. I'm not worrying too much  
about this right now.

Also, I've found the class, method, and line number of set\_trace\_func to  
be useful. I've found that the line number matches the line number in  
Ripper's s-expression output. I don't know if this is the case in  
general, but it's worked in my proof of concept so far. Combined with  
the binding and local\_variables, I can then display the source being  
executed with values substituted for variables.

That's as far as I've gotten. It's very rough and doesn't handle a lot  
of parses yet, but honestly, my biggest unknown now is how to present  
the information to the user in a way he/she can interact with it.

I'd love to hear any thoughts or ideas of a better way to accomplish  
this!

Jon

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [11 September 2012 20:22 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/4 "2012-09-11T20:22:26Z")

</div>

I'm trying to avoid stepping through the code line by line. I'd like to  
get a big-picture view if possible. Also, similar to the OP, I don't  
want to modify the code being inspected either.

Trying to boil it down to my main "feature" I'm trying to implement, I  
think it's removing all intermediate steps between writing code and  
seeing its output. But not just its output -- also how it got there.  
Also, I personally find it tedious to navigate with the keyboard and  
type the variable names I want to inspect in the exact spot I want to  
inspect them. So I want to be able to avoid that. I'd much rather have  
some kind of overlay on top of my source that I can just glance at or  
maybe mouse-over.

With current tools, my co-workers and I end up using things like  
autotest or guard to detect when a file is saved and then re-run the  
tests. The test output is displayed in a terminal, optionally reported  
to Growl. When it gets slow loading all those gem dependencies, we use  
spork.

This is all fine. I can edit files. I can point my Gemfile to a dir with  
:path and add debugger/pry breakpoints or prints, or even edit the  
installed gem if needed. I can inspect any value. I just feel it's  
inconvenient. For one, I have to be sure to remove all the breakpoints  
b/c they should never make it to production, but there are other issues.  
So I thought I'd try to experiment with something else.

This may not be for everyone, but I feel that my ideal development  
workflow needs continual evaluation and to reflect the source code back  
to me with test values filled in. It doesn't need to capture all the  
data of all the execution flow. As someone pointed out, that would be a  
lot of data, and not very useful.

Also, a test (unit, functional, etc.) will print out a bad value that is  
asserted. However, I specifically avoid assertions on intermediate  
values which are implementation-dependent, because they make tests  
brittle. But these intermediate values are often very useful in fixing  
the final result. So I'd like to be able to easily \*see\* the  
intermediate values without having to manually add and remove inspects  
or step through the debugger every time.

Anyway, I know it helps to understand a person's context and motivation  
when helping them. So that's mine. It's more of a hunch of what I think  
might be useful. And I'm trying to make it to find out for sure.

I obviously don't want to re-implement the Ruby interpreter, and I'd  
like to avoid patching it. So when I found set\_trace\_func, it seemed to  
be a good match. However, it calls your proc with file and line number.  
This may be fine for a traditional debugger that simply echoes back your  
source as a string. But I want to actually parse the code so that I can  
do interesting things with it. set\_trace\_func's "line" event doesn't map  
perfectly to the parsed AST. The most recent case I've run into is an  
if-else-end statement that spans multiple lines but is used as an  
expression to assign to a variable.

1: result = if some\_true\_val  
2: 'yes'  
3: else  
4: 'no'  
5: end  
6: puts result

I think set\_trace\_func is giving me one "line" event for line 1, then  
line 2, then line 6. However, according to the actual AST, the  
assignment is on line 1, and necessarily must occur \*after\* executing  
line 2. This is what I mean by saying that they don't map perfectly. For  
my experiment, this mapping is what the majority of the code deals with.

As for the actual UI, I've considered using MacRuby. But I've found that  
MacRuby doesn't support set\_trace\_func. So maybe this is the wrong route  
to head down.

Anyway, if the OP isn't listening, I don't really have a specific  
question for the mailing list. ...Except maybe this:

Is anyone working on a "Light Table" for Ruby?

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [3 July 2012 06:05 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/5 "2012-07-03T06:05:09Z")

</div>

> To achieve your goal you'd need to copy the state of variables at each  
> tracefunc invocation. Even worse, as the objects themselves may change,  
> you will need to do a deep copy each time (otherwise you'll pluck into  
> exactly the same problem with object instance variables). I would  
> suggest  
> marshalling the objects and writing them to something like tmpfs, then  
> using a special tool to navigate the captured information.
> 
> This is going to consume a lot of memory. I repeat: a lot. Like tens  
> of gigabytes for a complex thing like... Sinatra. And probably  
> terabytes  
> for Rails.

Hmm, you're right, it would not be efficient at all to store all those  
variables especially in a large program.

I guess another possible approach is to rerun the program every time i  
want to inspect a variable. Since I know which file and line the  
variable is, I can use that as a condition on set\_trace\_func handler on  
when to output that variable.

set\_trace\_func proc { |event, file, line, id, binding, classname|  
&nbsp;&nbsp;if event == "line" && file == "myfile.rb" && line == 4  
&nbsp;&nbsp;&nbsp;&nbsp;puts eval("@myvar", binding)  
&nbsp;&nbsp;end  
}

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![11142](https://avatars.discourse-cdn.com/v4/letter/1/e0b2c6/32.png) [@11142](https://rubytalk.org/u/11142)\
**Post date:** [3 July 2012 11:23 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/6 "2012-07-03T11:23:01Z")

</div>

Have you tried somehow using continuations?

[http://www.ruby-doc.org/core-1.9.3/Continuation.html](http://www.ruby-doc.org/core-1.9.3/Continuation.html)

-- Matma Rex

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [11 September 2012 08:37 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/7 "2012-09-11T08:37:57Z")

</div>

You could throw out a prompt. Maybe IRB can help you with that. But  
then again, why not use the debugger? Note that the OP's goal was  
different: he wanted to present the state after the execution. For  
that simply dumping state during execution might be sufficient. But  
what you are trying to to sounds more like debugging (interaction  
after the program has finished does not make much sense I guess).

Kind regards

robert

> **···**
>
> On Mon, Sep 10, 2012 at 9:55 PM, Jonathan Tran \<lists@ruby-forum.com\> wrote:
> 
> > That's as far as I've gotten. It's very rough and doesn't handle a lot  
> > of parses yet, but honestly, my biggest unknown now is how to present  
> > the information to the user in a way he/she can interact with it.
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [12 September 2012 09:00 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/8 "2012-09-12T09:00:28Z")

</div>

Thank you for the elaborate answer. I need to muse a bit about this.  
Just one quick thought:

> Also, a test (unit, functional, etc.) will print out a bad value that is  
> asserted. However, I specifically avoid assertions on intermediate  
> values which are implementation-dependent, because they make tests  
> brittle. But these intermediate values are often very useful in fixing  
> the final result. So I'd like to be able to easily \*see\* the  
> intermediate values without having to manually add and remove inspects  
> or step through the debugger every time.

At least that could be fixed with a customized version of assert  
methods which would also pp a specific instance (or self as default)  
when the assertion fails so you can see all the internal state.

Second thought: you could use set\_trace\_func and custom assert methods  
in order to record method calls and state and only output it when the  
assert fails.

Kind regards

robert

> **···**
>
> On Tue, Sep 11, 2012 at 10:22 PM, Jonathan Tran \<lists@ruby-forum.com\> wrote:
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![Ryan\_Davis1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/ryan_davis1/32/1848_2.png) [@Ryan\_Davis1](https://rubytalk.org/u/Ryan_Davis1)\
**Post date:** [12 September 2012 09:11 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/9 "2012-09-12T09:11:07Z")

</div>

You make me want to add "should"-level assertions in minitest. 😉

> **···**
>
> On Sep 11, 2012, at 13:22 , Jonathan Tran \<lists@ruby-forum.com\> wrote:
> 
> > Also, a test (unit, functional, etc.) will print out a bad value that is  
> > asserted. However, I specifically avoid assertions on intermediate  
> > values which are implementation-dependent, because they make tests  
> > brittle. But these intermediate values are often very useful in fixing  
> > the final result. So I'd like to be able to easily \*see\* the  
> > intermediate values without having to manually add and remove inspects  
> > or step through the debugger every time.

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [3 July 2012 07:02 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/10 "2012-07-03T07:02:00Z")

</div>

> \>  
> \> To achieve your goal you'd need to copy the state of variables at each  
> \> tracefunc invocation. Even worse, as the objects themselves may change,  
> \> you will need to do a deep copy each time (otherwise you'll pluck into  
> \> exactly the same problem with object instance variables). I would  
> \> suggest  
> \> marshalling the objects and writing them to something like tmpfs, then  
> \> using a special tool to navigate the captured information.  
> \>  
> \> This is going to consume a lot of memory. I repeat: a lot. Like tens  
> \> of gigabytes for a complex thing like... Sinatra. And probably  
> \> terabytes  
> \> for Rails.
> 
> Hmm, you're right, it would not be efficient at all to store all those  
> variables especially in a large program.

Especially since you would have to store the complete graph of objects  
reachable from every scope because the change might be in an object  
referenced through some intermediate objects.

> I guess another possible approach is to rerun the program every time i  
> want to inspect a variable. Since I know which file and line the  
> variable is, I can use that as a condition on set\_trace\_func handler on  
> when to output that variable.

What about debug output? You can make that pretty efficient:

if ENV["DEBUG"]  
&nbsp;&nbsp;def debug; $stderr.puts(yield) end  
else  
&nbsp;&nbsp;def debug; end  
end

debug { sleep 1; "Complex operation" }

Kind regards

robert

> **···**
>
> On Tue, Jul 3, 2012 at 8:05 AM, Reginald Tan \<lists@ruby-forum.com\> wrote:
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![Peter\_Zotov](https://avatars.discourse-cdn.com/v4/letter/p/bbce88/32.png) [@Peter\_Zotov](https://rubytalk.org/u/Peter_Zotov)\
**Post date:** [3 July 2012 23:22 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/11 "2012-07-03T23:22:00Z")

</div>

Bartosz Dziewoński писал 03.07.2012 15:23:

> Have you tried somehow using continuations?
> 
> [Class: Continuation (Ruby 1.9.3)](http://www.ruby-doc.org/core-1.9.3/Continuation.html)
> 
> -- Matma Rex

A continuation is basically a copy of the current call stack, somewhat  
akin to fork() but with cooperative multitasking. How would it help here?

You cannot introspect continuations.

> **···**
>
> --  
> &nbsp;&nbsp;&nbsp;WBR, Peter Zotov.

---

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [3 July 2012 17:13 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/12 "2012-07-03T17:13:37Z")

</div>

> What about debug output? You can make that pretty efficient:
> 
> if ENV["DEBUG"]  
> &nbsp;&nbsp;def debug; $stderr.puts(yield) end  
> else  
> &nbsp;&nbsp;def debug; end  
> end
> 
> debug { sleep 1; "Complex operation" }
> 
> Kind regards
> 
> robert

Hi Robert, I'm not sure I understand what you mean. Isn't that the same  
as just inserting a puts statement in the code or putting logger debug  
statements around the code? What I wish to do is to inspect the  
variables at any line of execution without modifying the original  
program 🙂

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [4 July 2012 00:53 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/13 "2012-07-04T00:53:32Z")

</div>

Peter Zotov wrote in post #1067270:

> Bartosz Dziewoński писал 03.07.2012 15:23:
> 
> > Have you tried somehow using continuations?
> > 
> > [Class: Continuation (Ruby 1.9.3)](http://www.ruby-doc.org/core-1.9.3/Continuation.html)
> > 
> > -- Matma Rex
> 
> A continuation is basically a copy of the current call stack, somewhat  
> akin to fork() but with cooperative multitasking. How would it help  
> here?
> 
> You cannot introspect continuations.

Hi Matma, I tried using continuation approach here  
[Attempt to use continuation to inspect previous execution state · GitHub](https://gist.github.com/3044387) but with no luck. The output is still "5  
5 5". I guess that's because I'm still relying on binding to inspect the  
variable

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [3 July 2012 17:26 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/14 "2012-07-03T17:26:13Z")

</div>

> > What about debug output? You can make that pretty efficient:
> > 
> > if ENV["DEBUG"]  
> > &nbsp;&nbsp;def debug; $stderr.puts(yield) end  
> > else  
> > &nbsp;&nbsp;def debug; end  
> > end
> > 
> > debug { sleep 1; "Complex operation" }

> Hi Robert, I'm not sure I understand what you mean. Isn't that the same  
> as just inserting a puts statement in the code or putting logger debug  
> statements around the code?

Sort of, just a tad smarter.

> What I wish to do is to inspect the  
> variables at any line of execution without modifying the original  
> program 🙂

Oh, that requirement wasn't given as far as I can see. That's  
something different of course.

Why would the debugger not work for you? If you know the line (as you  
said earlier) you can use that information to set a breakpoint and  
inspect data when you've hit the breakpoint.

Can you explain what goal you are trying to achieve?

Cheers

robert

> **···**
>
> On Tue, Jul 3, 2012 at 7:13 PM, Reginald Tan \<lists@ruby-forum.com\> wrote:
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![11142](https://avatars.discourse-cdn.com/v4/letter/1/e0b2c6/32.png) [@11142](https://rubytalk.org/u/11142)\
**Post date:** [4 July 2012 07:57 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/15 "2012-07-04T07:57:13Z")

</div>

You can use the `local_variables` method to get a list of local  
variables in current scope. So maybe something like this:

$values\_at\_time = {}

set\_trace\_func proc { |event, file, line, id, binding, classname|  
&nbsp;&nbsp;if event == "line"  
&nbsp;&nbsp;&nbsp;&nbsp;$values\_at\_time[line] = binding.eval('local\_variables.map{|v| [v,  
eval(v.to\_s)] }')  
&nbsp;&nbsp;end  
}

a = 5  
stuff = 'asd'  
a += 8

set\_trace\_func nil  
pp $values\_at\_time

-- Matma Rex

---

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [3 July 2012 22:21 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/16 "2012-07-03T22:21:07Z")

</div>

> Why would the debugger not work for you? If you know the line (as you  
> said earlier) you can use that information to set a breakpoint and  
> inspect data when you've hit the breakpoint.
> 
> Can you explain what goal you are trying to achieve?

Sure. I want to create a tool that allows me to quickly be familiar with  
3rd party libraries or any existing legacy code base that I'll be  
maintaining.

ctags is pretty helpful in terms looking at the complete method call  
chain being executed but is not helpful in getting a big picture of  
what's going on with how my data is being transformed from one line to  
another.

Debuggers on the other hand, would give me that flexibility of  
inspecting variables, but I've experienced too much repetitive typing of  
's' for "step" and 'n' for "next" and I find that experience really  
frustrating. Moreover, since the ruby debugger only allows you to move  
forward, i would have to restart the debugging session again if i want  
trace things backwards.

So I guess what I want is the combine the power of 'ctags' and  
'ruby-debug', and create a tool that will output the callgraph of ruby  
program or method, wherein not only would I be able to see the source  
code of each method call, i would also be able to inspect the variables  
backward or forwards and at any line of the execution.

I believe this will give me a big picture of a codebase and see how one  
section of the code relates to another 🙂

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [4 July 2012 08:49 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/17 "2012-07-04T08:49:08Z")

</div>

That still suffers from the issue of changes in referenced object  
which will modify the stored state. Even adding to an Array will  
change history. As I said earlier you would need to store a complete  
object graph, something like

$values\_at\_time = {}

set\_trace\_func proc { |event, file, line, id, binding, classname|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if event == "line"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$values\_at\_time[line] =  
Marshal.dump(binding.eval("local\_variables").inject({})  
{|h,v|h[v]=binding.eval(v.to\_s);h})  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
}

Kind regards

robert

> **···**
>
> On Wed, Jul 4, 2012 at 9:57 AM, Bartosz Dziewoński \<matma.rex@gmail.com\> wrote:
> 
> > You can use the `local_variables` method to get a list of local  
> > variables in current scope. So maybe something like this:
> > 
> > $values\_at\_time = {}
> > 
> > set\_trace\_func proc { |event, file, line, id, binding, classname|  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if event == "line"  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$values\_at\_time[line] = binding.eval('local\_variables.map{|v| [v,  
> > eval(v.to\_s)] }')  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > }
> > 
> > a = 5  
> > stuff = 'asd'  
> > a += 8
> > 
> > set\_trace\_func nil  
> > pp $values\_at\_time
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![Alex\_Chaffee](https://avatars.discourse-cdn.com/v4/letter/a/da6949/32.png) [@Alex\_Chaffee](https://rubytalk.org/u/Alex_Chaffee)\
**Post date:** [6 July 2012 04:00 UTC](https://rubytalk.org/t/using-binding-set-trace-func-to-capture-execution-state/65807/18 "2012-07-06T04:00:11Z")

</div>

Nice timing! For kicks, I just wrote a gem that emulates Java's  
behavior of printing stack traces when you hit ctrl-backslash. (The  
idea is to debug programs that are stuck in an infinite loop or  
something somewhere.) I tried to also print local and instance  
variables but hit a wall; this may help with that.

It's not really ready for prime time but you can check it out:

> **[GitHub - alexch/thready: debugging library that prints your threads'...](https://github.com/alexch/thready)**
>
> debugging library that prints your threads' backtrace info when you press Ctrl-\\ - GitHub - alexch/thready: debugging library that prints your threads' backtrace info when you press Ctrl-\\

- A

> **···**
>
> On Wed, Jul 4, 2012 at 1:49 AM, Robert Klemme \<shortcutter@googlemail.com\> wrote:
> 
> > On Wed, Jul 4, 2012 at 9:57 AM, Bartosz Dziewoński \<matma.rex@gmail.com\> wrote:
> > 
> > > You can use the `local_variables` method to get a list of local  
> > > variables in current scope. So maybe something like this:
> > > 
> > > $values\_at\_time = {}
> > > 
> > > set\_trace\_func proc { |event, file, line, id, binding, classname|  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if event == "line"  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$values\_at\_time[line] = binding.eval('local\_variables.map{|v| [v,  
> > > eval(v.to\_s)] }')  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > > }
> > > 
> > > a = 5  
> > > stuff = 'asd'  
> > > a += 8
> > > 
> > > set\_trace\_func nil  
> > > pp $values\_at\_time
> > 
> > That still suffers from the issue of changes in referenced object  
> > which will modify the stored state. Even adding to an Array will  
> > change history. As I said earlier you would need to store a complete  
> > object graph, something like
> > 
> > $values\_at\_time = {}
> > 
> > set\_trace\_func proc { |event, file, line, id, binding, classname|  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if event == "line"  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$values\_at\_time[line] =  
> > Marshal.dump(binding.eval("local\_variables").inject({})  
> > {|h,v|h[v]=binding.eval(v.to\_s);h})  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > }
> > 
> > Kind regards
> > 
> > robert
> > 
> > --  
> > remember.guy do |as, often| as.you\_can - without end  
> > [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)
> 
> --  
> Alex Chaffee - alex@stinky.com  
> [http://alexchaffee.com](http://alexchaffee.com)  
> [http://twitter.com/alexch](http://twitter.com/alexch)
