Skip to content

Instantly share code, notes, and snippets.

@Telmo
Forked from tenderlove/instrument.rb
Created March 24, 2012 01:48
Show Gist options
  • Save Telmo/2177407 to your computer and use it in GitHub Desktop.
Save Telmo/2177407 to your computer and use it in GitHub Desktop.
class Dot
class Node
attr_reader :children, :name, :started
attr_accessor :finished
def initialize name, fields = [], started = Time.now
@name = name
@fields = fields
@children = []
@started = started
@finished = nil
end
def label
fields = @fields.map { |k,v|
"<tr><td>#{k.to_s}</td><td>#{v.to_s}</td></tr>"
}.join "\n"
<<-eolabel
#{object_id}[
shape="plaintext";
label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD colspan="2">#{name} (#{delta_ms} ms)</TD></TR>
#{fields}
</TABLE>>];
eolabel
end
def delta_ms
if finished
1000.0 * (finished - started)
else
"..."
end
end
def to_dot
stack = [self]
edges = []
until stack.empty?
node = stack.pop
node.children.each do |child|
edges << [node, child]
stack << child
end
end
nodes = edges.flatten.uniq
e = edges.map { |l,r| "#{l.object_id} -> #{r.object_id}" }.join ";\n"
<<-eodot
digraph G {
#{nodes.map(&:label).join(";\n")};
#{e};
}
eodot
end
end
def initialize
@root = Node.new 'ROOT'
@stack = [@root]
trap(:INFO) {
File.open('/tmp/out.dot', 'w') { |f|
f.write @root.to_dot
}
@stack = [@root]
@root.children.clear
}
end
def start name, id, payload
fields = payload.find_all { |k,v|
String === v
}.map { |k,v| [k, v.sub(/^#{Application.root}/, '')] }
node = Node.new name, fields
@stack.last.children << node
@stack << node
end
def finish name, id, payload
@stack.pop.finished = Time.now
end
end
ActiveSupport::Notifications.notifier.subscribe(nil, Dot.new)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment