Module: Interception
- Defined in:
- lib/interception.rb,
ext/interception.c
Overview
Provides global facility for monitoring exceptions raised in your application.
Class Attribute Summary collapse
-
.listeners ⇒ Object
Returns the value of attribute listeners.
-
.mutex ⇒ Object
Returns the value of attribute mutex.
-
.rescueing ⇒ Object
Returns the value of attribute rescueing.
Class Method Summary collapse
-
.listen(for_block = nil, &listen_block) {|exception, binding| ... } ⇒ Object
Listen for any exceptions raised.
-
.rescue(exception, binding) ⇒ Object
Called by platform-specific implementations whenever an exception is raised.
- .ruby_21? ⇒ Boolean
-
.start ⇒ Object
Start sending events to rescue.
-
.stop ⇒ Object
Stop sending events to rescue.
-
.unlisten(listen_block) ⇒ Object
Disable a previously added listener.
Class Attribute Details
.listeners ⇒ Object
Returns the value of attribute listeners.
8 9 10 |
# File 'lib/interception.rb', line 8 def listeners @listeners end |
.mutex ⇒ Object
Returns the value of attribute mutex.
8 9 10 |
# File 'lib/interception.rb', line 8 def mutex @mutex end |
.rescueing ⇒ Object
Returns the value of attribute rescueing.
8 9 10 |
# File 'lib/interception.rb', line 8 def rescueing @rescueing end |
Class Method Details
.listen(for_block = nil, &listen_block) {|exception, binding| ... } ⇒ Object
Listen for any exceptions raised.
The listener block that you pass in will be executed as though inside Kernel#raise, so your entire program is still actively running. If you have a gem like pry-stack_explorer you can access the stack frames that lead to the exception occurring.
NOTE: Be careful when writing a listener, if your listener raises an exception it will mask the original exception (though it will not recursively call your listener).
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/interception.rb', line 62 def self.listen(for_block=nil, &listen_block) raise ArgumentError, "no block given" unless listen_block || for_block mutex.synchronize{ start if listeners.empty? listeners << (listen_block || for_block) } if listen_block && for_block begin for_block.call ensure unlisten listen_block end else listen_block end end |
.rescue(exception, binding) ⇒ Object
101 102 103 104 105 106 107 108 109 |
# File 'lib/interception.rb', line 101 def self.rescue(exception, binding) return if rescueing self.rescueing = true listeners.each do |l| l.call(exception, binding) end ensure self.rescueing = false end |
.ruby_21? ⇒ Boolean
136 137 138 |
# File 'lib/interception.rb', line 136 def self.ruby_21? RUBY_VERSION == '2.1.0' && RUBY_ENGINE == 'ruby' end |
.start ⇒ Object
For Ruby 2.1 we use the new TracePoint API.
Start sending events to rescue. Implemented per-platform
114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/interception.rb', line 114 def self.start if ruby_21? @tracepoint ||= TracePoint.new(:raise) do |tp| self.rescue(tp.raised_exception, tp.binding) end @tracepoint.enable else raise NotImplementedError end end |
.stop ⇒ Object
Stop sending events to rescue. Implemented per-platform
128 129 130 131 132 133 134 |
# File 'lib/interception.rb', line 128 def self.stop if ruby_21? @tracepoint.disable else raise NotImplementedError end end |
.unlisten(listen_block) ⇒ Object
Disable a previously added listener
84 85 86 87 88 89 |
# File 'lib/interception.rb', line 84 def self.unlisten(listen_block) mutex.synchronize{ listeners.delete listen_block stop if listeners.empty? } end |