errorapp_notifier 0.1.0

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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/MIT-LICENSE +25 -0
  6. data/README.md +60 -0
  7. data/Rakefile +8 -0
  8. data/errorapp_notifier.gemspec +29 -0
  9. data/lib/errorapp_notifier/action_controller_methods.rb +35 -0
  10. data/lib/errorapp_notifier/application_environment_data.rb +77 -0
  11. data/lib/errorapp_notifier/config.rb +67 -0
  12. data/lib/errorapp_notifier/controller_failure_data.rb +96 -0
  13. data/lib/errorapp_notifier/exception_data.rb +19 -0
  14. data/lib/errorapp_notifier/failure_data.rb +87 -0
  15. data/lib/errorapp_notifier/monkeypatches.rb +11 -0
  16. data/lib/errorapp_notifier/notifier.rb +80 -0
  17. data/lib/errorapp_notifier/notifiers/rack_rails.rb +32 -0
  18. data/lib/errorapp_notifier/notifiers/rails.rb +34 -0
  19. data/lib/errorapp_notifier/notifiers/tester.rb +16 -0
  20. data/lib/errorapp_notifier/notify.rb +59 -0
  21. data/lib/errorapp_notifier/rack_failure_data.rb +29 -0
  22. data/lib/errorapp_notifier/railtie.rb +48 -0
  23. data/lib/errorapp_notifier/sanitizer.rb +56 -0
  24. data/lib/errorapp_notifier/tasks/errorapp_notifier.rake +6 -0
  25. data/lib/errorapp_notifier/version.rb +3 -0
  26. data/lib/errorapp_notifier.rb +74 -0
  27. data/lib/generators/errorapp_notifier/errorapp_notifier_generator.rb +54 -0
  28. data/lib/generators/errorapp_notifier/templates/errorapp_notifier.rb +2 -0
  29. data/spec/errorapp_notifier/config_spec.rb +76 -0
  30. data/spec/errorapp_notifier/controller_failure_data_spec.rb +277 -0
  31. data/spec/errorapp_notifier/failure_data_spec.rb +32 -0
  32. data/spec/errorapp_notifier/notifier_spec.rb +31 -0
  33. data/spec/errorapp_notifier/notify_spec.rb +128 -0
  34. data/spec/errorapp_notifier/rack_failure_data_spec.rb +87 -0
  35. data/spec/errorapp_notifier/sanitizer_spec.rb +57 -0
  36. data/spec/helper.rb +12 -0
  37. data/spec/spec_helper.rb +16 -0
  38. metadata +188 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 73aabada015e5a366a71f919330dbda250a796b6
