class Rack::MP::Middleware

Small middleware to count Ruby objects before and after a request. Puts the values in the X-MP-ObjectCounts response header. Just pass __mp__=counts in the query string.

That’s all it does at the moment - probably only useful for identifying which type of object is causing a memory leak. And, possibly, confirming which queries are contributing.

Public Class Methods

new(app) click to toggle source

New middleware instance.

# File lib/rack/mp/middleware.rb, line 15
def initialize(app)
  @app = app
end

Public Instance Methods

call(env) click to toggle source

Run the middleware. Will count the objects, run the app, count the objects, and output how long the whole thing took, and the number of objects before and after.

NOTE - the header string will be JSON! Yuck. But it was the quickest way to do it for now.

# File lib/rack/mp/middleware.rb, line 25
def call(env)
  return @app.call(env) unless active?(env)
  before, t0 = time { count_objects }
  result, t1 = time { @app.call(env.merge('mp.counting' => true)) }
  after,  t2 = time { count_objects }
  timings = { before: t0, request: t1, after: t2 }
  data = serialize(before: before, after: after, timings: timings)
  status, headers, body = *result
  [status, headers.merge('X-MP-ObjectCounts' => data), result]
end

Private Instance Methods

active?(env) click to toggle source

Check whether we need to do anything. Just looks for __mp__=counts in the query string. Not very sophisticated. Could be extended to check authentication, etc.

# File lib/rack/mp/middleware.rb, line 40
def active?(env)
  env['QUERY_STRING'] =~ %r{__mp__=counts}
end
count_objects() click to toggle source

The simplest object counter. Could potentially be expanded to ask all apps in a cluster, and sum them!

# File lib/rack/mp/middleware.rb, line 46
def count_objects
  ObjectSpace.count_objects
end
serialize(*args) click to toggle source

Make a string for the response. Easiest output for now seems to be JSON

# File lib/rack/mp/middleware.rb, line 52
def serialize(*args)
  MultiJson.dump(*args)
end
time() { || ... } click to toggle source

Time an operation, returning the operation’s result and the time it took.

# File lib/rack/mp/middleware.rb, line 58
def time(&block)
  t = Time.now
  [yield, Time.now - t]
end