cleanup a few typos
[raindrops.git] / lib / raindrops / middleware.rb
blobf5cbb89cd6d260c7c84d67b459f2e799ea74f962
1 # -*- encoding: binary -*-
2 require 'raindrops'
4 # Raindrops middleware should be loaded at the top of Rack
5 # middleware stack before other middlewares for maximum accuracy.
6 class Raindrops
7 class Middleware < ::Struct.new(:app, :stats, :path, :tcp, :unix)
9   # :stopdoc:
10   Stats = Raindrops::Struct.new(:calling, :writing)
11   PATH_INFO = "PATH_INFO"
12   # :startdoc:
14   def initialize(app, opts = {})
15     super(app, opts[:stats] || Stats.new, opts[:path] || "/_raindrops")
16     tmp = opts[:listeners]
17     if tmp.nil? && defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
18       tmp = Unicorn.listener_names
19     end
21     if tmp
22       self.tcp = tmp.grep(/\A[^:]+:\d+\z/)
23       self.unix = tmp.grep(%r{\A/})
24       self.tcp = nil if tcp.empty?
25       self.unix = nil if unix.empty?
26     end
27   end
29   # standard Rack endpoint
30   def call(env)
31     env[PATH_INFO] == path ? stats_response : dup._call(env)
32   end
34   def _call(env)
35     stats.incr_calling
36     status, headers, self.app = app.call(env)
38     # the Rack server will start writing headers soon after this method
39     stats.incr_writing
40     [ status, headers, self ]
41     ensure
42       stats.decr_calling
43   end
45   # yield to the Rack server here for writing
46   def each(&block)
47     app.each(&block)
48   end
50   # the Rack server should call this after #each (usually ensure-d)
51   def close
52     stats.decr_writing
53     app.close if app.respond_to?(:close)
54   end
56   def stats_response
57     body = "calling: #{stats.calling}\n" \
58            "writing: #{stats.writing}\n"
60     if defined?(Linux)
61       Linux.tcp_listener_stats(tcp).each do |addr,stats|
62         body << "#{addr} active: #{stats.active}\n" \
63                 "#{addr} queued: #{stats.queued}\n"
64       end if tcp
65       Linux.unix_listener_stats(unix).each do |addr,stats|
66         body << "#{addr} active: #{stats.active}\n" \
67                 "#{addr} queued: #{stats.queued}\n"
68       end if unix
69     end
71     headers = {
72       "Content-Type" => "text/plain",
73       "Content-Length" => body.size.to_s,
74     }
75     [ 200, headers, [ body ] ]
76   end
78 end
79 end