Skip to content

Instantly share code, notes, and snippets.

@steve9001
Created December 7, 2011 16:18
Show Gist options
  • Star 32 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save steve9001/1443408 to your computer and use it in GitHub Desktop.
Save steve9001/1443408 to your computer and use it in GitHub Desktop.
Rails middleware to provide information about errors during requests
module MyApp
class Application < Rails::Application
if Rails.env == 'test'
require 'diagnostic'
config.middleware.use(MyApp::DiagnosticMiddleware)
end
end
end
module MyApp
class DiagnosticMiddleware
FILENAME = 'diagnostic.txt'
def initialize(app)
@app = app
end
def call(env)
return @app.call(env)
rescue StandardError => e
trace = e.backtrace.select{ |l|l.start_with?(Rails.root.to_s) }.join("\n ")
msg = "#{e.class}\n#{e.message}\n#{trace}\n"
File.open(FILENAME, 'a') { |f| f.write msg }
raise e
end
end
end
@supairish
Copy link

This is great, really helpful when testing Capybara request specs that use JS drivers. Thanks man!

@amalagaura
Copy link

My god thank you for this, i was going crazy trying to get the exception into the log.

@amalagaura
Copy link

BTW, you can just stick the lines in test.rb instead of application.rb with checking the environment, thats what test.rb is there for.

@scootklein
Copy link

also, putting the lines straight into log/test.log with some delimiters for visual ease help out a lot as well

module MyApp
  class DiagnosticMiddleware
    FILENAME = File.join(Rails.root, 'log', 'test.log')

    def initialize(app)
      @app = app
    end

    def call(env)
      return @app.call(env)
    rescue StandardError => e
      trace = e.backtrace.select{ |l|l.start_with?(Rails.root.to_s) }.join("\n    ")
      msg = "#{e.class}\n#{e.message}\n#{trace}\n"
      File.open(FILENAME, 'a') { |f| 
        f.write "\n"
        f.write "\n"
        f.write " ---   BACKTRACE   --- \n"
        f.write "\n"

        f.write msg 

        f.write "\n"
        f.write " ---   BACKTRACE   --- \n"
        f.write "\n"
        f.write "\n"
      }
      raise e
    end
  end
end

@redross
Copy link

redross commented Aug 28, 2012

Works like a charm. Thanks Steve!

@wdspkr
Copy link

wdspkr commented Nov 14, 2012

The only way I found, to track down Internal server errors that come from ajax calls. You made my day! Thanks! (also very convenient additions by amalagaura and scottklein!)

@Hengjie
Copy link

Hengjie commented Mar 2, 2013

I placed the diagnostic.rb file inside the config directory but needed to replace the require 'diagnostic line in application.rb with the following:

require File.expand_path("../diagnostic.rb", __FILE__)

@Bestra
Copy link

Bestra commented May 21, 2013

Awesome. Thank you!

@yagudaev
Copy link

That is absolutely awesome! Thank you!
@scootklein's modifications make it even more powerful by seeing the backtrace along with the request. This makes debugging integration tests very similar to debugging in development env.

@micapam
Copy link

micapam commented Oct 2, 2013

Excellent - thanks @steve9001 and @scootklein. I put the 'middleware.use' line into config/environments/test.rb to keep my application.rb file clean.

@Paxa
Copy link

Paxa commented Mar 16, 2015

Thanks, very useful. I just print to stdout:

module MyApp
  class DiagnosticMiddleware

    def initialize(app)
      @app = app
    end

    def call(env)
      return @app.call(env)
    rescue StandardError => error
      puts error.message
      puts error.backtrace
      raise error
    end
  end
end

@jerefrer
Copy link

Proved helpful in a case of "Internal server error" while running a spec which did not provide much detail either on the page or in the test log file.

Thanks a bunch !

@grauschnabel
Copy link

the same here, i would also like to have it as a spec, so it does not work for me.

@aterletskiy
Copy link

It didn't work for me until I changed it to rescue Exception instead of StandardError.

@davidmles
Copy link

application.rb should be:

if Rails.env == 'test'
  require File.expand_path('../diagnostic', __FILE__)
  config.middleware.use(MyApp::DiagnosticMiddleware)
end

@mcmire
Copy link

mcmire commented Apr 24, 2017

I happened to handle this a little bit differently -- by detecting RoutingErrors on image paths: https://gist.github.com/mcmire/68cd9c74ba765a2d5dfb14abf58409aa

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment