Permalink
Browse files

First commit. Timer and Rack env panels

  • Loading branch information...
0 parents commit 9686cab164a0e3c9faef1a62f4ed6e179100e671 @brynary committed Mar 9, 2009
@@ -0,0 +1 @@
+coverage
5 README
@@ -0,0 +1,5 @@
+Thanks to:
+
+ Django debug toolbar
+ Rails footnotes
+ Rack's ShowException middleware
@@ -0,0 +1,20 @@
+require "rubygems"
+require "spec/rake/spectask"
+require File.expand_path("./lib/rack/bug")
+
+Spec::Rake::SpecTask.new do |t|
+ t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
+end
+
+desc "Run the specs"
+task :default => :spec
+
+desc "Run all specs in spec directory with RCov"
+Spec::Rake::SpecTask.new(:rcov) do |t|
+ t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
+ t.rcov = true
+ t.rcov_opts = lambda do
+ IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
+ end
+end
+
@@ -0,0 +1,61 @@
+require "rubygems"
+
+unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__) + "/.."))
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/.."))
+end
+
+require "rack/bug/panels/timer_panel"
+require "rack/bug/panels/env_panel"
+
+module Rack
+ module Bug
+
+ class Middleware
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ @env = env
+ @env["rack.bug.panels"] ||= []
+ status, headers, body = builder.call(env)
+ return debugged_response(env, status, headers, body)
+ end
+
+ def panel_classes
+ [TimerPanel, EnvPanel]
+ end
+
+ def builder
+ @builder = Rack::Builder.new
+
+ panel_classes.each do |panel_class|
+ @builder.use panel_class
+ end
+
+ @builder.run @app
+ return @builder
+ end
+
+ def debugged_response(env, status, headers, body)
+ output = []
+ body.each do |body_fragment|
+ output << body_fragment
+ end
+ full_output = output.join
+ full_output.sub! /<body>/, "<body>" + html(env)
+ headers["Content-Length"] = full_output.size.to_s
+ return [status, headers, full_output]
+ end
+
+ def html(env)
+ @panels = @env["rack.bug.panels"].reverse
+ @template = ERB.new ::File.read(::File.dirname(__FILE__) + "/bug/views/bug.html.erb")
+ @template.result(binding)
+ end
+
+ end
+
+ end
+end
@@ -0,0 +1,38 @@
+require "erb"
+
+module Rack
+ module Bug
+
+ # Panels are also Rack middleware
+ class Panel
+ include ERB::Util
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ before(env)
+ status, headers, body = @app.call(env)
+ after(env, status, headers, body)
+ env["rack.bug.panels"] << self
+ return [status, headers, body]
+ end
+
+ def before(env)
+ end
+
+ def after(env, status, headers, body)
+ end
+
+ def content
+ nil
+ end
+
+ def render(template)
+ end
+
+ end
+
+ end
+end
@@ -0,0 +1,23 @@
+module Rack
+ module Bug
+
+ class EnvPanel < Panel
+
+ def before(env)
+ @env = env
+ end
+
+ def heading
+ "Rack Env"
+ end
+
+ def content
+ @template = ERB.new ::File.read(::File.dirname(__FILE__) + "/../views/panels/env.html.erb")
+ @template.result(binding)
+ # render "panels/env.html.erb"
+ end
+
+ end
+
+ end
+end
@@ -0,0 +1,27 @@
+require "rack/bug/panel"
+
+module Rack
+ module Bug
+
+ class TimerPanel < Panel
+
+ def before(env)
+ @start_time = Time.now
+ end
+
+ def after(env, status, headers, body)
+ @end_time = Time.now
+ end
+
+ def run_time
+ @end_time - @start_time
+ end
+
+ def heading
+ "%.1fms" % (run_time * 1_000)
+ end
+
+ end
+
+ end
+end
@@ -0,0 +1,24 @@
+module Rack
+ module Bug
+
+ class Toolbar
+
+ def panel_classes
+ [TimerPanel, EnvPanel]
+ end
+
+ def builder
+ @builder = Rack::Builder.new
+
+ panel_classes.each do |panel_class|
+ @builder.use panel_class
+ end
+
+ @builder.run @app
+ return @builder
+ end
+
+ end
+
+ end
+end
@@ -0,0 +1,13 @@
+<div id="rack_bug">
+ <ul class="panels">
+ <li>Rack::Bug</li>
+
+ <% @panels.each do |panel| %>
+ <li><%= panel.heading %></li>
+ <% end %>
+ </ul>
+
+ <% @panels.each do |panel| %>
+ <div><%= panel.content %></div>
+ <% end %>
+</div>
@@ -0,0 +1,16 @@
+<table class="req">
+ <thead>
+ <tr>
+ <th>Variable</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ <% @env.sort_by { |k, v| k.to_s }.each do |key, val| %>
+ <tr>
+ <td><%=h key %></td>
+ <td class="code"><div><%=h val %></div></td>
+ </tr>
+ <% end %>
+ </tbody>
+</table>
@@ -0,0 +1,6 @@
+require "rubygems"
+require "sample_app"
+require File.dirname(__FILE__) + "/../../lib/rack/bug"
+
+use Rack::Bug::Middleware
+run SampleApp
@@ -0,0 +1,15 @@
+require "sinatra"
+
+class SampleApp < Sinatra::Default
+
+ get "/" do
+ <<-HTML
+ <html>
+ <body>
+ <p>Hello</p>
+ </body>
+ </html>
+ HTML
+ end
+
+end
@@ -0,0 +1,31 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe Rack::Bug do
+
+ def app
+ Rack::Bug::Middleware.new(SampleApp.new)
+ end
+
+ def session
+ @session ||= Rack::Test::Session.new(app)
+ end
+
+ def get(*args, &block)
+ session.get(*args, &block)
+ end
+
+ def response
+ session.last_response
+ end
+
+ it "should return the right Content-Length" do
+ get "/"
+ response["Content-Length"].should == response.body.join("\n").size.to_s
+ end
+
+ it "should track the elapsed time" do
+ get "/"
+ response.body.join("\n").should =~ /\d+\.\dms/
+ end
+
+end
@@ -0,0 +1 @@
+-x gems,spec\/
@@ -0,0 +1 @@
+--color
@@ -0,0 +1,6 @@
+require "rubygems"
+require "spec"
+require "rack/test"
+
+require File.dirname(__FILE__) + "/../lib/rack/bug"
+require File.dirname(__FILE__) + "/fixtures/sample_app"

0 comments on commit 9686cab

Please sign in to comment.