allanbatista
7/4/2016 - 6:15 PM

Rails MIddleware to track Request Timeout

Rails MIddleware to track Request Timeout

## app/middleware/request_timeout_log.rb
#
## config/application.rb
# add middleware to cout request time and log them
# config.middleware.use 'RequestTimeoutLog'
#
# http://thread.gmane.org/gmane.comp.lang.ruby.unicorn.general/1265/focus=1269
#
#   class RequestTimeoutLog < Struct.new(:app)
#     def call(env)
#       thr = Thread.new do
#         sleep(1) # set this to Unicorn timeout - 1
#         unless Thread.current[:done]
#           path = env["PATH_INFO"]
#           qs = env["QUERY_STRING"] and path = "#{path}?#{qs}"
#           env["rack.logger"].warn("#{path} about to die from SIGKILL")
#         end
#       end
#       app.call(env)
#     ensure
#       thr[:done] = true
#       thr.run
#     end
#   end

class RequestTimeoutLog
  SLEEP_MS  = 0.100
  MAX_SLEEP = 120

  def initialize(app)
    @app = app
  end

  def call(env)
    thr = Thread.new do
      Thread.current[:count] = 0
      Thread.current[:max_count] = MAX_SLEEP / SLEEP_MS

      while !Thread.current[:done] do
        sleep(SLEEP_MS)
        Thread.current[:count] = Thread.current[:count] + 1

        if Thread.current[:count] >=  Thread.current[:max_count]
          message = "{\"REQUEST_URI\":\"#{env['REQUEST_URI']}\"}"
          Honeybadger.notify(StandardError.new(message))
          Rails.logger.error(message)
          Thread.kill(thr)
        end

        break if Thread.current[:count] >= Thread.current[:max_count]
      end
    end

    @app.call(env)
  ensure
    thr[:done] = true
    thr.run
  end
end