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 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