failbot_rails 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +65 -0
- data/failbot_rails.gemspec +21 -0
- data/lib/failbot_rails.rb +146 -0
- metadata +64 -0
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# failbot_rails
|
2
|
+
|
3
|
+
Configures a Rails application to report exceptions to [Haystack][] using the
|
4
|
+
[Failbot][] library.
|
5
|
+
|
6
|
+
[Haystack]: https://haystack.githubapp.com
|
7
|
+
[Failbot]: https://github.com/github/failbot
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add it to the app's Gemfile manifest. The gem is publicly available but **keep
|
12
|
+
this repository private.**
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem "failbot_rails", "~>0.2"
|
16
|
+
```
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
Require `failbot_rails` at the very top of `config/application.rb` right after
|
21
|
+
loading `boot.rb`:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require File.expand_path('../boot', __FILE__)
|
25
|
+
|
26
|
+
# report exceptions to Haystack using Failbot
|
27
|
+
require "failbot_rails"
|
28
|
+
FailbotRails.setup("my_app")
|
29
|
+
```
|
30
|
+
|
31
|
+
Every library, script or unicorn that loads the Rails environment are now setup
|
32
|
+
to automatically report all exceptions to Haystack.
|
33
|
+
|
34
|
+
### `failbot_context`
|
35
|
+
|
36
|
+
The exception context is automatically populated with request metadata including
|
37
|
+
the URL, method, params, etc. It can be augmented by defining a` failbot_context`
|
38
|
+
method on `ApplicationController`:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
def failbot_context
|
42
|
+
{:repo => current_repository.name_with_owner}
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
### `failbot(exception, context={})`
|
47
|
+
|
48
|
+
Use the `failbot` helper anywhere in controllers, views or helpers to manually
|
49
|
+
rescue and report an exception. Often used in "graceful degradation" situations.
|
50
|
+
**Often risky and error prone but sometimes worth it. Consider carefully before
|
51
|
+
using.**
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
def load_tree
|
55
|
+
current_repository.tree(params[:tree])
|
56
|
+
rescue TreeCorruptError
|
57
|
+
failbot($!)
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
## Contributing
|
63
|
+
|
64
|
+
The failbot_rails project follows the open source contribution model and is
|
65
|
+
maintained by @sr. Open a pull request and wait for a :+1:
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "failbot_rails"
|
5
|
+
s.version = "0.3.1"
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.authors = %w[@sr]
|
8
|
+
s.email = ["sr@github.com"]
|
9
|
+
s.homepage = "https://github.com/github/failbot_rails#readme"
|
10
|
+
s.summary = "Glue code for using Failbot in a Rails app"
|
11
|
+
s.description = s.summary
|
12
|
+
|
13
|
+
s.required_rubygems_version = ">= 1.3.6"
|
14
|
+
|
15
|
+
s.add_runtime_dependency "failbot", "~>0.9.0"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n") - %w[Gemfile Gemfile.lock]
|
18
|
+
s.test_files = `git ls-files -- test`.split("\n").select { |f| f =~ /_test.rb$/ }
|
19
|
+
s.executables = `git ls-files -- bin`.split("\n").map { |f| File.basename(f) }
|
20
|
+
s.require_paths = %w[lib]
|
21
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require "failbot"
|
2
|
+
require "failbot/middleware"
|
3
|
+
|
4
|
+
require "rails"
|
5
|
+
require "rails/railtie"
|
6
|
+
require "active_support/concern"
|
7
|
+
|
8
|
+
module FailbotRails
|
9
|
+
def self.setup(app_name)
|
10
|
+
if _setup
|
11
|
+
fail "FailbotRails already setup"
|
12
|
+
end
|
13
|
+
|
14
|
+
if !app_name.respond_to?(:to_str) || app_name.to_str.empty?
|
15
|
+
raise ArgumentError, "app_name argument is required"
|
16
|
+
end
|
17
|
+
|
18
|
+
settings = ENV.to_hash
|
19
|
+
|
20
|
+
# sensible defaults
|
21
|
+
if Rails.env.development? || Rails.env.test?
|
22
|
+
settings["FAILBOT_BACKEND"] ||= "memory"
|
23
|
+
|
24
|
+
if !settings.key?("FAILBOT_RAISE")
|
25
|
+
settings["FAILBOT_RAISE"] = "1"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Failbot.setup(settings, {:app => app_name.to_str})
|
30
|
+
Failbot.install_unhandled_exception_hook!
|
31
|
+
|
32
|
+
@_setup = true
|
33
|
+
end
|
34
|
+
|
35
|
+
class << self
|
36
|
+
attr_reader :_setup
|
37
|
+
end
|
38
|
+
|
39
|
+
class Engine < Rails::Railtie
|
40
|
+
initializer "failbot_rails.assert_setup" do |app|
|
41
|
+
app.config.before_initialize do
|
42
|
+
if !::FailbotRails._setup
|
43
|
+
fail "FailbotRails must be setup like so: FailbotRails.setup(\"my_app\")"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
initializer "failbot_rails.install_middleware" do |app|
|
49
|
+
app.middleware.insert_after \
|
50
|
+
::ActionDispatch::DebugExceptions,
|
51
|
+
::FailbotRails::Middleware
|
52
|
+
end
|
53
|
+
|
54
|
+
initializer "failbot_rails.install_action_controller_utilities" do |app|
|
55
|
+
app.config.to_prepare do
|
56
|
+
ActiveSupport.on_load(:action_controller) do
|
57
|
+
include ::FailbotRails::ActionControllerUtilities
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Middleware < ::Failbot::Rescuer
|
64
|
+
def initialize(app)
|
65
|
+
@app = app
|
66
|
+
end
|
67
|
+
|
68
|
+
def call(env)
|
69
|
+
request = Rack::Request.new(env)
|
70
|
+
@app.call(env)
|
71
|
+
rescue Exception
|
72
|
+
context = {
|
73
|
+
:method => request.request_method,
|
74
|
+
:url => request.url,
|
75
|
+
:user_agent => request.env["HTTP_USER_AGENT"],
|
76
|
+
:params => request.params,
|
77
|
+
:session => (request.session.to_hash rescue nil),
|
78
|
+
:referrer => request.referrer,
|
79
|
+
:remote_ip => request.ip,
|
80
|
+
}
|
81
|
+
Failbot.report($!, ::FailbotRails._failbot_safe_context(context))
|
82
|
+
raise
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def self._failbot_safe_context(context)
|
87
|
+
new_context = {}.merge(context)
|
88
|
+
filters = Rails.application.config.filter_parameters
|
89
|
+
filter = ActionDispatch::Http::ParameterFilter.new(filters)
|
90
|
+
|
91
|
+
if new_context.key?(:params)
|
92
|
+
new_context[:params] = filter.filter(new_context[:params])
|
93
|
+
end
|
94
|
+
|
95
|
+
new_context
|
96
|
+
end
|
97
|
+
|
98
|
+
module ActionControllerUtilities
|
99
|
+
extend ActiveSupport::Concern
|
100
|
+
|
101
|
+
included do
|
102
|
+
# reset context before populating it with rails-specific info
|
103
|
+
before_filter :_failbot_rails
|
104
|
+
|
105
|
+
helper_method :failbot
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def failbot(e, context={})
|
111
|
+
if e.kind_of?(ActionView::TemplateError) && e.respond_to?(:original_exception)
|
112
|
+
# exceptions raised from views are wrapped in TemplateError. This is the
|
113
|
+
# most annoying thing ever.
|
114
|
+
e = e.original_exception
|
115
|
+
end
|
116
|
+
|
117
|
+
if e.respond_to?(:info) && e.info.is_a?(Hash)
|
118
|
+
context = e.info.merge(context || {})
|
119
|
+
end
|
120
|
+
|
121
|
+
Failbot.report(e, ::FailbotRails._failbot_safe_context(context))
|
122
|
+
end
|
123
|
+
|
124
|
+
def _failbot_rails
|
125
|
+
# clear context before every request
|
126
|
+
Failbot.reset!
|
127
|
+
|
128
|
+
context = {
|
129
|
+
:controller => params[:controller],
|
130
|
+
:action => params[:action],
|
131
|
+
:user => lambda {
|
132
|
+
respond_to?(:current_user) &&
|
133
|
+
current_user.respond_to?(:login) &&
|
134
|
+
current_user.login
|
135
|
+
},
|
136
|
+
}
|
137
|
+
|
138
|
+
# allow overriding context by defining ApplicationController#failbot_context
|
139
|
+
if respond_to?(:failbot_context) && failbot_context.respond_to?(:to_hash)
|
140
|
+
context.merge!(failbot_context.to_hash)
|
141
|
+
end
|
142
|
+
|
143
|
+
Failbot.push(::FailbotRails._failbot_safe_context(context))
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: failbot_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- ! '@sr'
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: failbot
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.9.0
|
30
|
+
description: Glue code for using Failbot in a Rails app
|
31
|
+
email:
|
32
|
+
- sr@github.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- README.md
|
38
|
+
- failbot_rails.gemspec
|
39
|
+
- lib/failbot_rails.rb
|
40
|
+
homepage: https://github.com/github/failbot_rails#readme
|
41
|
+
licenses: []
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 1.3.6
|
58
|
+
requirements: []
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.8.23
|
61
|
+
signing_key:
|
62
|
+
specification_version: 3
|
63
|
+
summary: Glue code for using Failbot in a Rails app
|
64
|
+
test_files: []
|