90 lines
2.1 KiB
Ruby
90 lines
2.1 KiB
Ruby
|
require 'ruby-prof'
|
||
|
require 'stringio'
|
||
|
|
||
|
require 'carto/configuration'
|
||
|
|
||
|
module CartoDB
|
||
|
|
||
|
# A profiler based on https://github.com/justinweiss/request_profiler/
|
||
|
class Profiler
|
||
|
include Carto::Configuration
|
||
|
|
||
|
def initialize(printer: nil, exclude: nil)
|
||
|
@printer = printer || ::RubyProf::CallTreePrinter
|
||
|
@exclusions = exclude
|
||
|
end
|
||
|
|
||
|
def call(request, response)
|
||
|
mode = profile_mode(request)
|
||
|
|
||
|
::RubyProf.measure_mode = mode
|
||
|
::RubyProf.start
|
||
|
begin
|
||
|
yield
|
||
|
ensure
|
||
|
result = ::RubyProf.stop
|
||
|
write_result(result, request, response)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def profile_mode(request)
|
||
|
mode_string = request.params["profile_request"]
|
||
|
if mode_string
|
||
|
if mode_string.downcase == "true" or mode_string == "1"
|
||
|
::RubyProf::PROCESS_TIME
|
||
|
else
|
||
|
::RubyProf.const_get(mode_string.upcase)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def format(printer)
|
||
|
case printer
|
||
|
when ::RubyProf::FlatPrinter
|
||
|
'txt'
|
||
|
when ::RubyProf::FlatPrinterWithLineNumbers
|
||
|
'txt'
|
||
|
when ::RubyProf::GraphPrinter
|
||
|
'txt'
|
||
|
when ::RubyProf::GraphHtmlPrinter
|
||
|
'html'
|
||
|
when ::RubyProf::DotPrinter
|
||
|
'dot'
|
||
|
when ::RubyProf::CallTreePrinter
|
||
|
"out.#{Process.pid}"
|
||
|
when ::RubyProf::CallStackPrinter
|
||
|
'html'
|
||
|
else
|
||
|
'txt'
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def prefix(printer)
|
||
|
case printer
|
||
|
when ::RubyProf::CallTreePrinter
|
||
|
"callgrind."
|
||
|
else
|
||
|
""
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def write_result(result, request, response)
|
||
|
result.eliminate_methods!(@exclusions) if @exclusions
|
||
|
printer = @printer.new(result)
|
||
|
url = request.fullpath.gsub(/[?\/]/, '-')
|
||
|
filename = "#{prefix(printer)}#{Time.now.strftime('%Y-%m-%d-%H-%M-%S')}-#{url.slice(0, 50)}.#{format(printer)}"
|
||
|
|
||
|
in_mem_file = ""
|
||
|
::StringIO.open(in_mem_file, 'w+') do |f|
|
||
|
printer.print(f)
|
||
|
end
|
||
|
|
||
|
response.body = in_mem_file
|
||
|
response.status = 200
|
||
|
response.content_type = 'text/plain'
|
||
|
response.headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end
|