Skip to content
This repository has been archived by the owner on Aug 22, 2019. It is now read-only.

Commit

Permalink
Add plugin support and status plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
evanphx committed May 1, 2012
1 parent 8bd0741 commit a4f9dd6
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 4 deletions.
36 changes: 32 additions & 4 deletions lib/puma/express.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,21 @@ class Puma::Express
"content-length" => true
}

def initialize
@plugins = {}

def self.add_plugin(name, obj)
@plugins[name] = obj
end

def self.plugin(name)
@plugins[name]
end

DefaultPlugins = ["status"]

def initialize(plugins=DefaultPlugins.dup)
@plugins = plugins.map { |i| self.class.plugin(i).new self }

@running = {}
@root = ENV['PUMA_EXPRESS_ROOT'] || File.expand_path("~/.puma_express")
@apps = {}
Expand All @@ -23,6 +37,8 @@ def initialize
monitor_apps
end

attr_reader :apps

def cleanup
@apps.each do |h,a|
a.stop
Expand Down Expand Up @@ -66,7 +82,7 @@ def start(env)
path = File.join @root, base

if File.exists? path
app = App.new host, path, @unix_socket_dir, 5.0
app = App.new host, path, @unix_socket_dir, 180.0

app.run

Expand Down Expand Up @@ -189,6 +205,10 @@ def proxy_tcp(env, host, port)
end

def call(env)
plugin = @plugins.detect { |i| i.handle?(env) }

return plugin.call(env) if plugin

app = find_app(env)

app = start(env) unless app
Expand All @@ -197,14 +217,22 @@ def call(env)

begin
if sock = app.unix_socket
proxy_unix env, sock
res = proxy_unix env, sock
else
proxy_tcp env, "localhost", app.tcp_port
res = proxy_tcp env, "localhost", app.tcp_port
end

@plugins.each do |i|
i.add_result(app, env, res)
end

res
rescue SystemCallError => e
error env, "Error: #{e.message} (#{e.class})"
rescue Exception => e
error env, "Unknown error: #{e.message} (#{e.class})"
end
end
end

require 'puma/express/status'
86 changes: 86 additions & 0 deletions lib/puma/express/status.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<html>
<head>
<title>Puma Express Status</title>
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">
<style>
body {
padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
}
</style>
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="#">Puma Express Status</a>
<div class="nav-collapse">
<ul class="nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<div class="container">
<% apps.each do |h,a| %>
<i class="icon-star"></i> <strong><%= h %></strong>
<ul>
<% hits[a].reverse_each do |hit| %>
<div class="hit">
<h1>
<span class="label label-success"><%= hit.code %></span>
<%= hit.path %>
</h1>

<dl>
<dt>Request</dt>
<dd>
<table class="table table-striped table-condensed">
<tbody>
<% hit.sorted_request.each do |k,v| %>
<tr><th><%= k %></th><td><code><%= v %></code></td></tr>
<% end %>
</tbody>
</table>
</dd>
<dt>Response</dt>
<dd>
<table class="table table-striped table-condensed">
<tbody>
<tr>
<th>Code</th>
<td><span class="label label-success"><%= hit.code %></span></td>
</tr>
<tr>
<th>Headers</th>
<td>
<table class="table table-striped table-condensed">
<% hit.sorted_response.each do |k,v| %>
<tr><th><%= k %></th><td><code><%= v %></td></code></tr>
<% end %>
</table>
</td>
</tr>
<tr>
<th>Body</th>
<td>
<code><%= hit.body %></code>
</td>
</tr>
</tbody>
</table>
</dd>
</div>
<% end %>
</ul>
<% end %>
</div>
</body>
</html>
77 changes: 77 additions & 0 deletions lib/puma/express/status.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
require 'erb'
require 'thread'

class Puma::Express
class Status

Puma::Express.add_plugin 'status', self

TEMPLATE = File.expand_path "../status.erb", __FILE__

def initialize(express)
@express = express
@mutex = Mutex.new
@hits = Hash.new { |h,k| h[k] = [] }
@hit_window = 10
end

def handle?(env)
env['HTTP_HOST'].split(".").first == "status"
end

class Hit
def initialize(req, res)
@request = req
@result = res
end

attr_reader :request, :result

def path
@request['PATH_INFO']
end

def code
@result.first
end

def body
@result.last.join
end

def sorted_request
headers = @request.find_all { |k,v| k[0,5] == "HTTP_" }
headers.map! do |k,v|
[k[5..-1].split("_").map { |x| x.downcase.capitalize }.join("-"), v]
end

headers.sort_by { |k,v| k }
end

def sorted_response
@result[1].sort_by { |k,v| k }
end
end

def add_result(app, req, res)
p :res => res

@mutex.synchronize do
hits = @hits[app]
if hits.size >= @hit_window
hits.shift
end

hits.push Hit.new(req, res)
end
end

def call(env)
apps = @express.apps.sort_by { |h,a| h }
hits = @hits

body = ERB.new(File.read(TEMPLATE)).result(binding)
[200, {}, body]
end
end
end

0 comments on commit a4f9dd6

Please sign in to comment.