Module: Failbot
- Included in:
- Failbot
- Defined in:
- lib/failbot.rb,
lib/failbot/compat.rb,
lib/failbot/server.rb,
lib/failbot/version.rb,
lib/failbot/haystack.rb,
lib/failbot/middleware.rb,
lib/failbot/bert_backend.rb,
lib/failbot/file_backend.rb,
lib/failbot/http_backend.rb,
lib/failbot/json_backend.rb,
lib/failbot/heroku_backend.rb,
lib/failbot/memory_backend.rb
Overview
Failbot asynchronously takes exceptions and reports them to the exception logger du jour. Keeps the main app from failing or lagging if the exception logger service is down or slow.
Defined Under Namespace
Modules: Compat, Handler Classes: BERTBackend, FileBackend, HTTPBackend, Haystack, HerokuBackend, JSONBackend, MemoryBackend, Rescuer, Server
Constant Summary collapse
- VERSION =
"0.9.5"
Instance Attribute Summary
Attributes included from Compat
Instance Method Summary collapse
-
#context ⇒ Object
Stack of context information to include in the next failbot report.
-
#exception_info(e) ⇒ Object
Extract exception info into a simple Hash.
- #hostname ⇒ Object
-
#install_unhandled_exception_hook! ⇒ Object
Installs an at_exit hook to report exceptions that raise all the way out of the stack and halt the interpreter.
- #logger ⇒ Object
- #logger=(logger) ⇒ Object
-
#pop ⇒ Object
Remove the last info hash from the context stack.
-
#push(info = {}) ⇒ Object
Add info to be sent in the next failbot report, should one occur.
-
#report(e, other = {}) ⇒ Object
Public: Sends an exception to the exception tracking service along with a hash of custom attributes to be included with the report.
- #report!(e, other = {}) ⇒ Object
-
#reports ⇒ Object
Public: exceptions that were reported.
-
#reset! ⇒ Object
Reset the context stack to a pristine state.
-
#setup(settings = {}, default_context = {}) ⇒ Object
Public: Setup the backend for reporting exceptions.
-
#squash_context(*other) ⇒ Object
Combines all context hashes into a single hash converting non-standard data types in values to strings, then combines the result with a custom info hash provided in the other argument.
Methods included from Compat
backend!, backend_name, cast, config, config_file, default_options, default_options=, environment, fail, haystack, raise_errors=, raise_errors?, service, setup_deprecated
Instance Method Details
#context ⇒ Object
Stack of context information to include in the next failbot report. These hashes are condensed down into one and included in the next report. Don’t mess with this structure directly - use the #push and #pop methods.
71 72 73 |
# File 'lib/failbot.rb', line 71 def context @context ||= [{'server' => hostname}] end |
#exception_info(e) ⇒ Object
Extract exception info into a simple Hash.
e - The exception object to turn into a Hash.
Returns a Hash including a ‘class’, ‘message’, ‘backtrace’, and ‘rollup’
keys. The rollup value is a MD5 hash of the exception class, file, and line
number and is used to group exceptions.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/failbot.rb', line 177 def exception_info(e) backtrace = Array(e.backtrace)[0, 500] res = { 'class' => e.class.to_s, 'message' => e., 'backtrace' => backtrace.join("\n"), 'ruby' => RUBY_DESCRIPTION, 'rollup' => Digest::MD5.hexdigest("#{e.class}#{backtrace[0]}"), 'created_at' => Time.now.utc.iso8601(6) } if original = (e.respond_to?(:original_exception) && e.original_exception) remote_backtrace = [] remote_backtrace << original. if original.backtrace remote_backtrace.concat(Array(original.backtrace)[0,500]) end res['remote_backtrace'] = remote_backtrace.join("\n") end res end |
#hostname ⇒ Object
236 237 238 |
# File 'lib/failbot.rb', line 236 def hostname @hostname ||= Socket.gethostname end |
#install_unhandled_exception_hook! ⇒ Object
Installs an at_exit hook to report exceptions that raise all the way out of the stack and halt the interpreter. This is useful for catching boot time errors as well and even signal kills.
To use, call this method very early during the program’s boot to cover as much code as possible:
require 'failbot'
Failbot.install_unhandled_exception_hook!
Returns true when the hook was installed, nil when the hook had previously been installed by another component.
213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/failbot.rb', line 213 def install_unhandled_exception_hook! # only install the hook once, even when called from multiple locations return if @unhandled_exception_hook_installed # the $! is set when the interpreter is exiting due to an exception at_exit do boom = $! if boom && !@raise_errors && !boom.is_a?(SystemExit) report(boom, 'argv' => ([$0]+ARGV).join(" "), 'halting' => true) end end @unhandled_exception_hook_installed = true end |
#logger ⇒ Object
228 229 230 |
# File 'lib/failbot.rb', line 228 def logger @logger ||= Logger.new($stderr) end |
#logger=(logger) ⇒ Object
232 233 234 |
# File 'lib/failbot.rb', line 232 def logger=(logger) @logger = logger end |
#pop ⇒ Object
Remove the last info hash from the context stack.
90 91 92 |
# File 'lib/failbot.rb', line 90 def pop context.pop if context.size > 1 end |
#push(info = {}) ⇒ Object
Add info to be sent in the next failbot report, should one occur.
info - Hash of name => value pairs to include in the exception report. block - When given, the info is removed from the current context after the
block is executed.
Returns the value returned by the block when given; otherwise, returns nil.
82 83 84 85 86 87 |
# File 'lib/failbot.rb', line 82 def push(info={}) context.push(info) yield if block_given? ensure pop if block_given? end |
#report(e, other = {}) ⇒ Object
Public: Sends an exception to the exception tracking service along with a hash of custom attributes to be included with the report. When the raise_errors option is set, this method raises the exception instead of reporting to the exception tracking service.
e - The Exception object. Must respond to #message and #backtrace. other - Hash of additional attributes to include with the report.
Examples
begin
my_code
rescue => e
Failbot.report(e, :user => current_user)
end
Returns nothing.
116 117 118 119 120 121 122 123 |
# File 'lib/failbot.rb', line 116 def report(e, other = {}) if @raise_errors squash_context(exception_info(e), other) # surface problems squashing raise e else report!(e, other) end end |
#report!(e, other = {}) ⇒ Object
125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/failbot.rb', line 125 def report!(e, other = {}) data = squash_context(exception_info(e), other) backend.report(data) rescue Object => i # don't fail for any reason logger.debug "FAILBOT: #{data.inspect}" rescue nil logger.debug e. rescue nil logger.debug e.backtrace.join("\n") rescue nil logger.debug i. rescue nil logger.debug i.backtrace.join("\n") rescue nil end |
#reports ⇒ Object
Public: exceptions that were reported. Only available when using the memory and file backends.
Returns an Array of exceptions data Hash.
141 142 143 |
# File 'lib/failbot.rb', line 141 def reports backend.reports end |
#reset! ⇒ Object
Reset the context stack to a pristine state.
95 96 97 |
# File 'lib/failbot.rb', line 95 def reset! @context = [context[0]] end |
#setup(settings = {}, default_context = {}) ⇒ Object
Public: Setup the backend for reporting exceptions.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/failbot.rb', line 28 def setup(settings={}, default_context={}) deprecated_settings = %w[ backend host port haystack workers service_logs raise_errors ] if settings.empty? || settings.keys.any? { |key| deprecated_settings.include?(key) } warn "%s Deprecated Failbot.setup usage. See %s for details." % [ caller[0], "https://github.com/github/failbot" ] return setup_deprecated(settings) end if default_context.respond_to?(:to_hash) && !default_context.to_hash.empty? context[0] = default_context.to_hash end self.backend = case (name = settings["FAILBOT_BACKEND"]) when "bert" Failbot::BERTBackend.new(URI(settings["FAILBOT_BACKEND_BERT_URL"])) when "memory" Failbot::MemoryBackend.new when "file" Failbot::FileBackend.new(settings["FAILBOT_BACKEND_FILE_PATH"]) when "http" Failbot::HTTPBackend.new(URI(settings["FAILBOT_HAYSTACK_URL"])) when 'json' Failbot::JSONBackend.new(settings["FAILBOT_BACKEND_JSON_HOST"], settings["FAILBOT_BACKEND_JSON_PORT"]) else raise ArgumentError, "Unknown backend: #{name.inspect}" end @raise_errors = !settings["FAILBOT_RAISE"].to_s.empty? end |
#squash_context(*other) ⇒ Object
Combines all context hashes into a single hash converting non-standard data types in values to strings, then combines the result with a custom info hash provided in the other argument.
other - Optional array of hashes to also squash in on top of the context
stack hashes.
Returns a Hash with all keys and values.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/failbot.rb', line 153 def squash_context(*other) merged = {} (context + other).each do |hash| hash.each do |key, value| value = (value.call rescue nil) if value.kind_of?(Proc) merged[key.to_s] = case value when String, Numeric, true, false value.to_s else value.inspect end end end merged end |