What is this? #
ExceptionManager
is a gem for getting extra information from your exception.
Source code: https://github.com/iliabylich/exception_manager
With this gem every time when you get an exception, it’s possible to grab subject
of exception (the instance of class where raise
happened), locals
- local variables, subject_instance_variables
and subject_class_variables
Examples:
require 'exception_manager' ExceptionManager.enable! class TestClassThatRaisesException @@class_variable = :class_value def test_error(*args) @instance_variable = :instance_value raise 'Test error' end end begin TestClassThatRaisesException.new.test_error(1, 2, 3) rescue => e puts "Subject: #{e.subject}" puts "Locals: #{e.locals}" puts "Instance variables: #{e.subject_instance_variables}" puts "Class variables: #{e.subject_class_variables}" puts "Summary: #{e.summary.inspect}" end
This code snippet prints:
Subject: #<TestClassThatRaisesException:0x00000001512268> Locals: {:args=>[1, 2, 3]} Instance variables: {:@instance_variable=>:instance_value} Class variables: {:@@class_variable=>:class_value} Summary: { :locals => { :klass => TestClassThatRaisesException, :args=> [1, 2, 3] }, :subject => #<TestClassThatRaisesException:0x00000001512268>, :subject_instance_variables => { :@instance_variable => :instance_value }, :subject_class_variables => { :@@class_variable => :class_value } }
So, you can get local variables of you exception, instance where it happened and the whole context.
If you have pry
installed, you can inject pry session into stored binding:
begin TestClassThatRaisesException.new.test_error(1, 2, 3) rescue => e e._binding.pry end
Integration with NewRelic #
Just use the following snippet:
class StandardError def original_exception message_for_new_relic = [message, summary.inspect].join(' ') self.exception(message_for_new_relic) end end
NewRelic gem by default calls .original_exception.to_s
on every caught exception. Yes, looks dirty, but saves a lot of time!
How it works #
In old versions of ruby there was a Kernel
method called set_trace_func
which allows to set trigger for every executed line (including c-calls).
Ruby 2.0.0 (and newer) has a class called TracePoint
which allows to subscribe to any specific method call (raise
in our case).
So, simplified version of the main code looks like:
class Exception attr_accessor :_binding end TracePoint.new(:raise) do |tp| tp.raised_exception._binding = tp.binding end
And then we can get everything through this binding
Compatibility #
ExceptionManager
is compatible (and tested on Travis CI) with the following versions of ruby
- 2.0.0
- 2.1.0
- 2.2.0
(In other words, in all versions of ruby that has TracePoint
class).
Questions #
If you have any questions/suggestions feel free to create an issue on GitHub .