2016-09-13 17:45:13 +05:30
|
|
|
require 'ruby-prof'
|
|
|
|
|
|
|
|
module Gitlab
|
|
|
|
module RequestProfiler
|
|
|
|
class Middleware
|
|
|
|
def initialize(app)
|
|
|
|
@app = app
|
|
|
|
end
|
|
|
|
|
|
|
|
def call(env)
|
|
|
|
if profile?(env)
|
|
|
|
call_with_profiling(env)
|
|
|
|
else
|
|
|
|
@app.call(env)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def profile?(env)
|
|
|
|
header_token = env['HTTP_X_PROFILE_TOKEN']
|
|
|
|
return unless header_token.present?
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
profile_token = Gitlab::RequestProfiler.profile_token
|
2016-09-13 17:45:13 +05:30
|
|
|
return unless profile_token.present?
|
|
|
|
|
|
|
|
header_token == profile_token
|
|
|
|
end
|
|
|
|
|
|
|
|
def call_with_profiling(env)
|
|
|
|
ret = nil
|
|
|
|
result = RubyProf::Profile.profile do
|
|
|
|
ret = catch(:warden) do
|
|
|
|
@app.call(env)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
printer = RubyProf::CallStackPrinter.new(result)
|
|
|
|
file_name = "#{env['PATH_INFO'].tr('/', '|')}_#{Time.current.to_i}.html"
|
|
|
|
file_path = "#{PROFILES_DIR}/#{file_name}"
|
|
|
|
|
|
|
|
FileUtils.mkdir_p(PROFILES_DIR)
|
|
|
|
File.open(file_path, 'wb') do |file|
|
|
|
|
printer.print(file)
|
|
|
|
end
|
|
|
|
|
|
|
|
if ret.is_a?(Array)
|
|
|
|
ret
|
|
|
|
else
|
|
|
|
throw(:warden, ret)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|