Im trying to get the backtrace in sinatra in case of an error.
I know rails has one in
Rails.respond_to?(:backtrace_cleaner)
and I saw that sinatra is suppose to have one (by default enabled) in STDERR
So i tried
STDERR.inspect
and I got #<IO:<STDERR>>
When rescuing the exception, catch the exception object.
begin
raise "hello"
rescue => e
e.backtrace
end
In Ruby you can call a method caller at any place and get a full backtrace as an array.
Related
I'm trying to rescue an exception with this method:
def template_deleted
mailchimp_client.templates.info(mailchimp_id)
rescue Mailchimp::InvalidTemplateError => error
puts "Template deleted in Mailchimp: #{error}"
return true
else
return false
end
And no matter what I use to output the message, whether it's STDERR, STDOUT, log.error, p, puts, or print, nothing gets out to the environment's log. This should definitely be returning an error, because the template definitely doesn't exist in Mailchimp.
When I try the same code in the console I can read the error just fine, so either there's something wrong with the rescuing itself (i.e., my method is returning false which it shouldn't), or there's something wrong with the way I'm outputting it.
To output something in the log file of the current environment, use the Rails logger like this:
logger.debug "Template deleted in Mailchimp: #{error}"
You can replace the debug method call with any logging level name, that are briefly described in the link above. Also don't forget to make sure you're running in correct environment!
Suppose you have an existing app, and want to modify the exception handling for the entire app. It is not possible to wrap the app in a begin/rescue block.
What is a good way to modify the exception handler (to suppress the backtrace) by adding code that runs before the app starts?
begin/rescue are not methods so you can't over-write them. If an exception is raised, several steps will unfold, the first one being...calling .exception on whatever object you passed the exception on. Example:
class A
def exception
p 'I am going to print'
RuntimeError.new('message')
end
end
a = A.new
raise a #=> 'I am going to print' and then runtime error is raised
If you control what you pass to 'raise', then you can pass it an object. The first step after .raise is called is that it calls the .exception method on that object, as you can see from here.
If you don't want the backtrace to show at all in the terminal, use abort instead of raise:
abort 'aborting!' #=> prints 'aborting' to STDERR and then does exit 1 implicitly. No backtrace is shown.
You can wrap the entire app in a method that will do all the exception handling for you:
def exception_handler
puts 'Do whatever you want here before the app starts executing'
yield
rescue
# put the logic of handling errors here
# for example, you could do 'abort 'error occured'' that will make the program stop and not show a backtrace
end
exception_handler do
puts 'My app code goes here'
end
Will print:
Do whatever you want here before the app starts executing
My app code goes here
Let's say your app raises a bunch of ArgumentErrors. What you can do is re-open the class and execute some code before raising:
class ArgumentError
alias_method :real_initialize, :initialize
def initialize(*args) # we're overriding initialize
super(*args)
p 'some code here'
end
end
raise ArgumentError
Recently, I am working on mobile automation using appium+selenium in ruby. But stopped by the following issue: selenium driver is quit automatically (mobile app is closed) every time an exception happens. This will result in that the following code to access the driver will fail after I manage to rescue the exception.
e.g.
begin
#driver.find_element(:xpath, "//window[1]/button[27]")
rescue
#driver.find_element(:xpath, "//window[1]/navigationBar[1]/button[2]").click
end
Does anyone have this issue as well?
According to http://www.ruby-doc.org/core-2.1.1/doc/syntax/exceptions_rdoc.html "By default StandardError and its subclasses are rescued. You can rescue a specific set of exception classes (and their subclasses) by listing them after rescue:
begin
# ...
rescue ArgumentError, NameError
# handle ArgumentError or NameError
end
I assume you are waiting for something like ElementNotVisibleException. So, add type of exception after rescue. Something like rescue ElementNotVisibleException.
The problem is in relation to the radis-rb gem.
The exception is not caught by my rescue block and my app goes down.
My code:
begin
redis = Redis.new
puts "WTF?"
rescue Exception
puts "Exception"
end
If redis is down, the message WTF? is exposed.
It happens with or without the Exception statement.
Why is the exception not raised to my rescue block?
I have solved the problem myself (with help from the community and comments).
The exception occurred in IRB only.
The reason of one is IRB's inspect call when IRB try to print result of Redis.new.
In the script (not IRB), the exception doesn't occur because Redis.new does not raise an exception if the Redis service is down.
This question helped to solve my problem.
I have a set of cucumber tests that get run on a build server.
I often want faster feedback than the server directly provides and so I watch the console output as it runs. I was wanting a way of identifying any failing test with a single search term so I modified our Around to print "Failed Test" on any exception, but Ruby doesn't seem to be handing the exception back up to the around. I've verified this by having puts statements after the begin ... end.
Does anyone know why this is happening or a way of wrapping any exception thrown from a failing test in a begin?
Around() do |scenario, block|
begin
Timeout.timeout(0.1) do
block.call
end
rescue Timeout::Error => e
puts "Failed Test"
puts caller
rescue Exception => e
puts "Failed Test"
raise e
end
end
Looking at cucumber 1.3.12 it actually rescues any exceptions from scenario steps. So you can't see them in any way without modifying cucumber gem.
See my answer on how to put a debug hook in that place for more information:
https://stackoverflow.com/a/22654786/520567
Have you tried disabling Cucumber's exception capturing with the #allow-rescue tag?
#allow-rescue: Turns off Cucumber’s exception capturing for the tagged scenario(s). Used when the code being tested is expected to raise and handle exceptions.
https://github.com/cucumber/cucumber/wiki/Tags