diff options
| author | hukl <contact@smyck.org> | 2009-10-31 18:59:01 +0100 |
|---|---|---|
| committer | hukl <contact@smyck.org> | 2009-10-31 18:59:01 +0100 |
| commit | a2671e54c3abfcdc14b95f262d0bb6d016a938ff (patch) | |
| tree | 36fb152b93ac11fe2c97b91f6fde5b39408eed15 /vendor/plugins/exception_notification/lib | |
| parent | 3781bd31ff137e6bc0a3b1d0c5506dfb42878a5c (diff) | |
added exception notifier plugin to catch all exceptions
Diffstat (limited to 'vendor/plugins/exception_notification/lib')
3 files changed, 243 insertions, 0 deletions
diff --git a/vendor/plugins/exception_notification/lib/exception_notifiable.rb b/vendor/plugins/exception_notification/lib/exception_notifiable.rb new file mode 100644 index 0000000..d5e28fc --- /dev/null +++ b/vendor/plugins/exception_notification/lib/exception_notifiable.rb | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | require 'ipaddr' | ||
| 2 | |||
| 3 | # Copyright (c) 2005 Jamis Buck | ||
| 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. | ||
| 23 | module ExceptionNotifiable | ||
| 24 | def self.included(target) | ||
| 25 | target.extend(ClassMethods) | ||
| 26 | end | ||
| 27 | |||
| 28 | module ClassMethods | ||
| 29 | def consider_local(*args) | ||
| 30 | local_addresses.concat(args.flatten.map { |a| IPAddr.new(a) }) | ||
| 31 | end | ||
| 32 | |||
| 33 | def local_addresses | ||
| 34 | addresses = read_inheritable_attribute(:local_addresses) | ||
| 35 | unless addresses | ||
| 36 | addresses = [IPAddr.new("127.0.0.1")] | ||
| 37 | write_inheritable_attribute(:local_addresses, addresses) | ||
| 38 | end | ||
| 39 | addresses | ||
| 40 | end | ||
| 41 | |||
| 42 | def exception_data(deliverer=self) | ||
| 43 | if deliverer == self | ||
| 44 | read_inheritable_attribute(:exception_data) | ||
| 45 | else | ||
| 46 | write_inheritable_attribute(:exception_data, deliverer) | ||
| 47 | end | ||
| 48 | end | ||
| 49 | |||
| 50 | def exceptions_to_treat_as_404 | ||
| 51 | exceptions = [ActiveRecord::RecordNotFound, | ||
| 52 | ActionController::UnknownController, | ||
| 53 | ActionController::UnknownAction] | ||
| 54 | exceptions << ActionController::RoutingError if ActionController.const_defined?(:RoutingError) | ||
| 55 | exceptions | ||
| 56 | end | ||
| 57 | end | ||
| 58 | |||
| 59 | private | ||
| 60 | |||
| 61 | def local_request? | ||
| 62 | remote = IPAddr.new(request.remote_ip) | ||
| 63 | !self.class.local_addresses.detect { |addr| addr.include?(remote) }.nil? | ||
| 64 | end | ||
| 65 | |||
| 66 | def render_404 | ||
| 67 | respond_to do |type| | ||
| 68 | type.html { render :file => "#{RAILS_ROOT}/public/404.html", :status => "404 Not Found" } | ||
| 69 | type.all { render :nothing => true, :status => "404 Not Found" } | ||
| 70 | end | ||
| 71 | end | ||
| 72 | |||
| 73 | def render_500 | ||
| 74 | respond_to do |type| | ||
| 75 | type.html { render :file => "#{RAILS_ROOT}/public/500.html", :status => "500 Error" } | ||
| 76 | type.all { render :nothing => true, :status => "500 Error" } | ||
| 77 | end | ||
| 78 | end | ||
| 79 | |||
| 80 | def rescue_action_in_public(exception) | ||
| 81 | case exception | ||
| 82 | when *self.class.exceptions_to_treat_as_404 | ||
| 83 | render_404 | ||
| 84 | |||
| 85 | else | ||
| 86 | render_500 | ||
| 87 | |||
| 88 | deliverer = self.class.exception_data | ||
| 89 | data = case deliverer | ||
| 90 | when nil then {} | ||
| 91 | when Symbol then send(deliverer) | ||
| 92 | when Proc then deliverer.call(self) | ||
| 93 | end | ||
| 94 | |||
| 95 | ExceptionNotifier.deliver_exception_notification(exception, self, | ||
| 96 | request, data) | ||
| 97 | end | ||
| 98 | end | ||
| 99 | end | ||
diff --git a/vendor/plugins/exception_notification/lib/exception_notifier.rb b/vendor/plugins/exception_notification/lib/exception_notifier.rb new file mode 100644 index 0000000..72e2e1a --- /dev/null +++ b/vendor/plugins/exception_notification/lib/exception_notifier.rb | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | require 'pathname' | ||
| 2 | |||
| 3 | # Copyright (c) 2005 Jamis Buck | ||
| 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. | ||
| 23 | class ExceptionNotifier < ActionMailer::Base | ||
| 24 | @@sender_address = %("Exception Notifier" <exception.notifier@default.com>) | ||
| 25 | cattr_accessor :sender_address | ||
| 26 | |||
| 27 | @@exception_recipients = [] | ||
| 28 | cattr_accessor :exception_recipients | ||
| 29 | |||
| 30 | @@email_prefix = "[ERROR] " | ||
| 31 | cattr_accessor :email_prefix | ||
| 32 | |||
| 33 | @@sections = %w(request session environment backtrace) | ||
| 34 | cattr_accessor :sections | ||
| 35 | |||
| 36 | self.template_root = "#{File.dirname(__FILE__)}/../views" | ||
| 37 | |||
| 38 | def self.reloadable?() false end | ||
| 39 | |||
| 40 | def exception_notification(exception, controller, request, data={}) | ||
| 41 | content_type "text/plain" | ||
| 42 | |||
| 43 | subject "#{email_prefix}#{controller.controller_name}##{controller.action_name} (#{exception.class}) #{exception.message.inspect}" | ||
| 44 | |||
| 45 | recipients exception_recipients | ||
| 46 | from sender_address | ||
| 47 | |||
| 48 | body data.merge({ :controller => controller, :request => request, | ||
| 49 | :exception => exception, :host => (request.env["HTTP_X_FORWARDED_HOST"] || request.env["HTTP_HOST"]), | ||
| 50 | :backtrace => sanitize_backtrace(exception.backtrace), | ||
| 51 | :rails_root => rails_root, :data => data, | ||
| 52 | :sections => sections }) | ||
| 53 | end | ||
| 54 | |||
| 55 | private | ||
| 56 | |||
| 57 | def sanitize_backtrace(trace) | ||
| 58 | re = Regexp.new(/^#{Regexp.escape(rails_root)}/) | ||
| 59 | trace.map { |line| Pathname.new(line.gsub(re, "[RAILS_ROOT]")).cleanpath.to_s } | ||
| 60 | end | ||
| 61 | |||
| 62 | def rails_root | ||
| 63 | @rails_root ||= Pathname.new(RAILS_ROOT).cleanpath.to_s | ||
| 64 | end | ||
| 65 | |||
| 66 | end | ||
diff --git a/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb b/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb new file mode 100644 index 0000000..d3dc63a --- /dev/null +++ b/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | require 'pp' | ||
| 2 | |||
| 3 | # Copyright (c) 2005 Jamis Buck | ||
| 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. | ||
| 23 | module ExceptionNotifierHelper | ||
| 24 | VIEW_PATH = "views/exception_notifier" | ||
| 25 | APP_PATH = "#{RAILS_ROOT}/app/#{VIEW_PATH}" | ||
| 26 | PARAM_FILTER_REPLACEMENT = "[FILTERED]" | ||
| 27 | |||
| 28 | def render_section(section) | ||
| 29 | RAILS_DEFAULT_LOGGER.info("rendering section #{section.inspect}") | ||
| 30 | summary = render_overridable(section).strip | ||
| 31 | unless summary.blank? | ||
| 32 | title = render_overridable(:title, :locals => { :title => section }).strip | ||
| 33 | "#{title}\n\n#{summary.gsub(/^/, " ")}\n\n" | ||
| 34 | end | ||
| 35 | end | ||
| 36 | |||
| 37 | def render_overridable(partial, options={}) | ||
| 38 | if File.exist?(path = "#{APP_PATH}/_#{partial}.rhtml") | ||
| 39 | render(options.merge(:file => path, :use_full_path => false)) | ||
| 40 | elsif File.exist?(path = "#{File.dirname(__FILE__)}/../#{VIEW_PATH}/_#{partial}.rhtml") | ||
| 41 | render(options.merge(:file => path, :use_full_path => false)) | ||
| 42 | else | ||
| 43 | "" | ||
| 44 | end | ||
| 45 | end | ||
| 46 | |||
| 47 | def inspect_model_object(model, locals={}) | ||
| 48 | render_overridable(:inspect_model, | ||
| 49 | :locals => { :inspect_model => model, | ||
| 50 | :show_instance_variables => true, | ||
| 51 | :show_attributes => true }.merge(locals)) | ||
| 52 | end | ||
| 53 | |||
| 54 | def inspect_value(value) | ||
| 55 | len = 512 | ||
| 56 | result = object_to_yaml(value).gsub(/\n/, "\n ").strip | ||
| 57 | result = result[0,len] + "... (#{result.length-len} bytes more)" if result.length > len+20 | ||
| 58 | result | ||
| 59 | end | ||
| 60 | |||
| 61 | def object_to_yaml(object) | ||
| 62 | object.to_yaml.sub(/^---\s*/m, "") | ||
| 63 | end | ||
| 64 | |||
| 65 | def exclude_raw_post_parameters? | ||
| 66 | @controller && @controller.respond_to?(:filter_parameters) | ||
| 67 | end | ||
| 68 | |||
| 69 | def filter_sensitive_post_data_parameters(parameters) | ||
| 70 | exclude_raw_post_parameters? ? @controller.__send__(:filter_parameters, parameters) : parameters | ||
| 71 | end | ||
| 72 | |||
| 73 | def filter_sensitive_post_data_from_env(env_key, env_value) | ||
| 74 | return env_value unless exclude_raw_post_parameters? | ||
| 75 | return PARAM_FILTER_REPLACEMENT if (env_key =~ /RAW_POST_DATA/i) | ||
| 76 | return @controller.__send__(:filter_parameters, {env_key => env_value}).values[0] | ||
| 77 | end | ||
| 78 | end | ||
