exception_notification 2.5.0 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,130 @@
1
+ Exception Notifier Plugin for Rails
2
+ ====
3
+
4
+ The Exception Notifier plugin provides a mailer object and a default set of
5
+ templates for sending email notifications when errors occur in a Rails
6
+ application. The plugin is configurable, allowing programmers to specify:
7
+
8
+ * the sender address of the email
9
+ * the recipient addresses
10
+ * the text used to prefix the subject line
11
+
12
+ The email includes information about the current request, session, and
13
+ environment, and also gives a backtrace of the exception.
14
+
15
+ Installation
16
+ ---
17
+
18
+ You can use the latest ExceptionNotification gem with Rails 3, by adding
19
+ the following line in your Gemfile
20
+
21
+ gem 'exception_notification'
22
+
23
+ As of Rails 3 ExceptionNotification is used as a rack middleware, so you can
24
+ configure its options on your config.ru file, or in the environment you
25
+ want it to run. In most cases you would want ExceptionNotification to
26
+ run on production. You can make it work by
27
+
28
+ Whatever::Application.config.middleware.use ExceptionNotifier,
29
+ :email_prefix => "[Whatever] ",
30
+ :sender_address => %{"notifier" <notifier@example.com>},
31
+ :exception_recipients => %w{exceptions@example.com}
32
+
33
+ Customization
34
+ ---
35
+
36
+ By default, the notification email includes four parts: request, session,
37
+ environment, and backtrace (in that order). You can customize how each of those
38
+ sections are rendered by placing a partial named for that part in your
39
+ app/views/exception_notifier directory (e.g., _session.rhtml). Each partial has
40
+ access to the following variables:
41
+
42
+ @controller # the controller that caused the error
43
+ @request # the current request object
44
+ @exception # the exception that was raised
45
+ @backtrace # a sanitized version of the exception's backtrace
46
+ @data # a hash of optional data values that were passed to the notifier
47
+ @sections # the array of sections to include in the email
48
+
49
+ You can reorder the sections, or exclude sections completely, by altering the
50
+ ExceptionNotifier.sections variable. You can even add new sections that
51
+ describe application-specific data--just add the section's name to the list
52
+ (wherever you'd like), and define the corresponding partial.
53
+
54
+ #Example with two new added sections
55
+ Whatever::Application.config.middleware.use ExceptionNotifier,
56
+ :email_prefix => "[Whatever] ",
57
+ :sender_address => %{"notifier" <notifier@example.com>},
58
+ :exception_recipients => %w{exceptions@example.com},
59
+ :sections => %w{my_section1 my_section2} + ExceptionNotifier::Notifier.default_sections
60
+
61
+ If your new section requires information that isn't available by default, make sure
62
+ it is made available to the email using the exception_data macro:
63
+
64
+ class ApplicationController < ActionController::Base
65
+ before_filter :log_additional_data
66
+ ...
67
+ protected
68
+ def log_additional_data
69
+ request.env["exception_notifier.exception_data"] = {
70
+ :document => @document,
71
+ :person => @person
72
+ }
73
+ end
74
+ ...
75
+ end
76
+
77
+ In the above case, @document and @person would be made available to the email
78
+ renderer, allowing your new section(s) to access and display them. See the
79
+ existing sections defined by the plugin for examples of how to write your own.
80
+
81
+ Background Notifications
82
+ ---
83
+
84
+ If you want to send notifications from a background process like
85
+ DelayedJob, you should use the background_exception_notification method
86
+ like this:
87
+
88
+ begin
89
+ some code...
90
+ rescue => e
91
+ ExceptionNotifier::Notifier.background_exception_notification(e)
92
+ end
93
+
94
+ Manually notify of exception
95
+ ---
96
+
97
+ If your controller action manually handles an error, the notifier will never be
98
+ run. To manually notify of an error you can do something like the following:
99
+
100
+ rescue_from Exception, :with => :server_error
101
+
102
+ def server_error(exception)
103
+ # Whatever code that handles the exception
104
+
105
+ ExceptionNotifier::Notifier.exception_notification(request.env, exception).deliver
106
+ end
107
+
108
+ Notification
109
+ ---
110
+
111
+ After an exception notification has been delivered the rack environment variable
112
+ 'exception_notifier.delivered' will be set to +true+.
113
+
114
+ Rails 2.3 stable and earlier
115
+ ---
116
+
117
+ If you are running Rails 2.3 then see the branch for that:
118
+
119
+ <a href="http://github.com/smartinez87/exception_notification/tree/2-3-stable">http://github.com/smartinez87/exception_notification/tree/2-3-stable</a>
120
+
121
+ If you are running pre-rack Rails then see this tag:
122
+
123
+ <a href="http://github.com/smartinez87/exception_notification/tree/pre-2-3">http://github.com/smartinez87/exception_notification/tree/pre-2-3</a>
124
+
125
+ Support and tickets
126
+ ---
127
+
128
+ <a href="https://github.com/smartinez87/exception_notification/issues">https://github.com/smartinez87/exception_notification/issues</a>
129
+
130
+ Copyright (c) 2005 Jamis Buck, released under the MIT license
@@ -0,0 +1 @@
1
+ require 'exception_notifier'
@@ -0,0 +1,37 @@
1
+ require 'action_dispatch'
2
+ require 'exception_notifier/notifier'
3
+
4
+ class ExceptionNotifier
5
+ def self.default_ignore_exceptions
6
+ [].tap do |exceptions|
7
+ exceptions << ::ActiveRecord::RecordNotFound if defined? ::ActiveRecord::RecordNotFound
8
+ exceptions << ::AbstractController::ActionNotFound if defined? ::AbstractController::ActionNotFound
9
+ exceptions << ::ActionController::RoutingError if defined? ::ActionController::RoutingError
10
+ end
11
+ end
12
+
13
+ def initialize(app, options = {})
14
+ @app, @options = app, options
15
+
16
+ Notifier.default_sender_address = @options[:sender_address]
17
+ Notifier.default_exception_recipients = @options[:exception_recipients]
18
+ Notifier.default_email_prefix = @options[:email_prefix]
19
+ Notifier.default_sections = @options[:sections]
20
+
21
+ @options[:ignore_exceptions] ||= self.class.default_ignore_exceptions
22
+ end
23
+
24
+ def call(env)
25
+ @app.call(env)
26
+ rescue Exception => exception
27
+ options = (env['exception_notifier.options'] ||= Notifier.default_options)
28
+ options.reverse_merge!(@options)
29
+
30
+ unless Array.wrap(options[:ignore_exceptions]).include?(exception.class)
31
+ Notifier.exception_notification(env, exception).deliver
32
+ env['exception_notifier.delivered'] = true
33
+ end
34
+
35
+ raise exception
36
+ end
37
+ end
@@ -0,0 +1,108 @@
1
+ require 'action_mailer'
2
+ require 'pp'
3
+
4
+ class ExceptionNotifier
5
+ class Notifier < ActionMailer::Base
6
+ self.mailer_name = 'exception_notifier'
7
+
8
+ #Append application view path to the ExceptionNotifier lookup context.
9
+ self.append_view_path Rails.root.nil? ? "app/views" : "#{Rails.root}/app/views" if defined?(Rails)
10
+ self.append_view_path "#{File.dirname(__FILE__)}/views"
11
+
12
+ class << self
13
+ attr_writer :default_sender_address
14
+ attr_writer :default_exception_recipients
15
+ attr_writer :default_email_prefix
16
+ attr_writer :default_sections
17
+
18
+ def default_sender_address
19
+ @default_sender_address || %("Exception Notifier" <exception.notifier@default.com>)
20
+ end
21
+
22
+ def default_exception_recipients
23
+ @default_exception_recipients || []
24
+ end
25
+
26
+ def default_email_prefix
27
+ @default_email_prefix || "[ERROR] "
28
+ end
29
+
30
+ def default_sections
31
+ @default_sections || %w(request session environment backtrace)
32
+ end
33
+
34
+ def default_options
35
+ { :sender_address => default_sender_address,
36
+ :exception_recipients => default_exception_recipients,
37
+ :email_prefix => default_email_prefix,
38
+ :sections => default_sections }
39
+ end
40
+ end
41
+
42
+ class MissingController
43
+ def method_missing(*args, &block)
44
+ end
45
+ end
46
+
47
+ def exception_notification(env, exception)
48
+ @env = env
49
+ @exception = exception
50
+ @options = (env['exception_notifier.options'] || {}).reverse_merge(self.class.default_options)
51
+ @kontroller = env['action_controller.instance'] || MissingController.new
52
+ @request = ActionDispatch::Request.new(env)
53
+ @backtrace = clean_backtrace(exception)
54
+ @sections = @options[:sections]
55
+ data = env['exception_notifier.exception_data'] || {}
56
+
57
+ data.each do |name, value|
58
+ instance_variable_set("@#{name}", value)
59
+ end
60
+
61
+ prefix = "#{@options[:email_prefix]}#{@kontroller.controller_name}##{@kontroller.action_name}"
62
+ subject = "#{prefix} (#{@exception.class}) #{@exception.message.inspect}"
63
+ subject = subject.length > 120 ? subject[0...120] + "..." : subject
64
+
65
+ mail(:to => @options[:exception_recipients], :from => @options[:sender_address], :subject => subject) do |format|
66
+ format.text { render "#{mailer_name}/exception_notification" }
67
+ end
68
+ end
69
+
70
+ def background_exception_notification(exception)
71
+ if @notifier = Rails.application.config.middleware.detect{ |x| x.klass == ExceptionNotifier }
72
+ @options = (@notifier.args.first || {}).reverse_merge(self.class.default_options)
73
+ subject = "#{@options[:email_prefix]} (#{exception.class}) #{exception.message.inspect}"
74
+
75
+ @exception = exception
76
+ @backtrace = exception.backtrace || []
77
+ @sections = %w{backtrace}
78
+
79
+ mail(:to => @options[:exception_recipients], :from => @options[:sender_address], :subject => subject) do |format|
80
+ format.text { render "#{mailer_name}/background_exception_notification" }
81
+ end.deliver
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def clean_backtrace(exception)
88
+ if Rails.respond_to?(:backtrace_cleaner)
89
+ Rails.backtrace_cleaner.send(:filter, exception.backtrace)
90
+ else
91
+ exception.backtrace
92
+ end
93
+ end
94
+
95
+ helper_method :inspect_object
96
+
97
+ def inspect_object(object)
98
+ case object
99
+ when Hash, Array
100
+ object.inspect
101
+ when ActionController::Base
102
+ "#{object.controller_name}##{object.action_name}"
103
+ else
104
+ object.to_s
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1 @@
1
+ <%= raw @backtrace.join("\n") %>
@@ -0,0 +1,8 @@
1
+ <% filtered_env = @request.filtered_env -%>
2
+ <% max = filtered_env.keys.max { |a, b| a.length <=> b.length } -%>
3
+ <% filtered_env.keys.sort.each do |key| -%>
4
+ * <%= raw("%-*s: %s" % [max.length, key, inspect_object(filtered_env[key])]) %>
5
+ <% end -%>
6
+
7
+ * Process: <%= raw $$ %>
8
+ * Server : <%= raw `hostname -s`.chomp %>
@@ -0,0 +1,4 @@
1
+ * URL : <%= raw @request.url %>
2
+ * IP address: <%= raw @request.remote_ip %>
3
+ * Parameters: <%= raw @request.filtered_parameters.inspect %>
4
+ * Rails root: <%= raw Rails.root %>
@@ -0,0 +1,2 @@
1
+ * session id: <%= @request.ssl? ? "[FILTERED]" : (raw @request.session['session_id'].inspect.html_safe) %>
2
+ * data: <%= raw PP.pp(@request.session, "") %>
@@ -0,0 +1,3 @@
1
+ -------------------------------
2
+ <%= raw title.to_s.humanize %>:
3
+ -------------------------------
@@ -0,0 +1,13 @@
1
+ A <%= @exception.class %> occurred in background:
2
+
3
+ <%= @exception.message %>
4
+ <%= @backtrace.first %>
5
+
6
+ <% sections = @sections.map do |section|
7
+ summary = render(section).strip
8
+ unless summary.blank?
9
+ title = render("title", :title => section).strip
10
+ "#{title}\n\n#{summary.gsub(/^/, " ")}\n\n"
11
+ end
12
+ end %>
13
+ <%= raw sections.join %>
@@ -0,0 +1,13 @@
1
+ A <%= @exception.class %> occurred in <%= @kontroller.controller_name %>#<%= @kontroller.action_name %>:
2
+
3
+ <%= raw @exception.message %>
4
+ <%= raw @backtrace.first %>
5
+
6
+ <% sections = @sections.map do |section|
7
+ summary = render(section).strip
8
+ unless summary.blank?
9
+ title = render("title", :title => section).strip
10
+ "#{title}\n\n#{summary.gsub(/^/, " ")}\n\n"
11
+ end
12
+ end %>
13
+ <%= raw sections.join %>
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exception_notification
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
8
  - 5
9
- - 0
10
- version: 2.5.0
9
+ - 1
10
+ version: 2.5.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jamis Buck
@@ -16,8 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-08-27 00:00:00 -03:00
20
- default_executable:
19
+ date: 2011-08-29 00:00:00 Z
21
20
  dependencies:
22
21
  - !ruby/object:Gem::Dependency
23
22
  name: actionmailer
@@ -76,12 +75,22 @@ extensions: []
76
75
  extra_rdoc_files: []
77
76
 
78
77
  files:
78
+ - lib/exception_notification.rb
79
+ - lib/exception_notifier.rb
80
+ - lib/exception_notifier/notifier.rb
81
+ - lib/exception_notifier/views/exception_notifier/_backtrace.text.erb
82
+ - lib/exception_notifier/views/exception_notifier/_environment.text.erb
83
+ - lib/exception_notifier/views/exception_notifier/_request.text.erb
84
+ - lib/exception_notifier/views/exception_notifier/_session.text.erb
85
+ - lib/exception_notifier/views/exception_notifier/_title.text.erb
86
+ - lib/exception_notifier/views/exception_notifier/background_exception_notification.text.erb
87
+ - lib/exception_notifier/views/exception_notifier/exception_notification.text.erb
79
88
  - Rakefile
80
89
  - .gemtest
81
- - test/exception_notification_test.rb
82
- - test/dummy/test/functional/posts_controller_test.rb
90
+ - README.md
83
91
  - test/background_exception_notification_test.rb
84
- has_rdoc: true
92
+ - test/dummy/test/functional/posts_controller_test.rb
93
+ - test/exception_notification_test.rb
85
94
  homepage:
86
95
  licenses: []
87
96
 
@@ -111,11 +120,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
120
  requirements: []
112
121
 
113
122
  rubyforge_project:
114
- rubygems_version: 1.5.0
123
+ rubygems_version: 1.7.1
115
124
  signing_key:
116
125
  specification_version: 3
117
126
  summary: Exception notification by email for Rails apps
118
127
  test_files:
119
- - test/exception_notification_test.rb
120
- - test/dummy/test/functional/posts_controller_test.rb
121
128
  - test/background_exception_notification_test.rb
129
+ - test/dummy/test/functional/posts_controller_test.rb
130
+ - test/exception_notification_test.rb