cartodb-4.42/lib/cartodb/profiler.rb
2024-04-06 05:25:13 +00:00

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