errorkit 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +133 -0
- data/Rakefile +60 -0
- data/config/database.yml.example +19 -0
- data/errorkit.gemspec +25 -0
- data/lib/errorkit/config.rb +46 -0
- data/lib/errorkit/engine.rb +7 -0
- data/lib/errorkit/errors_controller.rb +49 -0
- data/lib/errorkit/errors_mailer.rb +43 -0
- data/lib/errorkit/ignorable_error.rb +3 -0
- data/lib/errorkit/version.rb +3 -0
- data/lib/errorkit.rb +86 -0
- data/lib/generators/errorkit/USAGE +19 -0
- data/lib/generators/errorkit/install_generator.rb +60 -0
- data/lib/generators/errorkit/templates/app/models/error.rb +9 -0
- data/lib/generators/errorkit/templates/app/views/errors/error_notification.html.erb +7 -0
- data/lib/generators/errorkit/templates/app/views/errors/show.html.erb +13 -0
- data/lib/generators/errorkit/templates/config/initializers/errorkit.rb +84 -0
- data/lib/generators/errorkit/templates/db/migrate/create_errors.rb +38 -0
- data/lib/generators/errorkit/templates/spec/models/error_spec.rb +18 -0
- data/spec/spec_helper.rb +16 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3b3a8d7d3ae4c413ca53a1f7d0463e80ddae34db
|
4
|
+
data.tar.gz: e55ce216c6f4d957e29883a3fde546fa52bd22cf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: db9a77577712658b5af7d04aa64bca059343191d465deecad12a3b017c223cf1c8760daf8cd2fb1d770ab57693a55170d223c72fdeabd8a9414590fc9e26ab6a
|
7
|
+
data.tar.gz: 417b54060cd71254cd200e5b01729e34ea260780b056352886f99cafb9e95045a128b9809f37e42515fdd28936c6396391e06b6e2906cb70de74bf7cbb7e4a54
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Jeff Rafter
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# Errorkit
|
2
|
+
|
3
|
+
ErrorKit allows you to track errors within your application and generate a
|
4
|
+
notification when they happen.
|
5
|
+
|
6
|
+
ErrorKit is based on exception_notification and takes a similar approach. It allows
|
7
|
+
you to install Rack middleware that catches exceptions and allows you to notify a
|
8
|
+
list of recipients.
|
9
|
+
|
10
|
+
ErrorKit also allows you to record the errors to your database and resolve them
|
11
|
+
as necessary. This allows error handling to become an application concern and expects
|
12
|
+
that you will attach application specific information to the errors when possible
|
13
|
+
(such as the user that performed the action or the priority level of the error).
|
14
|
+
|
15
|
+
ErrorKit provides a generator to build the default Error model.
|
16
|
+
|
17
|
+
You can ignore specific exception classes and specific user agents. Additionally,
|
18
|
+
ErrorKit can throttle error notifications to prevent overwhelming your inbox.
|
19
|
+
|
20
|
+
Finally, ErrorKit keeps track of how many successful responses are made as well
|
21
|
+
so that it can track your error rate per server and per release.
|
22
|
+
|
23
|
+
## Installation
|
24
|
+
|
25
|
+
Add this line to your application's Gemfile:
|
26
|
+
|
27
|
+
gem 'errorkit'
|
28
|
+
|
29
|
+
And then execute:
|
30
|
+
|
31
|
+
$ bundle
|
32
|
+
|
33
|
+
Or install it yourself as:
|
34
|
+
|
35
|
+
$ gem install errorkit
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
Once you have installed the gem, you need to run the generator:
|
40
|
+
|
41
|
+
$ rails g errorkit:install
|
42
|
+
|
43
|
+
After you run the generator you need to migrate the database:
|
44
|
+
|
45
|
+
$ rails db:migrate
|
46
|
+
|
47
|
+
You can override the default configuration in config/initializers/errorkit.rb.
|
48
|
+
|
49
|
+
## Custom Views
|
50
|
+
|
51
|
+
From this point you can customize most things. Errorkit handles errors
|
52
|
+
that occur within your application and displays a corresponding template.
|
53
|
+
By default, it uses app/views/errors/error.html.erb which you should
|
54
|
+
customize. If you want to have specific templates for specific pages
|
55
|
+
you can create them by name:
|
56
|
+
|
57
|
+
bad_request.html.erb
|
58
|
+
forbidden.html.erb
|
59
|
+
internal_server_error.html.erb
|
60
|
+
method_not_allowed.html.erb
|
61
|
+
not_acceptable.html.erb
|
62
|
+
not_found.html.erb
|
63
|
+
not_implemented.html.erb
|
64
|
+
unauthorized.html.erb
|
65
|
+
unprocessable_entity.html.erb
|
66
|
+
|
67
|
+
You can extend this list of defaults as well. See
|
68
|
+
http://guides.rubyonrails.org/layouts_and_rendering.html for more information.
|
69
|
+
|
70
|
+
It is also possible to customize the notification template found at
|
71
|
+
app/views/errors/notification.html.erb.
|
72
|
+
|
73
|
+
## Custom Errors Controller
|
74
|
+
|
75
|
+
You can override the errors_controller by creating a new one in your application:
|
76
|
+
|
77
|
+
class MyController < Errorkit::ErrorsController
|
78
|
+
end
|
79
|
+
|
80
|
+
You can even make this descend from your own application controller (though
|
81
|
+
this may generate additional errors if there is a problem in your controller)
|
82
|
+
|
83
|
+
class MyController < ApplicationController
|
84
|
+
def show
|
85
|
+
# You must implement show
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
Once created, you must tell Errorkit to use this controller in the initializer:
|
90
|
+
|
91
|
+
config.errors_controller = MyController
|
92
|
+
|
93
|
+
## Custom Errors Mailer
|
94
|
+
|
95
|
+
You can override the errors_mailer by creating a new one in your application:
|
96
|
+
|
97
|
+
class MyMailer < Errorkit::ErrorsMailer
|
98
|
+
end
|
99
|
+
|
100
|
+
You can descend from ActionMailer::Base if you want to completely override the
|
101
|
+
behavior. However you must implement error_notification:
|
102
|
+
|
103
|
+
class MyMailer < ActionMailer::Base
|
104
|
+
def error_notification(error_id)
|
105
|
+
# You must implement error_notification
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
Once created, you must tell Errorkit to use this mailer in the initializer:
|
110
|
+
|
111
|
+
config.errors_mailer = MyMailer
|
112
|
+
|
113
|
+
## Contributing
|
114
|
+
|
115
|
+
1. Fork it
|
116
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
117
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
118
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
119
|
+
5. Create new Pull Request
|
120
|
+
|
121
|
+
## Acknowledgements
|
122
|
+
|
123
|
+
http://geekmonkey.org/articles/29-exception-applications-in-rails-3-2
|
124
|
+
https://github.com/sheerun/rails4-bootstrap/issues/26
|
125
|
+
https://github.com/sheerun/rails4-bootstrap/commit/5c2df5a108ad204bc407183b959bb355ff5ed53d
|
126
|
+
http://stackoverflow.com/questions/15459143/how-to-rescue-from-actiondispatchparamsparserparseerror-in-rails-4
|
127
|
+
https://github.com/mirego/gaffe
|
128
|
+
https://github.com/mirego/gaffe/blob/master/lib/gaffe/errors.rb
|
129
|
+
|
130
|
+
|
131
|
+
https://github.com/rails/rails/blob/f886fe2d8ccc900cde2629577e5c0be8c7d4c67f/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
|
132
|
+
https://github.com/rails/rails/blob/c2cb83b1447fee6cee496acd0816c0117b68b687/guides/source/layouts_and_rendering.md
|
133
|
+
http://stackoverflow.com/questions/15459143/how-to-rescue-from-actiondispatchparamsparserparseerror-in-rails-4
|
data/Rakefile
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
gem_name = :errorkit
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(spec: ["generator:cleanup", "generator:prepare", "generator:#{gem_name}"]) do |task|
|
7
|
+
task.pattern = "spec/**/*_spec.rb"
|
8
|
+
task.rspec_opts = "--color --drb"
|
9
|
+
task.verbose = true
|
10
|
+
end
|
11
|
+
|
12
|
+
namespace :spec do
|
13
|
+
RSpec::Core::RakeTask.new(database: ["generator:cleanup", "generator:prepare", "generator:database", "generator:#{gem_name}"]) do |task|
|
14
|
+
task.pattern = "spec/**/*_spec.rb"
|
15
|
+
task.verbose = true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
namespace :generator do
|
20
|
+
desc "Cleans up the sample app before running the generator"
|
21
|
+
task :cleanup do
|
22
|
+
FileUtils.rm_rf("spec/tmp/sample") if Dir.exist?("spec/tmp/sample") if ENV['SKIP_CLEANUP'].nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Prepare the sample app before running the generator"
|
26
|
+
task :prepare do
|
27
|
+
next if Dir.exist?("spec/tmp/sample")
|
28
|
+
|
29
|
+
FileUtils.mkdir_p("spec/tmp")
|
30
|
+
|
31
|
+
system "cd spec/tmp && rails new sample"
|
32
|
+
|
33
|
+
# bundle
|
34
|
+
gem_root = File.expand_path(File.dirname(__FILE__))
|
35
|
+
system "echo \"gem 'rspec-rails'\" >> spec/tmp/sample/Gemfile"
|
36
|
+
system "echo \"gem '#{gem_name}', :path => '#{gem_root}'\" >> spec/tmp/sample/Gemfile"
|
37
|
+
system "cd spec/tmp/sample && bundle install"
|
38
|
+
system "cd spec/tmp/sample && rails g rspec:install"
|
39
|
+
|
40
|
+
# Make a thing
|
41
|
+
system "cd spec/tmp/sample && rails g scaffold thing name:string mood:string"
|
42
|
+
end
|
43
|
+
|
44
|
+
# This task is not used unless you need to test the generator with an alternate database
|
45
|
+
# such as mysql or postgres. By default the sample application utilize sqlite3
|
46
|
+
desc "Prepares the application with an alternate database"
|
47
|
+
task :database do
|
48
|
+
puts "== Configuring the database =================================================="
|
49
|
+
system "cp config/database.yml.example spec/tmp/sample/config/database.yml"
|
50
|
+
system "cd spec/tmp/sample && rake db:migrate:reset"
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "Run the #{gem_name} generator"
|
54
|
+
task gem_name do
|
55
|
+
system "cd spec/tmp/sample && rails g #{gem_name}:install --force && rake db:migrate db:test:prepare"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
task :default => :spec
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file is not copied to or used by your Rails environment. The only time
|
2
|
+
# these settings are used is when you have executed rake test:database while
|
3
|
+
# running the tests for the gem (not from within Rails). This file makes
|
4
|
+
# it easy to test alternate database drivers with the gem. The
|
5
|
+
# default testing environment uses the rails default (sqlite3).
|
6
|
+
|
7
|
+
development:
|
8
|
+
adapter: mysql
|
9
|
+
database: errorkit_development
|
10
|
+
username: root
|
11
|
+
password:
|
12
|
+
host: localhost
|
13
|
+
|
14
|
+
test:
|
15
|
+
adapter: mysql
|
16
|
+
database: errorkit_test
|
17
|
+
username: root
|
18
|
+
password:
|
19
|
+
host: localhost
|
data/errorkit.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'errorkit/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "errorkit"
|
8
|
+
spec.version = Errorkit::VERSION
|
9
|
+
spec.authors = ["Jeff Rafter"]
|
10
|
+
spec.email = ["jeffrafter@gmail.com"]
|
11
|
+
spec.description = %q{ErrorKit allows you to track errors within your application and generate a notification when they happen.}
|
12
|
+
spec.summary = %q{ErrorKit allows you to track errors within your application and generate a notification when they happen.}
|
13
|
+
spec.homepage = "http://github.com/jeffrafter/errorkit"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec-rails"
|
24
|
+
spec.add_development_dependency "factory_girl_rails"
|
25
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Errorkit
|
2
|
+
class Config
|
3
|
+
attr_accessor \
|
4
|
+
:ignore_agents,
|
5
|
+
:ignore_exceptions,
|
6
|
+
:errors_class,
|
7
|
+
:errors_mailer,
|
8
|
+
:errors_controller,
|
9
|
+
:errors_layout,
|
10
|
+
:mailer_recipients,
|
11
|
+
:mailer_sender,
|
12
|
+
:max_notifications_per_minute,
|
13
|
+
:max_notifications_per_quarter_hour,
|
14
|
+
:alert_threshold
|
15
|
+
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@errors_mailer = Errorkit::ErrorsMailer
|
19
|
+
@errors_controller = Errorkit::ErrorsController
|
20
|
+
@errors_layout = false
|
21
|
+
@ignore_exceptions = []
|
22
|
+
@ignore_exceptions << ::ActiveRecord::RecordNotFound if defined? ::ActiveRecord::RecordNotFound
|
23
|
+
@ignore_exceptions << ::AbstractController::ActionNotFound if defined? ::AbstractController::ActionNotFound
|
24
|
+
@ignore_exceptions << ::ActionController::RoutingError if defined? ::ActionController::RoutingError
|
25
|
+
@ignore_agents = %w{Googlebot MSNBot Baiduspider Bing Inktomi Yahoo AskJeeves FastCrawler InfoSeek Lycos YandexBot NewRelicPinger Pingdom}
|
26
|
+
@max_notifications_per_minute = 5
|
27
|
+
@max_notifications_per_quarter_hour = 10
|
28
|
+
@alert_threshold = 0.4
|
29
|
+
end
|
30
|
+
|
31
|
+
def config
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def ignore_exception?(exception)
|
36
|
+
return false if @ignore_exceptions.nil? || @ignore_exceptions.length == 0
|
37
|
+
@ignore_exceptions.include?(exception.class)
|
38
|
+
end
|
39
|
+
|
40
|
+
def ignore_agent?(agent)
|
41
|
+
return false if @ignore_agents.nil? || @ignore_agents.length == 0
|
42
|
+
@ignore_agent_re ||= /(#{@ignore_agents.join('|')})/i
|
43
|
+
!!(agent =~ @ignore_agents_re)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Errorkit
|
2
|
+
class ErrorsController < ActionController::Base
|
3
|
+
before_filter :append_view_paths
|
4
|
+
|
5
|
+
helper_method :error, :exception, :status_code, :status_text
|
6
|
+
|
7
|
+
layout :error_layout
|
8
|
+
|
9
|
+
def show
|
10
|
+
begin
|
11
|
+
render "errors/#{rescue_response}", status: status_code
|
12
|
+
rescue ActionView::MissingTemplate
|
13
|
+
render "errors/show", status: status_code
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def error
|
20
|
+
@error ||= env['errorkit.error']
|
21
|
+
end
|
22
|
+
|
23
|
+
def exception
|
24
|
+
@exception ||= env['action_dispatch.exception']
|
25
|
+
end
|
26
|
+
|
27
|
+
def status_code
|
28
|
+
@status_code ||= ActionDispatch::ExceptionWrapper.new(env, exception).status_code
|
29
|
+
end
|
30
|
+
|
31
|
+
def status_text
|
32
|
+
Rack::Utils::HTTP_STATUS_CODES.fetch(status_code, "Internal Server Error")
|
33
|
+
end
|
34
|
+
|
35
|
+
def rescue_response
|
36
|
+
@rescue_response ||= ActionDispatch::ExceptionWrapper.rescue_responses[exception.class.name]
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def append_view_paths
|
42
|
+
append_view_path Pathname.new(File.expand_path('../../../', __FILE__)).join('lib', 'generators', 'errorkit', 'templates', 'app', 'views')
|
43
|
+
end
|
44
|
+
|
45
|
+
def error_layout
|
46
|
+
Errorkit.config.errors_layout
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'action_mailer'
|
2
|
+
|
3
|
+
module Errorkit
|
4
|
+
class ErrorsMailer < ActionMailer::Base
|
5
|
+
before_filter :append_view_paths
|
6
|
+
|
7
|
+
helper_method :error
|
8
|
+
|
9
|
+
self.mailer_name = 'errors'
|
10
|
+
|
11
|
+
def error_notification(error_id)
|
12
|
+
@error = Error.find(error_id)
|
13
|
+
|
14
|
+
mail(:to => mailer_recipients,
|
15
|
+
:from => mailer_sender,
|
16
|
+
:subject => mailer_subject) do |format|
|
17
|
+
format.html { render "#{mailer_name}/error_notification" }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def error
|
24
|
+
@error
|
25
|
+
end
|
26
|
+
|
27
|
+
def mailer_recipients
|
28
|
+
Errorkit.config.mailer_recipients
|
29
|
+
end
|
30
|
+
|
31
|
+
def mailer_sender
|
32
|
+
Errorkit.config.mailer_sender
|
33
|
+
end
|
34
|
+
|
35
|
+
def mailer_subject
|
36
|
+
"[#{error.environment || 'Error'}] #{error.exception}: #{error.message}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def append_view_paths
|
40
|
+
append_view_path Pathname.new(File.expand_path('../../../', __FILE__)).join('lib', 'generators', 'errorkit', 'templates', 'app', 'views')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/errorkit.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require "errorkit/version"
|
2
|
+
require 'errorkit/config'
|
3
|
+
require 'errorkit/ignorable_error'
|
4
|
+
require 'errorkit/errors_controller'
|
5
|
+
require 'errorkit/errors_mailer'
|
6
|
+
|
7
|
+
module Errorkit
|
8
|
+
require 'errorkit/engine' if defined?(Rails)
|
9
|
+
|
10
|
+
def self.configure(&block)
|
11
|
+
config.instance_eval(&block)
|
12
|
+
|
13
|
+
if defined?(Rails)
|
14
|
+
Rails.application.config.exceptions_app = lambda do |env|
|
15
|
+
Errorkit.server_error(env)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.config
|
21
|
+
@config ||= Errorkit::Config.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.server_error(env)
|
25
|
+
exception = env['action_dispatch.exception']
|
26
|
+
unless config.errors_class.nil? || config.ignore_exception?(exception) || config.ignore_agent?(env['HTTP_USER_AGENT'])
|
27
|
+
begin
|
28
|
+
request = ActionDispatch::Request.new(env)
|
29
|
+
error = config.errors_class.create(
|
30
|
+
server: server,
|
31
|
+
environment: environment,
|
32
|
+
version: application_version,
|
33
|
+
exception: exception.class.to_s,
|
34
|
+
message: exception.message,
|
35
|
+
backtrace: clean_backtrace(exception),
|
36
|
+
params: filtered_parameters(request).to_json,
|
37
|
+
session: filtered_session(request).to_json,
|
38
|
+
remote_ip: request.remote_ip.to_s,
|
39
|
+
controller: (env['action_controller.instance'].controller_name rescue nil),
|
40
|
+
action: (env['action_controller.instance'].action_name rescue nil))
|
41
|
+
|
42
|
+
env['errorkit.notified'] = send_notification(error)
|
43
|
+
env['errorkit.error'] = error
|
44
|
+
rescue Errorkit::IgnorableError
|
45
|
+
# noop
|
46
|
+
end
|
47
|
+
end
|
48
|
+
config.errors_controller.action(:show).call(env)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.environment
|
52
|
+
Rails.env.to_s if defined?(Rails)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.server
|
56
|
+
@server ||= `hostname`.chomp rescue nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.application_version
|
60
|
+
@version ||= `cd #{Rails.root.to_s} && git rev-parse HEAD`.chomp rescue nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.filtered_parameters(request)
|
64
|
+
request.filtered_parameters
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.filtered_session(request)
|
68
|
+
session = request.session.dup
|
69
|
+
session.delete(:session_id)
|
70
|
+
session
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.clean_backtrace(exception)
|
74
|
+
backtrace = Rails.backtrace_cleaner.send(:filter, exception.backtrace) if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner)
|
75
|
+
backtrace ||= exception.backtrace
|
76
|
+
backtrace ||= []
|
77
|
+
backtrace.join("\n")
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.send_notification(error)
|
81
|
+
return if config.mailer_recipients.blank? || config.mailer_sender.blank?
|
82
|
+
|
83
|
+
# TODO, throttle
|
84
|
+
config.errors_mailer.error_notification(error.id).deliver
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Usage:
|
2
|
+
rails generate errorkit:install [options]
|
3
|
+
|
4
|
+
Runtime options:
|
5
|
+
-f, [--force] # Overwrite files that already exist
|
6
|
+
-p, [--pretend] # Run but do not make any changes
|
7
|
+
-s, [--skip] # Skip files that already exist
|
8
|
+
-q, [--quiet] # Supress status output
|
9
|
+
|
10
|
+
Description:
|
11
|
+
ErrorKit allows you to track errors within your application and generate a
|
12
|
+
notification when they happen.
|
13
|
+
|
14
|
+
Example:
|
15
|
+
rails generate errorkit:install
|
16
|
+
|
17
|
+
This generator will create an error
|
18
|
+
model and corresponding migration. It will also install view templates
|
19
|
+
for the error notifier.
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
module Errorkit
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
|
8
|
+
desc "An error system for your Rails app"
|
9
|
+
|
10
|
+
def self.source_root
|
11
|
+
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate_errorkit
|
15
|
+
generate_migration("create_errors")
|
16
|
+
|
17
|
+
# Ensure the destination structure
|
18
|
+
empty_directory "config"
|
19
|
+
empty_directory "initializers"
|
20
|
+
empty_directory "app"
|
21
|
+
empty_directory "app/models"
|
22
|
+
empty_directory "app/views"
|
23
|
+
empty_directory "app/views/errors"
|
24
|
+
empty_directory "spec"
|
25
|
+
empty_directory "spec/models"
|
26
|
+
empty_directory "spec/mailers"
|
27
|
+
empty_directory "lib"
|
28
|
+
|
29
|
+
# Fill out some templates (for now, this is just straight copy)
|
30
|
+
template "config/initializers/errorkit.rb", "config/initializers/errorkit.rb"
|
31
|
+
template "app/models/error.rb", "app/models/error.rb"
|
32
|
+
template "spec/models/error_spec.rb", "spec/models/error_spec.rb"
|
33
|
+
|
34
|
+
# Don't treat these like templates
|
35
|
+
copy_file "app/views/errors/error_notification.html.erb", "app/views/errors/error_notification.html.erb"
|
36
|
+
copy_file "app/views/errors/show.html.erb", "app/views/errors/show.html.erb"
|
37
|
+
|
38
|
+
# RSpec needs to be in the development group to be used in generators
|
39
|
+
gem_group :test, :development do
|
40
|
+
gem "rspec-rails"
|
41
|
+
gem "shoulda-matchers"
|
42
|
+
gem 'factory_girl_rails'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.next_migration_number(dirname)
|
47
|
+
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def generate_migration(filename)
|
53
|
+
if self.class.migration_exists?("db/migrate", "#{filename}")
|
54
|
+
say_status "skipped", "Migration #{filename}.rb already exists"
|
55
|
+
else
|
56
|
+
migration_template "db/migrate/#{filename}.rb", "db/migrate/#{filename}.rb"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<!--[if IE 8]> <html lang="en" class="ie ie8 lt-ie9"> <![endif]-->
|
3
|
+
<!--[if IE 9]> <html lang="en" class="ie ie9"> <![endif]-->
|
4
|
+
<!--[if gt IE 9]><!--> <html lang="en"> <!--<![endif]-->
|
5
|
+
<head>
|
6
|
+
<title><%= status_code %> Error</title>
|
7
|
+
<meta charset="utf-8">
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
9
|
+
</head>
|
10
|
+
<body>
|
11
|
+
The server encountered an error: <%= status_code %> (<%= status_text %>)
|
12
|
+
</body>
|
13
|
+
</html>
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Configure Errorkit to display custom error pages and deliver error notifications.
|
2
|
+
#
|
3
|
+
# To view the errors in development you must change config/environments/development.rb:
|
4
|
+
#
|
5
|
+
# config.consider_all_requests_local = false
|
6
|
+
#
|
7
|
+
Errorkit.configure do
|
8
|
+
# Many bots create errors spidering your site. You may want to ignore those. By
|
9
|
+
# default the following bots are ignored:
|
10
|
+
#
|
11
|
+
# config.ignore_agents = %w{
|
12
|
+
# Googlebot MSNBot Baiduspider Bing Inktomi Yahoo AskJeeves FastCrawler
|
13
|
+
# InfoSeek Lycos YandexBot NewRelicPinger Pingdom
|
14
|
+
# }
|
15
|
+
#
|
16
|
+
# If you do not want to ignore bots set the ignore_agents to an empty array
|
17
|
+
#
|
18
|
+
# config,ignore_agents = []
|
19
|
+
|
20
|
+
|
21
|
+
# Some exceptions should be expected and you don't want to be notified when they
|
22
|
+
# occur. By default the following exceptions are ignored:
|
23
|
+
#
|
24
|
+
# config.ignore_exceptions = [
|
25
|
+
# ActiveRecord::RecordNotFound,
|
26
|
+
# AbstractController::ActionNotFound,
|
27
|
+
# ActionController::RoutingError
|
28
|
+
# ]
|
29
|
+
#
|
30
|
+
# If you want to be notified of all errors set ignore_exceptions to an empty
|
31
|
+
# array:
|
32
|
+
#
|
33
|
+
# config.ignore_exceptions = []
|
34
|
+
|
35
|
+
# The recipients you want to notify when there is an error. If you leave this
|
36
|
+
# blank then notifications will not be sent.
|
37
|
+
config.mailer_recipients = ["you@example.com"]
|
38
|
+
|
39
|
+
# The sender of the error notifications. If you leave this blank then
|
40
|
+
# notifications will not be sent.
|
41
|
+
config.mailer_sender = ["errors@example.com"]
|
42
|
+
|
43
|
+
# Overriding the default error pages allows you to customize their look
|
44
|
+
# and feel but still have them served through your application. You can
|
45
|
+
# override the view templates by creating new template within you
|
46
|
+
# app/views/errors folder. If you want to change the layout used when
|
47
|
+
# rendering the views, set:
|
48
|
+
#
|
49
|
+
# config.errors_layout = 'application'
|
50
|
+
#
|
51
|
+
# By default, no layout is used (layout is false).
|
52
|
+
|
53
|
+
# By default, Errorkit sends notifications with its own mailer. To override
|
54
|
+
# this, set:
|
55
|
+
#
|
56
|
+
# config.errors_mailer = MyMailer
|
57
|
+
|
58
|
+
# By default, Errorkit responds to errors with its own controller. To override
|
59
|
+
# this, set:
|
60
|
+
#
|
61
|
+
# config.errors_controller = MyController
|
62
|
+
|
63
|
+
|
64
|
+
# To persist errors, you must specify a class that acts like an ActiveRecord
|
65
|
+
# model. If errors_class is not set, errors will not be persisted.
|
66
|
+
config.errors_class = Error
|
67
|
+
|
68
|
+
# Getting hundreds or thousands of error notifications is not fun. You
|
69
|
+
# can set a max number of notifiactions per minute and per fifteen
|
70
|
+
# minutes:
|
71
|
+
#
|
72
|
+
# config.max_notifications_per_minute = 5
|
73
|
+
# config.max_notifications_per_quarter_hour = 10
|
74
|
+
#
|
75
|
+
# To turn off throttling set these values to nil
|
76
|
+
|
77
|
+
|
78
|
+
# It is possible to create alerts that occur only when the number of
|
79
|
+
# errors per request exceeds a specific percentage.
|
80
|
+
#
|
81
|
+
# config.alert_threshold = 0.4
|
82
|
+
#
|
83
|
+
# To turn off error rate alerts, set this to nil
|
84
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Generated by Errorkit.
|
2
|
+
#
|
3
|
+
# Create an errors table for managing errors.
|
4
|
+
class CreateErrors < ActiveRecord::Migration
|
5
|
+
def self.up
|
6
|
+
create_table :errors do |t|
|
7
|
+
t.string :environment
|
8
|
+
t.string :server
|
9
|
+
t.string :version
|
10
|
+
t.string :exception
|
11
|
+
t.string :message
|
12
|
+
t.text :backtrace
|
13
|
+
t.string :controller
|
14
|
+
t.string :action
|
15
|
+
t.string :remote_ip
|
16
|
+
t.text :session
|
17
|
+
t.text :params
|
18
|
+
t.string :worker
|
19
|
+
t.string :queue
|
20
|
+
t.string :payload
|
21
|
+
t.string :url
|
22
|
+
t.integer :user_id
|
23
|
+
t.integer :subject_id
|
24
|
+
t.string :subject_type
|
25
|
+
t.datetime :resolved_at
|
26
|
+
|
27
|
+
t.timestamps
|
28
|
+
end
|
29
|
+
|
30
|
+
add_index :errors, :exception
|
31
|
+
add_index :errors, :created_at
|
32
|
+
add_index :errors, :resolved_at
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.down
|
36
|
+
drop_table :errors
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Error do
|
4
|
+
let(:error) { Error.new }
|
5
|
+
|
6
|
+
it "resolves errors" do
|
7
|
+
now = Time.now
|
8
|
+
Time.stub(:now).and_return(now)
|
9
|
+
error.should_receive(:update_attribute).with(:resolved_at, now)
|
10
|
+
error.resolve!
|
11
|
+
end
|
12
|
+
|
13
|
+
it "does not resolve already resolved errors" do
|
14
|
+
error.should_not_receive(:update_attribute)
|
15
|
+
error.resolved_at = Time.now
|
16
|
+
error.resolve!
|
17
|
+
end
|
18
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
ENV["RAILS_ENV"] ||= 'test'
|
2
|
+
require File.expand_path('../tmp/sample/config/environment', __FILE__)
|
3
|
+
require 'rspec/rails'
|
4
|
+
require 'rspec/autorun'
|
5
|
+
|
6
|
+
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
7
|
+
|
8
|
+
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.use_transactional_fixtures = true
|
12
|
+
config.infer_base_class_for_anonymous_controllers = false
|
13
|
+
config.order = "random"
|
14
|
+
# Because we are not running things in Rails we need to stub some secrets
|
15
|
+
config.before(:each) { Rails.application.config.stub(:secret_token).and_return("SECRET") }
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: errorkit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeff Rafter
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-11-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: factory_girl_rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: ErrorKit allows you to track errors within your application and generate
|
70
|
+
a notification when they happen.
|
71
|
+
email:
|
72
|
+
- jeffrafter@gmail.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- config/database.yml.example
|
83
|
+
- errorkit.gemspec
|
84
|
+
- lib/errorkit.rb
|
85
|
+
- lib/errorkit/config.rb
|
86
|
+
- lib/errorkit/engine.rb
|
87
|
+
- lib/errorkit/errors_controller.rb
|
88
|
+
- lib/errorkit/errors_mailer.rb
|
89
|
+
- lib/errorkit/ignorable_error.rb
|
90
|
+
- lib/errorkit/version.rb
|
91
|
+
- lib/generators/errorkit/USAGE
|
92
|
+
- lib/generators/errorkit/install_generator.rb
|
93
|
+
- lib/generators/errorkit/templates/app/models/error.rb
|
94
|
+
- lib/generators/errorkit/templates/app/views/errors/error_notification.html.erb
|
95
|
+
- lib/generators/errorkit/templates/app/views/errors/show.html.erb
|
96
|
+
- lib/generators/errorkit/templates/config/initializers/errorkit.rb
|
97
|
+
- lib/generators/errorkit/templates/db/migrate/create_errors.rb
|
98
|
+
- lib/generators/errorkit/templates/spec/models/error_spec.rb
|
99
|
+
- spec/spec_helper.rb
|
100
|
+
homepage: http://github.com/jeffrafter/errorkit
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
metadata: {}
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
requirements: []
|
119
|
+
rubyforge_project:
|
120
|
+
rubygems_version: 2.0.3
|
121
|
+
signing_key:
|
122
|
+
specification_version: 4
|
123
|
+
summary: ErrorKit allows you to track errors within your application and generate
|
124
|
+
a notification when they happen.
|
125
|
+
test_files:
|
126
|
+
- spec/spec_helper.rb
|