4
+ data.tar.gz: 81180c1a660b66aa8e2968245bef973665fdabb4
5
+ SHA512:
6
+ metadata.gz: 454ba40d8c73c1cdd81a1081c77e221bf41884ccd3b3afa0024daecb15882199635ec80622338a0eb9e3bb64e383b27dc83b9e0ffd178381f188a5e63cb400c8
7
+ data.tar.gz: 7bf777670b0e10f70c8dfdb2ea1ba5ca29453f28b7ed35adbacf52b42b46e2758637042275d20de4a9a016fe3b3061fd7b90702ce7e569264336c87b96c7d58c
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ tmp
2
+ log
3
+ Gemfile.lock
4
+ pkg
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in errorapp_notifier.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) 2012-2013, ErrorApp
2
+
3
+ NOTE: Few code ideas are copyright Exceptional DBA Airbrake.io was available
4
+ under the MIT license (listed below) on or before May 1, 2013.
5
+
6
+ Permission is hereby granted, free of charge, to any person
7
+ obtaining a copy of this software and associated documentation
8
+ files (the "Software"), to deal in the Software without
9
+ restriction, including without limitation the rights to use,
10
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the
12
+ Software is furnished to do so, subject to the following
13
+ conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ ErrorApp
2
+ ===============
3
+
4
+ This is the notifier gem for integrating apps with ErrorApp.
5
+
6
+ When an exception occurs, ErrorappNotifier will POST the relevant data to the ErrorApp server specified in your environment.
7
+
8
+ ## Rails Installation
9
+
10
+ Add the ErrorappNotifier gem to your gemfile:
11
+
12
+ ```ruby
13
+ gem 'errorapp_notifier'
14
+ ```
15
+ Install the gem
16
+ ```ruby
17
+ bundle install
18
+ ```
19
+ Then run the our generator which will create a initializer file
20
+ `errorapp_notifier.rb`
21
+ ```ruby
22
+ rails generate errorapp_notifier --api_key <Your Project Api Key>
23
+ ```
24
+
25
+ OR you can manually create initializer file and put below code snippet in that file
26
+ ```ruby
27
+ ErrorappNotifier.configure do|config|
28
+ config.api_key = 'api key'
29
+ end
30
+ ```
31
+
32
+ ##Testing Integration
33
+
34
+ To test that errorapp_notifier is properly installed run below rake task
35
+ ```ruby
36
+ rake errorapp_notifier:test_exception
37
+ ```
38
+ A test exception will be sent to your ErrorApp dashboard if everything is configured correctly.
39
+
40
+ ## Contributing
41
+
42
+ 1. Fork it.
43
+ 2. Create a topic branch `git checkout -b my_branch`
44
+ 3. Commit your changes `git commit -am "Boom"`
45
+ 3. Push to your branch `git push origin my_branch`
46
+ 4. Send a [pull request](https://github.com/errorapp/errorapp_notifier/pulls)
47
+
48
+ ## Credits
49
+
50
+ Idea from various Apps.
51
+
52
+ Thanks to
53
+
54
+ 1. Airbrake
55
+ 2. Exceptional
56
+
57
+ ## License
58
+
59
+ ErrorApp is Copyright 2014 © ErrorApp. It is free software, and
60
+ may be redistributed under the terms specified in the MIT-LICENSE file.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.pattern = "spec/errorapp_notifier/**/*_spec.rb"
6
+ end
7
+
8
+ task :default => [:spec]
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'errorapp_notifier/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "errorapp_notifier"
8
+ spec.version = ErrorappNotifier::VERSION
9
+ spec.authors = ["Rashmi"]
10
+ spec.email = ["rays.rashmi@gmail.com"]
11
+ spec.description = %q{ Notifier for sending errors to ErrorApp }
12
+ spec.summary = %q{ ErrorApp is a webapp for monitoring exceptions and other failures in your live applications. }
13
+ spec.homepage = "http://errorapp.com"
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{^(spec)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler"
22
+ spec.add_development_dependency "actionpack", "~> 3.2"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "rspec", "2.14"
25
+ spec.add_development_dependency "webmock"
26
+ spec.add_development_dependency "json"
27
+
28
+ spec.add_dependency "rack"
29
+ end
@@ -0,0 +1,35 @@
1
+ module ErrorappNotifier
2
+ module ActionControllerMethods
3
+ def rescue_with_errorapp(exception)
4
+ unless exception_handled_by_rescue_from?(exception)
5
+ notify_with_controller(exception)
6
+ ErrorappNotifier.context.clear!
7
+ end
8
+ end
9
+
10
+ def errorapp_rescue(context=nil, &block)
11
+ begin
12
+ ErrorappNotifier.context(context) unless context.nil?
13
+ block.call
14
+ rescue Exception => exception
15
+ notify_with_controller(exception)
16
+ ensure
17
+ ErrorappNotifier.context.clear!
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def notify_with_controller(exception)
24
+ ErrorappNotifier::Notify.notify_with_controller(
25
+ exception,
26
+ self,
27
+ request
28
+ )
29
+ end
30
+
31
+ def exception_handled_by_rescue_from?(exception)
32
+ respond_to?(:handler_for_rescue) && handler_for_rescue(exception)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,77 @@
1
+ class ApplicationEnvironmentData
2
+ attr_reader :exception
3
+
4
+ def initialize(exception)
5
+ @exception = exception
6
+ end
7
+
8
+ def data
9
+ {
10
+ :application_environment =>
11
+ {
12
+ :environment => application_environment,
13
+ :env => extract_environment(ENV),
14
+ :host => get_hostname,
15
+ :run_as_user => get_username,
16
+ :application_root_directory => application_root_directory,
17
+ :language => 'ruby',
18
+ :language_version => language_version_string,
19
+ :libraries_loaded => libraries_loaded
20
+ }
21
+ }
22
+ end
23
+
24
+ private
25
+
26
+ def application_root_directory
27
+ (application_root.to_s.respond_to?(:force_encoding) ?
28
+ application_root.to_s.force_encoding("UTF-8") : application_root)
29
+ end
30
+
31
+ def application_environment
32
+ config.application_environment
33
+ end
34
+
35
+ def application_root
36
+ config.application_root
37
+ end
38
+
39
+ def config
40
+ ErrorappNotifier.configuration
41
+ end
42
+
43
+ def extract_environment(env)
44
+ env.reject do |k, v|
45
+ is_http_header = (k =~ /^HTTP_/)
46
+ is_filtered = ErrorappNotifier::ENVIRONMENT_FILTER.include?(k)
47
+ matches_whitelist = ErrorappNotifier::ENVIRONMENT_WHITELIST.
48
+ any? do |whitelist_filter|
49
+ whitelist_filter === k
50
+ end
51
+ is_http_header || is_filtered || !matches_whitelist
52
+ end
53
+ end
54
+
55
+ def get_hostname
56
+ require 'socket' unless defined?(Socket)
57
+ Socket.gethostname
58
+ rescue
59
+ 'UNKNOWN'
60
+ end
61
+
62
+ def get_username
63
+ ENV['LOGNAME'] || ENV['USER'] || ENV['USERNAME'] || ENV['APACHE_RUN_USER'] || 'UNKNOWN'
64
+ end
65
+
66
+ def language_version_string
67
+ "#{RUBY_VERSION rescue '?.?.?'} p#{RUBY_PATCHLEVEL rescue '???'} #{RUBY_RELEASE_DATE rescue '????-??-??'} #{RUBY_PLATFORM rescue '????'}"
68
+ end
69
+
70
+ def libraries_loaded
71
+ begin
72
+ return Hash[*Gem.loaded_specs.map{|name, gem_specification| [name, gem_specification.version.to_s]}.flatten]
73
+ rescue
74
+ end
75
+ {}
76
+ end
77
+ end
@@ -0,0 +1,67 @@
1
+ module ErrorappNotifier
2
+ class Config
3
+ attr_accessor :api_key
4
+ attr_accessor :disabled_by_default
5
+ attr_accessor :environment_name
6
+ attr_accessor :http_open_timeout
7
+ attr_accessor :http_proxy_host
8
+ attr_accessor :http_proxy_password
9
+ attr_accessor :http_proxy_port
10
+ attr_accessor :http_proxy_username
11
+ attr_accessor :http_read_timeout
12
+ attr_accessor :ignore_exceptions
13
+ attr_accessor :ignore_user_agents
14
+ attr_accessor :logger
15
+ attr_accessor :params_filters
16
+ attr_accessor :project_root
17
+ attr_accessor :remote_host
18
+ attr_accessor :remote_port
19
+ attr_accessor :ssl
20
+
21
+ DEFAULT_IGNORE_EXCEPTIONS = ['ActiveRecord::RecordNotFound',
22
+ 'ActionController::RoutingError',
23
+ 'ActionController::InvalidAuthenticityToken',
24
+ 'CGI::Session::CookieStore::TamperedWithCookie',
25
+ 'ActionController::UnknownAction',
26
+ 'AbstractController::ActionNotFound',
27
+ 'ActionController::UnknownFormat',
28
+ 'Mongoid::Errors::DocumentNotFound',
29
+ 'Sinatra::NotFound',
30
+ "SystemExit",
31
+ "SignalException"].freeze
32
+
33
+ DEFAULT_PARAMS_FILTERS = %w(password password_confirmation).freeze
34
+
35
+ alias_method :ssl?, :ssl
36
+
37
+ def initialize
38
+ @api_key = ENV['ERRORAPP_API_KEY']
39
+ @disabled_by_default = %w(development test)
40
+ @http_open_timeout = 2
41
+ @http_read_timeout = 4
42
+ @ignore_exceptions = DEFAULT_IGNORE_EXCEPTIONS
43
+ @ignore_user_agents = []
44
+ @logger = Logger.new(STDOUT)
45
+ @params_filters = DEFAULT_PARAMS_FILTERS
46
+ @remote_host = "errorapp.com"
47
+ @remote_port = nil
48
+ @ssl = true
49
+ end
50
+
51
+ def should_send_to_api?
52
+ !disabled_by_default.include?(application_environment)
53
+ end
54
+
55
+ def application_root
56
+ @project_root || Dir.pwd
57
+ end
58
+
59
+ def remote_port
60
+ @remote_port ||= ssl? ? 443 : 80
61
+ end
62
+
63
+ def application_environment
64
+ @environment_name || ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,96 @@
1
+ module ErrorappNotifier
2
+ class ControllerFailureData < FailureData
3
+ def initialize(exception, controller = nil, request = nil)
4
+ super(exception)
5
+ @data = ControllerDataExtractor.new(controller, request) unless request.nil?
6
+ end
7
+
8
+ private
9
+
10
+ def extra_stuff
11
+ return {} if @data.nil?
12
+ {
13
+ :request =>
14
+ {
15
+ :url => @data.url,
16
+ :controller => @data.controller,
17
+ :action => @data.action,
18
+ :parameters => @data.parameters,
19
+ :request_method => @data.request_method,
20
+ :remote_ip => @data.remote_ip,
21
+ :headers => extract_http_headers(@data.env),
22
+ :session => Sanitizer.sanitize_session(@data.request)
23
+ }
24
+ }
25
+ end
26
+ end
27
+
28
+ class ControllerDataExtractor
29
+ def initialize(controller, request)
30
+ @request = request
31
+ @controller = controller
32
+ end
33
+
34
+ def controller
35
+ "#{@controller.class}"
36
+ end
37
+
38
+ def url
39
+ if @request.respond_to?(:url)
40
+ @request.url
41
+ else
42
+ "#{@request.protocol}#{@request.host}#{@request.request_uri}"
43
+ end
44
+ end
45
+
46
+ def action
47
+ if @request.respond_to?(:parameters)
48
+ @request.parameters['action']
49
+ else
50
+ @request.params['action']
51
+ end
52
+ end
53
+
54
+ def parameters
55
+ parameters = if @request.respond_to?(:parameters)
56
+ @request.parameters
57
+ else
58
+ @request.params
59
+ end
60
+
61
+ filter_parameters(parameters)
62
+ end
63
+
64
+ def request_method
65
+ "#{@request.request_method}"
66
+ end
67
+
68
+ def remote_ip
69
+ if @request.respond_to?(:remote_ip)
70
+ @request.remote_ip
71
+ else
72
+ @request.ip
73
+ end
74
+ end
75
+
76
+ def env
77
+ @request.env
78
+ end
79
+
80
+ def request
81
+ @request
82
+ end
83
+
84
+ private
85
+
86
+ def filter_parameters(hash)
87
+ if @request.respond_to?(:env) && @request.env["action_dispatch.parameter_filter"]
88
+ Sanitizer.filter_hash(@request.env["action_dispatch.parameter_filter"], hash)
89
+ elsif @controller.respond_to?(:filter_parameters)
90
+ @controller.send(:filter_parameters, hash)
91
+ else
92
+ hash
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,19 @@
1
+ class ExceptionData
2
+ attr_reader :exception
3
+
4
+ def initialize(exception)
5
+ @exception = exception
6
+ end
7
+
8
+ def data
9
+ {
10
+ :exception =>
11
+ {
12
+ :exception_class => exception.class.to_s,
13
+ :message => exception.message,
14
+ :backtrace => exception.backtrace,
15
+ :occurred_at => Time.now.utc.iso8601
16
+ }
17
+ }
18
+ end
19
+ end
@@ -0,0 +1,87 @@
1
+ require 'digest/md5'
2
+ require 'time'
3
+ require 'errorapp_notifier/exception_data'
4
+ require 'errorapp_notifier/application_environment_data'
5
+
6
+ module ErrorappNotifier
7
+ class FailureData
8
+ def initialize(exception, name = nil)
9
+ @exception = exception
10
+ @name = name
11
+ end
12
+
13
+ def to_hash
14
+ hash = {}
15
+ hash.merge!(ExceptionData.new(@exception).data)
16
+ hash.merge!(ApplicationEnvironmentData.new(@exception).data)
17
+ hash.merge!(extra_stuff)
18
+ hash.merge!(context_stuff)
19
+ hash.merge!(errorapp_client_data)
20
+ rescue_sanitize_hash do
21
+ Sanitizer.sanitize_hash(hash)
22
+ end
23
+ end
24
+
25
+ def to_json
26
+ begin
27
+ to_hash.to_json
28
+ rescue NoMethodError
29
+ begin
30
+ require 'json'
31
+ return to_hash.to_json
32
+ rescue StandardError => e
33
+ ErrorappNotifier.logger.error(e.message)
34
+ ErrorappNotifier.logger.error(e.backtrace)
35
+ raise StandardError.new("You need a json gem/library installed to send errors to ErrorApp (Object.to_json not defined). \nInstall json_pure, yajl-ruby, json-jruby, or the c-based json gem")
36
+ end
37
+ end
38
+ end
39
+
40
+ def uniq_key
41
+ return nil if (@exception.backtrace.nil? || @exception.backtrace.empty?)
42
+ Digest::MD5.hexdigest(@exception.backtrace.join)
43
+ end
44
+
45
+ private
46
+
47
+ def errorapp_client_data
48
+ {
49
+ :client =>
50
+ {
51
+ :name => ErrorappNotifier::CLIENT_NAME,
52
+ :version => ErrorappNotifier::VERSION,
53
+ :protocol_version => ErrorappNotifier::PROTOCOL_VERSION
54
+ }
55
+ }
56
+ end
57
+
58
+ def extra_stuff
59
+ { :rescue_block => {:name => @name} }
60
+ end
61
+
62
+ def context_stuff
63
+ context = Thread.current[:notifier_context]
64
+ (context.nil? || context.empty?) ? {} : {'context'=> context}
65
+ end
66
+
67
+ def extract_http_headers(env)
68
+ headers = {}
69
+ env.select{|k, v| k =~ /^HTTP_/}.each do |name, value|
70
+ proper_name = name.sub(/^HTTP_/, '').split('_').map{|upper_case| upper_case.capitalize}.join('-')
71
+ headers[proper_name] = value
72
+ end
73
+ unless headers['Cookie'].nil?
74
+ headers['Cookie'] = headers['Cookie'].sub(/_session=\S+/, '_session=[FILTERED]')
75
+ end
76
+ headers
77
+ end
78
+
79
+ def rescue_sanitize_hash
80
+ begin
81
+ yield
82
+ rescue Exception
83
+ {}
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,11 @@
1
+ class Regexp
2
+ def to_json(options = {})
3
+ "\"#{self.to_s}\""
4
+ end
5
+ end
6
+
7
+ class Fixnum
8
+ def to_json(options = {})
9
+ to_s
10
+ end
11
+ end
@@ -0,0 +1,80 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+
4
+ module ErrorappNotifier
5
+ class Notifier
6
+ def initialize(data, uniq_key = nil)
7
+ @uniq_key = uniq_key
8
+ @data = data
9
+ end
10
+
11
+ def self.notify_error(exception_data)
12
+ new(
13
+ exception_data.to_json,
14
+ exception_data.uniq_key
15
+ ).notify_error
16
+ end
17
+
18
+ def notify_error
19
+ log_and_send do
20
+ client.post(url, data)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :data, :uniq_key
27
+
28
+ def url
29
+ "/api/projects/#{config.api_key}/fails?protocol_version=#{PROTOCOL_VERSION}#{hash_param}"
30
+ end
31
+
32
+ def hash_param
33
+ unless uniq_key.nil?
34
+ "&hash=#{uniq_key}"
35
+ end
36
+ end
37
+
38
+ def log_and_send
39
+ begin
40
+ response = yield
41
+ case response
42
+ when Net::HTTPSuccess
43
+ ErrorappNotifier.logger.info("Error reported to Errorapp")
44
+ else
45
+ log_error(response.message)
46
+ end
47
+ rescue Exception => e
48
+ log_error
49
+ ErrorappNotifier.logger.error(e)
50
+ end
51
+ end
52
+
53
+ def config
54
+ ErrorappNotifier.configuration
55
+ end
56
+
57
+ def log_error(message = '')
58
+ ErrorappNotifier.logger.error(
59
+ "Problem notifying Errorapp about the error #{message}"
60
+ )
61
+ end
62
+
63
+ def client
64
+ client = optional_proxy.new(config.remote_host, config.remote_port)
65
+ client.open_timeout = config.http_open_timeout
66
+ client.read_timeout = config.http_read_timeout
67
+ client.use_ssl = config.ssl?
68
+ client.verify_mode = OpenSSL::SSL::VERIFY_NONE if config.ssl?
69
+ client
70
+ end
71
+
72
+ def optional_proxy
73
+ Net::HTTP::Proxy(config.http_proxy_host,
74
+ config.http_proxy_port,
75
+ config.http_proxy_username,
76
+ config.http_proxy_password
77
+ )
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,32 @@
1
+ require 'rack'
2
+
3
+ module Rack
4
+ class RailsErrorappNotifier
5
+ def initialize(app)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ begin
11
+ body = @app.call(env)
12
+ rescue Exception => e
13
+ ::ErrorappNotifier::Notify.notify_with_controller(
14
+ e,
15
+ env['action_controller.instance'],
16
+ Rack::Request.new(env)
17
+ )
18
+ raise
19
+ end
20
+
21
+ if env['rack.exception']
22
+ ::ErrorappNotifier::Notify.notify_with_controller(
23
+ env['rack.exception'],
24
+ env['action_controller.instance'],
25
+ Rack::Request.new(env)
26
+ )
27
+ end
28
+
29
+ body
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,34 @@
1
+ # force Rails < 2.0 to use quote keys as per the JSON standard...
2
+ if defined?(ActiveSupport) &&
3
+ defined?(ActiveSupport::JSON) &&
4
+ ActiveSupport::JSON.respond_to?(:unquote_hash_key_identifiers)
5
+ ActiveSupport::JSON.unquote_hash_key_identifiers = false
6
+ end
7
+
8
+ if defined? ActionController
9
+ module ActionController
10
+ class Base
11
+ def rescue_action_with_errorapp(exception)
12
+ unless exception_handled_by_rescue_from?(exception)
13
+ ErrorappNotifier::Notify.notify_with_controller(
14
+ exception,
15
+ self,
16
+ request
17
+ )
18
+ ErrorappNotifier.context.clear!
19
+ end
20
+ rescue_action_without_errorapp exception
21
+ end
22
+
23
+ alias_method :rescue_action_without_errorapp, :rescue_action
24
+ alias_method :rescue_action, :rescue_action_with_errorapp
25
+ protected :rescue_action
26
+
27
+ private
28
+
29
+ def exception_handled_by_rescue_from?(exception)
30
+ respond_to?(:handler_for_rescue) && handler_for_rescue(exception)
31
+ end
32
+ end
33
+ end
34
+ end