diff options
author | Ahmad Sherif <me@ahmadsherif.com> | 2016-07-15 18:46:39 +0300 |
---|---|---|
committer | Ahmad Sherif <me@ahmadsherif.com> | 2016-07-26 21:06:09 +0300 |
commit | 345cd22f21e4e5a6e340c35e50b43105ee107570 (patch) | |
tree | d1f3916535c9bca94cb9c8fe16559332dcbf762e /lib/gitlab/request_profiler | |
parent | 0c799be6b6fc0166473c82039ebf662a0558ed8f (diff) |
Profile requests when a header is passed
Diffstat (limited to 'lib/gitlab/request_profiler')
-rw-r--r-- | lib/gitlab/request_profiler/middleware.rb | 47 | ||||
-rw-r--r-- | lib/gitlab/request_profiler/profile.rb | 43 |
2 files changed, 90 insertions, 0 deletions
diff --git a/lib/gitlab/request_profiler/middleware.rb b/lib/gitlab/request_profiler/middleware.rb new file mode 100644 index 00000000000..8da8b754975 --- /dev/null +++ b/lib/gitlab/request_profiler/middleware.rb @@ -0,0 +1,47 @@ +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? + + profile_token = RequestProfiler.profile_token + return unless profile_token.present? + + header_token == profile_token + end + + def call_with_profiling(env) + ret = nil + result = RubyProf::Profile.profile do + ret = @app.call(env) + 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 + + ret + end + end + end +end diff --git a/lib/gitlab/request_profiler/profile.rb b/lib/gitlab/request_profiler/profile.rb new file mode 100644 index 00000000000..f89d56903ef --- /dev/null +++ b/lib/gitlab/request_profiler/profile.rb @@ -0,0 +1,43 @@ +module Gitlab + module RequestProfiler + class Profile + attr_reader :name, :time, :request_path + + alias_method :to_param, :name + + def self.all + Dir["#{PROFILES_DIR}/*.html"].map do |path| + new(File.basename(path)) + end + end + + def self.find(name) + name_dup = name.dup + name_dup << '.html' unless name.end_with?('.html') + + file_path = "#{PROFILES_DIR}/#{name_dup}" + return unless File.exist?(file_path) + + new(name_dup) + end + + def initialize(name) + @name = name + + set_attributes + end + + def content + File.read("#{PROFILES_DIR}/#{name}") + end + + private + + def set_attributes + _, path, timestamp = name.split(/(.*)_(\d+)\.html$/) + @request_path = path.tr('|', '/') + @time = Time.at(timestamp.to_i).utc + end + end + end +end |