GithubHelp home page GithubHelp logo

ruby-minstrel's Introduction

Ruby Minstrel

Minstrel allows you to wrap every method call for a given class so you can more
easily observe how a class and its methods are being used.

Get it

Why?

Fun. Also, sometimes ruby-prof and similar tools are overkill when I am trying
to debug or dig into how a piece of code works.

It’s a lot like strace/tcpdump/dtrace for ruby, or aims to be, anyway.

I wanted a tool that was useful for my own code as well as for helping
understand and debug other code (puppet, mcollective, rails, activerecord,
sinatra, etc…).

Examples

From the commandline

You can use minstrel to wrap classes with a default ‘print’ wrapper that simply
prints what is called. For example:

% RUBY_INSTRUMENT=String ruby -rminstrel -e 'puts "hello world".capitalize.reverse'
enter String#capitalize([])
exit String#capitalize([])
enter String#reverse([])
exit String#reverse([])
dlrow olleH

The ‘minstrel’ tool

Since the following doesn’t work as expected in ruby 1.8 (or maybe all rubies):
ruby -rrubygems -rminstrel …, I provide ‘minstrel’ as a way to run ruby
programs with minstrel preloaded.

% cat test.rb                            
#!/usr/bin/env ruby
puts "hello world".capitalize.reverse

% RUBY_INSTRUMENT=String minstrel test.rb
enter String#capitalize([])
exit String#capitalize([])
enter String#reverse([])
exit String#reverse([])
dlrow olleH

Example: Tracing puppet storeconfigs (aka Tracing ActiveRecord queries)

ActiveRecord has a base class for most things query-related. Let’s trace that:

% sudo env RUBY_INSTRUMENT=ActiveRecord::ConnectionAdapters::DatabaseStatements minstrel puppet ...
enter ActiveRecord::ConnectionAdapters::DatabaseStatements#select_all(["SELECT     DISTINCT 
`hosts`.id FROM       `hosts`  LEFT OUTER JOIN `fact_values` ON `fact_values`.`host_id` = `h
osts`.`id` LEFT OUTER JOIN `fact_names` ON `fact_names`.`id` = `fact_values`.`fact_name_id` 
...
enter ActiveRecord::ConnectionAdapters::DatabaseStatements#select_all(["SELECT     `hosts`.`id` AS t0_r0, `hosts`.`name` AS t0_r1, `hosts`.`ip` AS t0_r2, `hosts`.`environment ...

So easy :)

From ruby

Boilerplate:

require "minstrel"

instrument = Minstrel::Instrument.new()
instrument.wrap(String) do |point, klass, method, *args|
  #  * point is either :enter or :exit depending if this function is about to be
  #    called or has finished being called.
  #  * klass is the class object (String, etc)
  #  * method is the method (a Symbol)
  #  * *args is the arguments passed
end

Example:

require "minstrel"

class Foo
  def bar(one, &block)
    yield one
  end
  
  def baz
    puts "Baz!"
  end 
end

instrument = Minstrel::Instrument.new
instrument.wrap(Foo) do |point, klass, method, *args|
  puts "#{point} #{klass.name}##{method}(#{args.inspect})"
end

foo = Foo.new
foo.bar(123) { |arg| puts arg }
foo.baz

Output:

enter Foo#bar([123])
123
exit Foo#bar([123])
enter Foo#baz([])
Baz!
exit Foo#baz([])

From ruby (deferred loading)

Sometimes you don’t know when a class is going to be defined. To solve this,
you must use Minstrel::Instrument#wrap_classname. For example:

>> require "minstrel"
>> Minstrel::Instrument.new.wrap_classname("TCPSocket")
>> require "socket"
Wrap of TCPSocket successful

Minstrel will wrap ‘require’ and check for classes you want wrapped at each
require until it finds all the classes you asked to be wrapped.

Caveats

Metaprogramming will not be often caught, necessarily, by minstrel, because they don’t
show usuall up as methods. However, the things invoking metaprogramming are
usually methods so in most cases you’ll get lucky enough to see what’s going
on.

Some cases of metaprogramming (dynamic method generation, DSLs, etc) can be
caught if you call Minstrel::Instrument#wrap() late enough in the lifetime of
the program that the dynamic methods have been created.

Bugs?

If you find bugs, have feature suggestions, etc, feel free to open bugs here on
github (https://github.com/jordansissel/ruby-minstrel/issues). I also read email:
[email protected]

ruby-minstrel's People

Contributors

jordansissel avatar

Stargazers

Jeff McCune avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.