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