errorapp_notifier 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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