class Rack::Objectspace

Constants

KEY_SEPARATOR
VERSION

Public Class Methods

new(app, store:, async: true, object_space: ObjectSpace) click to toggle source
# File lib/rack/objectspace.rb, line 9
def initialize(app, store:, async: true, object_space: ObjectSpace)
  @app = app
  @store = store
  @async = async
  @object_space = object_space
  @object_space.trace_object_allocations_start
end

Public Instance Methods

call(env) click to toggle source
# File lib/rack/objectspace.rb, line 17
def call(env)
  result = @app.call(env)

  dumper = Thread.new { dump_allocations(env) }
  dumper.join unless @async

  result
end
dump_allocations(env) click to toggle source
# File lib/rack/objectspace.rb, line 26
def dump_allocations(env)
  read, write = IO.pipe

  if pid = fork
    # parent
    read.close
    GC.start
    @object_space.dump_all(output: write)
    write.close
    Process.wait(pid) unless @async
  else
    # child
    write.close
    parse_dump(input: read, key: request_id(request: env, pid: Process.ppid))
    read.close
  end
end
parse_dump(input:, key:, run: ->(id, obj) { store_object(id, obj) } click to toggle source
# File lib/rack/objectspace.rb, line 44
def parse_dump(input:, key:, run: ->(id, obj) { store_object(id, obj) })
  parser = Yajl::Parser.new
  parser.on_parse_complete = lambda do |obj|
    run.call(key, obj)
  end
  parser.parse(input)
end
request_id(request:, pid:, time: Time) click to toggle source
# File lib/rack/objectspace.rb, line 61
def request_id(request:, pid:, time: Time)
  timestamp = time.now.to_i
  request_path = request['PATH_INFO'].tr_s(::File::SEPARATOR, '-').sub!(/^-/, '').downcase
  request_method = request['REQUEST_METHOD'].downcase
  random_salt = SecureRandom.hex(4)
  ['rack-objectspace', pid, timestamp, request_path, request_method, random_salt].join(KEY_SEPARATOR)
end
store_object(request_id, obj) click to toggle source
# File lib/rack/objectspace.rb, line 52
def store_object(request_id, obj)
  object_id = obj.delete('address')
  if object_id
    obj.each do |attr, value|
      @store[[request_id, object_id, attr].join(KEY_SEPARATOR)] = value
    end
  end
end