errorkit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ spec/tmp
16
+ spec/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in errorkit.gemspec
4
+ gemspec
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,7 @@
1
+ require 'rails'
2
+
3
+ module Errorkit
4
+ class Engine < Rails::Engine
5
+ end
6
+ end
7
+
@@ -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
@@ -0,0 +1,3 @@
1
+ module Errorkit
2
+ class IgnorableError < RuntimeError; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module Errorkit
2
+ VERSION = "0.0.1"
3
+ 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,9 @@
1
+ class Error < ActiveRecord::Base
2
+ scope :unresolved, -> { where("resolved_at IS NULL") }
3
+
4
+ def resolve!
5
+ return true if self.resolved_at.present?
6
+
7
+ self.update_attribute(:resolved_at, Time.now)
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ There was an error:
2
+
3
+ <%= error.exception %>
4
+
5
+ <p>
6
+ <%= error.message %>
7
+ </p>
@@ -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
@@ -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