exception_notification 3.0.1 → 4.4.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 (153) hide show
  1. checksums.yaml +7 -0
  2. data/Appraisals +7 -0
  3. data/CHANGELOG.rdoc +129 -1
  4. data/CODE_OF_CONDUCT.md +22 -0
  5. data/CONTRIBUTING.md +29 -1
  6. data/Gemfile +1 -1
  7. data/MIT-LICENSE +23 -0
  8. data/README.md +168 -222
  9. data/Rakefile +5 -11
  10. data/docs/notifiers/campfire.md +50 -0
  11. data/docs/notifiers/custom.md +42 -0
  12. data/docs/notifiers/datadog.md +51 -0
  13. data/docs/notifiers/email.md +195 -0
  14. data/docs/notifiers/google_chat.md +31 -0
  15. data/docs/notifiers/hipchat.md +66 -0
  16. data/docs/notifiers/irc.md +97 -0
  17. data/docs/notifiers/mattermost.md +115 -0
  18. data/docs/notifiers/slack.md +161 -0
  19. data/docs/notifiers/sns.md +37 -0
  20. data/docs/notifiers/teams.md +54 -0
  21. data/docs/notifiers/webhook.md +60 -0
  22. data/examples/sample_app.rb +54 -0
  23. data/examples/sinatra/Gemfile +8 -0
  24. data/examples/sinatra/Gemfile.lock +95 -0
  25. data/examples/sinatra/Procfile +2 -0
  26. data/examples/sinatra/README.md +11 -0
  27. data/examples/sinatra/config.ru +3 -0
  28. data/examples/sinatra/sinatra_app.rb +36 -0
  29. data/exception_notification.gemspec +32 -11
  30. data/gemfiles/rails4_0.gemfile +7 -0
  31. data/gemfiles/rails4_1.gemfile +7 -0
  32. data/gemfiles/rails4_2.gemfile +7 -0
  33. data/gemfiles/rails5_0.gemfile +7 -0
  34. data/gemfiles/rails5_1.gemfile +7 -0
  35. data/gemfiles/rails5_2.gemfile +7 -0
  36. data/gemfiles/rails6_0.gemfile +7 -0
  37. data/lib/exception_notification.rb +11 -0
  38. data/lib/exception_notification/rack.rb +55 -0
  39. data/lib/exception_notification/rails.rb +9 -0
  40. data/lib/exception_notification/resque.rb +22 -0
  41. data/lib/exception_notification/sidekiq.rb +27 -0
  42. data/lib/exception_notification/version.rb +3 -0
  43. data/lib/exception_notifier.rb +137 -61
  44. data/lib/exception_notifier/base_notifier.rb +24 -0
  45. data/lib/exception_notifier/campfire_notifier.rb +16 -11
  46. data/lib/exception_notifier/datadog_notifier.rb +153 -0
  47. data/lib/exception_notifier/email_notifier.rb +196 -0
  48. data/lib/exception_notifier/google_chat_notifier.rb +42 -0
  49. data/lib/exception_notifier/hipchat_notifier.rb +49 -0
  50. data/lib/exception_notifier/irc_notifier.rb +57 -0
  51. data/lib/exception_notifier/mattermost_notifier.rb +72 -0
  52. data/lib/exception_notifier/modules/backtrace_cleaner.rb +11 -0
  53. data/lib/exception_notifier/modules/error_grouping.rb +77 -0
  54. data/lib/exception_notifier/modules/formatter.rb +118 -0
  55. data/lib/exception_notifier/notifier.rb +9 -179
  56. data/lib/exception_notifier/slack_notifier.rb +111 -0
  57. data/lib/exception_notifier/sns_notifier.rb +85 -0
  58. data/lib/exception_notifier/teams_notifier.rb +193 -0
  59. data/lib/exception_notifier/views/exception_notifier/_backtrace.html.erb +3 -1
  60. data/lib/exception_notifier/views/exception_notifier/_data.html.erb +6 -1
  61. data/lib/exception_notifier/views/exception_notifier/_environment.html.erb +8 -6
  62. data/lib/exception_notifier/views/exception_notifier/_environment.text.erb +1 -4
  63. data/lib/exception_notifier/views/exception_notifier/_request.html.erb +36 -5
  64. data/lib/exception_notifier/views/exception_notifier/_request.text.erb +10 -5
  65. data/lib/exception_notifier/views/exception_notifier/_session.html.erb +10 -2
  66. data/lib/exception_notifier/views/exception_notifier/_session.text.erb +2 -2
  67. data/lib/exception_notifier/views/exception_notifier/_title.html.erb +3 -3
  68. data/lib/exception_notifier/views/exception_notifier/background_exception_notification.html.erb +38 -11
  69. data/lib/exception_notifier/views/exception_notifier/background_exception_notification.text.erb +10 -11
  70. data/lib/exception_notifier/views/exception_notifier/exception_notification.html.erb +38 -22
  71. data/lib/exception_notifier/views/exception_notifier/exception_notification.text.erb +2 -3
  72. data/lib/exception_notifier/webhook_notifier.rb +51 -0
  73. data/lib/generators/exception_notification/install_generator.rb +15 -0
  74. data/lib/generators/exception_notification/templates/exception_notification.rb.erb +55 -0
  75. data/test/exception_notification/rack_test.rb +60 -0
  76. data/test/exception_notification/resque_test.rb +52 -0
  77. data/test/exception_notifier/campfire_notifier_test.rb +120 -0
  78. data/test/exception_notifier/datadog_notifier_test.rb +151 -0
  79. data/test/exception_notifier/email_notifier_test.rb +351 -0
  80. data/test/exception_notifier/google_chat_notifier_test.rb +181 -0
  81. data/test/exception_notifier/hipchat_notifier_test.rb +218 -0
  82. data/test/exception_notifier/irc_notifier_test.rb +137 -0
  83. data/test/exception_notifier/mattermost_notifier_test.rb +202 -0
  84. data/test/exception_notifier/modules/error_grouping_test.rb +165 -0
  85. data/test/exception_notifier/modules/formatter_test.rb +150 -0
  86. data/test/exception_notifier/sidekiq_test.rb +38 -0
  87. data/test/exception_notifier/slack_notifier_test.rb +227 -0
  88. data/test/exception_notifier/sns_notifier_test.rb +121 -0
  89. data/test/exception_notifier/teams_notifier_test.rb +90 -0
  90. data/test/exception_notifier/webhook_notifier_test.rb +96 -0
  91. data/test/exception_notifier_test.rb +182 -0
  92. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.html.erb +0 -0
  93. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.text.erb +0 -0
  94. data/test/{dummy/app → support}/views/exception_notifier/_new_section.html.erb +0 -0
  95. data/test/{dummy/app → support}/views/exception_notifier/_new_section.text.erb +0 -0
  96. data/test/test_helper.rb +12 -8
  97. metadata +333 -164
  98. data/.gemtest +0 -0
  99. data/Gemfile.lock +0 -122
  100. data/test/background_exception_notification_test.rb +0 -82
  101. data/test/campfire_test.rb +0 -53
  102. data/test/dummy/.gitignore +0 -4
  103. data/test/dummy/Gemfile +0 -33
  104. data/test/dummy/Gemfile.lock +0 -118
  105. data/test/dummy/Rakefile +0 -7
  106. data/test/dummy/app/controllers/application_controller.rb +0 -3
  107. data/test/dummy/app/controllers/posts_controller.rb +0 -30
  108. data/test/dummy/app/helpers/application_helper.rb +0 -2
  109. data/test/dummy/app/helpers/posts_helper.rb +0 -2
  110. data/test/dummy/app/models/post.rb +0 -2
  111. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  112. data/test/dummy/app/views/posts/_form.html.erb +0 -0
  113. data/test/dummy/app/views/posts/new.html.erb +0 -0
  114. data/test/dummy/app/views/posts/show.html.erb +0 -0
  115. data/test/dummy/config.ru +0 -4
  116. data/test/dummy/config/application.rb +0 -42
  117. data/test/dummy/config/boot.rb +0 -6
  118. data/test/dummy/config/database.yml +0 -22
  119. data/test/dummy/config/environment.rb +0 -13
  120. data/test/dummy/config/environments/development.rb +0 -24
  121. data/test/dummy/config/environments/production.rb +0 -49
  122. data/test/dummy/config/environments/test.rb +0 -35
  123. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  124. data/test/dummy/config/initializers/inflections.rb +0 -10
  125. data/test/dummy/config/initializers/mime_types.rb +0 -5
  126. data/test/dummy/config/initializers/secret_token.rb +0 -7
  127. data/test/dummy/config/initializers/session_store.rb +0 -8
  128. data/test/dummy/config/locales/en.yml +0 -5
  129. data/test/dummy/config/routes.rb +0 -3
  130. data/test/dummy/db/migrate/20110729022608_create_posts.rb +0 -15
  131. data/test/dummy/db/schema.rb +0 -24
  132. data/test/dummy/db/seeds.rb +0 -7
  133. data/test/dummy/lib/tasks/.gitkeep +0 -0
  134. data/test/dummy/public/404.html +0 -26
  135. data/test/dummy/public/422.html +0 -26
  136. data/test/dummy/public/500.html +0 -26
  137. data/test/dummy/public/favicon.ico +0 -0
  138. data/test/dummy/public/images/rails.png +0 -0
  139. data/test/dummy/public/index.html +0 -239
  140. data/test/dummy/public/javascripts/application.js +0 -2
  141. data/test/dummy/public/javascripts/controls.js +0 -965
  142. data/test/dummy/public/javascripts/dragdrop.js +0 -974
  143. data/test/dummy/public/javascripts/effects.js +0 -1123
  144. data/test/dummy/public/javascripts/prototype.js +0 -6001
  145. data/test/dummy/public/javascripts/rails.js +0 -191
  146. data/test/dummy/public/robots.txt +0 -5
  147. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  148. data/test/dummy/public/stylesheets/scaffold.css +0 -56
  149. data/test/dummy/script/rails +0 -6
  150. data/test/dummy/test/fixtures/posts.yml +0 -11
  151. data/test/dummy/test/functional/posts_controller_test.rb +0 -239
  152. data/test/dummy/test/test_helper.rb +0 -13
  153. data/test/exception_notification_test.rb +0 -73
@@ -0,0 +1,193 @@
1
+ require 'action_dispatch'
2
+ require 'active_support/core_ext/time'
3
+ require 'json'
4
+
5
+ module ExceptionNotifier
6
+ class TeamsNotifier < BaseNotifier
7
+ include ExceptionNotifier::BacktraceCleaner
8
+
9
+ class MissingController
10
+ def method_missing(*args, &block); end
11
+ end
12
+
13
+ attr_accessor :httparty
14
+
15
+ def initialize(options = {})
16
+ super
17
+ @default_options = options
18
+ @httparty = HTTParty
19
+ end
20
+
21
+ def call(exception, options = {})
22
+ @options = options.merge(@default_options)
23
+ @exception = exception
24
+ @backtrace = exception.backtrace ? clean_backtrace(exception) : nil
25
+
26
+ @env = @options.delete(:env)
27
+
28
+ @application_name = @options.delete(:app_name) || rails_app_name
29
+ @gitlab_url = @options.delete(:git_url)
30
+ @jira_url = @options.delete(:jira_url)
31
+
32
+ @webhook_url = @options.delete(:webhook_url)
33
+ raise ArgumentError, "You must provide 'webhook_url' parameter." unless @webhook_url
34
+
35
+ if @env.nil?
36
+ @controller = @request_items = nil
37
+ else
38
+ @controller = @env['action_controller.instance'] || MissingController.new
39
+
40
+ request = ActionDispatch::Request.new(@env)
41
+
42
+ @request_items = { url: request.original_url,
43
+ http_method: request.method,
44
+ ip_address: request.remote_ip,
45
+ parameters: request.filtered_parameters,
46
+ timestamp: Time.current }
47
+
48
+ if request.session['warden.user.user.key']
49
+ current_user = User.find(request.session['warden.user.user.key'][0][0])
50
+ @request_items[:current_user] = { id: current_user.id, email: current_user.email }
51
+ end
52
+ end
53
+
54
+ payload = message_text
55
+
56
+ @options[:body] = payload.to_json
57
+ @options[:headers] ||= {}
58
+ @options[:headers]['Content-Type'] = 'application/json'
59
+ @options[:debug_output] = $stdout
60
+
61
+ @httparty.post(@webhook_url, @options)
62
+ end
63
+
64
+ private
65
+
66
+ def message_text
67
+ errors_count = @options[:accumulated_errors_count].to_i
68
+
69
+ text = {
70
+ '@type' => 'MessageCard',
71
+ '@context' => 'http://schema.org/extensions',
72
+ 'summary' => "#{@application_name} Exception Alert",
73
+ 'title' => "⚠️ Exception Occurred in #{env_name} ⚠️",
74
+ 'sections' => [
75
+ {
76
+ 'activityTitle' => "#{errors_count > 1 ? errors_count : 'A'} *#{@exception.class}* occurred" + (@controller ? " in *#{controller_and_method}*." : '.'),
77
+ 'activitySubtitle' => @exception.message.to_s
78
+ }
79
+ ],
80
+ 'potentialAction' => []
81
+ }
82
+
83
+ text['sections'].push details
84
+ text['potentialAction'].push gitlab_view_link unless @gitlab_url.nil?
85
+ text['potentialAction'].push gitlab_issue_link unless @gitlab_url.nil?
86
+ text['potentialAction'].push jira_issue_link unless @jira_url.nil?
87
+
88
+ text
89
+ end
90
+
91
+ def details
92
+ details = {
93
+ 'title' => 'Details',
94
+ 'facts' => []
95
+ }
96
+
97
+ details['facts'].push message_request unless @request_items.nil?
98
+ details['facts'].push message_backtrace unless @backtrace.nil?
99
+
100
+ details
101
+ end
102
+
103
+ def message_request
104
+ {
105
+ 'name' => 'Request',
106
+ 'value' => "#{hash_presentation(@request_items)}\n "
107
+ }
108
+ end
109
+
110
+ def message_backtrace(size = 3)
111
+ text = []
112
+ size = @backtrace.size < size ? @backtrace.size : size
113
+ text << '```'
114
+ size.times { |i| text << '* ' + @backtrace[i] }
115
+ text << '```'
116
+
117
+ {
118
+ 'name' => 'Backtrace',
119
+ 'value' => text.join(" \n").to_s
120
+ }
121
+ end
122
+
123
+ def gitlab_view_link
124
+ {
125
+ '@type' => 'ViewAction',
126
+ 'name' => "\u{1F98A} View in GitLab",
127
+ 'target' => [
128
+ "#{@gitlab_url}/#{@application_name}"
129
+ ]
130
+ }
131
+ end
132
+
133
+ def gitlab_issue_link
134
+ link = [@gitlab_url, @application_name, 'issues', 'new'].join('/')
135
+ params = {
136
+ 'issue[title]' => ['[BUG] Error 500 :',
137
+ controller_and_method,
138
+ "(#{@exception.class})",
139
+ @exception.message].compact.join(' ')
140
+ }.to_query
141
+
142
+ {
143
+ '@type' => 'ViewAction',
144
+ 'name' => "\u{1F98A} Create Issue in GitLab",
145
+ 'target' => [
146
+ "#{link}/?#{params}"
147
+ ]
148
+ }
149
+ end
150
+
151
+ def jira_issue_link
152
+ {
153
+ '@type' => 'ViewAction',
154
+ 'name' => '🐞 Create Issue in Jira',
155
+ 'target' => [
156
+ "#{@jira_url}/secure/CreateIssue!default.jspa"
157
+ ]
158
+ }
159
+ end
160
+
161
+ def controller_and_method
162
+ if @controller
163
+ "#{@controller.controller_name}##{@controller.action_name}"
164
+ else
165
+ ''
166
+ end
167
+ end
168
+
169
+ def hash_presentation(hash)
170
+ text = []
171
+
172
+ hash.each do |key, value|
173
+ text << "* **#{key}** : `#{value}`"
174
+ end
175
+
176
+ text.join(" \n")
177
+ end
178
+
179
+ def rails_app_name
180
+ return unless defined?(Rails) && Rails.respond_to?(:application)
181
+
182
+ if ::Gem::Version.new(Rails.version) >= ::Gem::Version.new('6.0')
183
+ Rails.application.class.module_parent_name.underscore
184
+ else
185
+ Rails.application.class.parent_name.underscore
186
+ end
187
+ end
188
+
189
+ def env_name
190
+ Rails.env if defined?(Rails) && Rails.respond_to?(:env)
191
+ end
192
+ end
193
+ end
@@ -1 +1,3 @@
1
- <%= raw @backtrace.join("\n") %>
1
+ <pre style="font-size: 12px; padding: 10px; border: 1px solid #e1e1e8; background-color:#f5f5f5">
2
+ <%= @backtrace.join("\n") %>
3
+ </pre>
@@ -1 +1,6 @@
1
- * data: <%= raw PP.pp(@data, "") %>
1
+ <ul style="list-style: none">
2
+ <li>
3
+ <strong>data:</strong>
4
+ <span><%= PP.pp(@data, "") %></span>
5
+ </li>
6
+ </ul>
@@ -1,8 +1,10 @@
1
1
  <% filtered_env = @request.filtered_env -%>
2
- <% max = filtered_env.keys.map(&:to_s).max { |a, b| a.length <=> b.length } -%>
3
- <% filtered_env.keys.map(&:to_s).sort.each do |key| -%>
4
- * <%= raw("%-*s: %s" % [max.length, key, inspect_object(filtered_env[key])]) %>
5
- <% end -%>
6
2
 
7
- * Process: <%= raw $$ %>
8
- * Server : <%= raw `hostname`.chomp %>
3
+ <ul style="list-style: none">
4
+ <% filtered_env.keys.map(&:to_s).sort.each do |key| -%>
5
+ <li>
6
+ <strong><%= key %>:</strong>
7
+ <span><%= inspect_object(filtered_env[key]) %></span>
8
+ </li>
9
+ <% end -%>
10
+ </ul>
@@ -1,8 +1,5 @@
1
1
  <% filtered_env = @request.filtered_env -%>
2
2
  <% max = filtered_env.keys.map(&:to_s).max { |a, b| a.length <=> b.length } -%>
3
3
  <% filtered_env.keys.map(&:to_s).sort.each do |key| -%>
4
- * <%= raw("%-*s: %s" % [max.length, key, inspect_object(filtered_env[key])]) %>
4
+ * <%= raw safe_encode("%-*s: %s" % [max.length, key, inspect_object(filtered_env[key])]).strip %>
5
5
  <% end -%>
6
-
7
- * Process: <%= raw $$ %>
8
- * Server : <%= raw `hostname`.chomp %>
@@ -1,5 +1,36 @@
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 %>
5
- * Timestamp : <%= raw Time.current %>
1
+ <ul style="list-style: none">
2
+ <li>
3
+ <strong>URL:</strong>
4
+ <span><%= @request.url %></span>
5
+ </li>
6
+ <li>
7
+ <strong>HTTP Method:</strong>
8
+ <span><%= @request.request_method %></span>
9
+ </li>
10
+ <li>
11
+ <strong>IP Address:</strong>
12
+ <span><%= @request.remote_ip %></span>
13
+ </li>
14
+ <li>
15
+ <strong>Parameters:</strong>
16
+ <span><%= @request.filtered_parameters.inspect %></span>
17
+ </li>
18
+ <li>
19
+ <strong>Timestamp:</strong>
20
+ <span><%= @timestamp %></span>
21
+ </li>
22
+ <li>
23
+ <strong>Server:</strong>
24
+ <span><%= Socket.gethostname %></span>
25
+ </li>
26
+ <% if defined?(Rails) && Rails.respond_to?(:root) %>
27
+ <li>
28
+ <strong>Rails root:</strong>
29
+ <span><%= Rails.root %></span>
30
+ </li>
31
+ <% end %>
32
+ <li>
33
+ <strong>Process:</strong>
34
+ <span><%= $$ %></span>
35
+ </li>
36
+ </ul>
@@ -1,5 +1,10 @@
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 %>
5
- * Timestamp : <%= raw Time.current %>
1
+ * URL : <%= raw safe_encode @request.url %>
2
+ * HTTP Method: <%= raw @request.request_method %>
3
+ * IP address : <%= raw @request.remote_ip %>
4
+ * Parameters : <%= raw safe_encode @request.filtered_parameters.inspect %>
5
+ * Timestamp : <%= raw @timestamp %>
6
+ * Server : <%= raw Socket.gethostname %>
7
+ <% if defined?(Rails) && Rails.respond_to?(:root) %>
8
+ * Rails root : <%= raw Rails.root %>
9
+ <% end %>
10
+ * Process: <%= raw $$ %>
@@ -1,2 +1,10 @@
1
- * session id: <%= @request.ssl? ? "[FILTERED]" : (raw (@request.session['session_id'] || @request.env["rack.session.options"][:id]).inspect.html_safe) %>
2
- * data: <%= raw PP.pp(@request.session, "") %>
1
+ <ul style="list-style: none">
2
+ <li>
3
+ <strong>session_id: </strong>
4
+ <span><%= @request.ssl? ? "[FILTERED]" : (@request.session['session_id'] || (@request.env["rack.session.options"] and @request.env["rack.session.options"][:id]).inspect) %></span>
5
+ </li>
6
+ <li>
7
+ <strong>data: </strong>
8
+ <span><%= PP.pp(@request.session.to_hash, "") %></span>
9
+ </li>
10
+ </ul>
@@ -1,2 +1,2 @@
1
- * session id: <%= @request.ssl? ? "[FILTERED]" : (raw (@request.session['session_id'] || @request.env["rack.session.options"][:id]).inspect.html_safe) %>
2
- * data: <%= raw PP.pp(@request.session, "") %>
1
+ * session id: <%= @request.ssl? ? "[FILTERED]" : (raw (@request.session['session_id'] || (@request.env["rack.session.options"] and @request.env["rack.session.options"][:id])).inspect.html_safe) %>
2
+ * data: <%= raw PP.pp(@request.session.to_hash, "") %>
@@ -1,3 +1,3 @@
1
- -------------------------------
2
- <%= raw title.to_s.humanize %>:
3
- -------------------------------
1
+ <h2>
2
+ <%= title.to_s.humanize %>
3
+ </h2>
@@ -5,22 +5,49 @@
5
5
  <title>Exception</title>
6
6
  </head>
7
7
  <body>
8
- <pre style="font-size: 12px">
9
- <%= @exception.class.to_s =~ /^[aeiou]/i ? 'An' : 'A' %> <%= @exception.class %> occurred in background at <%= raw Time.current %> :
10
8
 
11
- <%= @exception.message %>
12
- <%= @backtrace.first %>
13
- <%
14
- sections = @sections.map do |section|
9
+ <%
10
+ sections_content = @sections.map do |section|
11
+ begin
15
12
  summary = render(section).strip
16
13
  unless summary.blank?
17
14
  title = render("title", :title => section).strip
18
- "#{title}\n\n#{summary.gsub(/^/, " ")}\n\n"
15
+ [title, summary]
19
16
  end
20
- end.join
21
- sections = sections.force_encoding('UTF-8').encode('UTF-16LE', :invalid => :replace).encode('UTF-8') if sections.respond_to?(:force_encoding)
17
+
18
+ rescue Exception => e
19
+ title = render("title", :title => section).strip
20
+ summary = ["ERROR: Failed to generate exception summary:", [e.class.to_s, e.message].join(": "), e.backtrace && e.backtrace.join("\n")].compact.join("\n\n")
21
+
22
+ [title, summary]
23
+ end
24
+ end
22
25
  %>
23
- <%= raw sections %>
24
- </pre>
26
+
27
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
28
+ <tr><td align="center" valign="top">
29
+ <table width="650" border="0" cellpadding="0" cellspacing="20">
30
+ <tr>
31
+ <td style="padding: 10px; border: 1px solid #eed3d7; background-color: #f2dede">
32
+ <h3 style="color: #b94a48">
33
+ <%= @exception.class.to_s =~ /^[aeiou]/i ? 'An' : 'A' %> <%= @exception.class %> occurred in background at <%= @timestamp %> :
34
+ </h3>
35
+ <p style="color: #b94a48"><%= @exception.message %></p>
36
+ <pre style="font-size: 12px; padding: 5px; background-color:#f5f5f5">
37
+ <%= @backtrace.first %>
38
+ </pre>
39
+ </td>
40
+ </tr>
41
+ <% sections_content.each do |title, summary| %>
42
+ <tr>
43
+ <td style="border-bottom: 1px solid #eeeeee;"><%= raw title %></td>
44
+ </tr>
45
+ <tr>
46
+ <td><%= raw summary %></td>
47
+ </tr>
48
+ <% end %>
49
+ </table>
50
+ </td></tr>
51
+ </table>
25
52
  </body>
26
53
  </html>
@@ -1,15 +1,14 @@
1
- <%= @exception.class.to_s =~ /^[aeiou]/i ? 'An' : 'A' %> <%= @exception.class %> occurred in background at <%= raw Time.current %> :
1
+ <%= @exception.class.to_s =~ /^[aeiou]/i ? 'An' : 'A' %> <%= @exception.class %> occurred in background at <%= raw @timestamp %> :
2
2
 
3
3
  <%= @exception.message %>
4
4
  <%= @backtrace.first %>
5
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.join
13
- sections = sections.force_encoding('UTF-8').encode('UTF-16LE', :invalid => :replace).encode('UTF-8') if sections.respond_to?(:force_encoding)
14
- %>
15
- <%= raw sections %>
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.join
13
+ %>
14
+ <%= raw sections %>
@@ -5,32 +5,48 @@
5
5
  <title>Exception</title>
6
6
  </head>
7
7
  <body>
8
- <pre style="font-size: 12px">
9
- <%= @exception.class.to_s =~ /^[aeiou]/i ? 'An' : 'A' %> <%= @exception.class %> occurred in <%= @kontroller.controller_name %>#<%= @kontroller.action_name %>:
10
-
11
- <%= raw @exception.message %>
12
- <%= raw @backtrace.first %>
13
8
 
14
9
  <%
15
- sections = @sections.map do |section|
16
- begin
17
- summary = render(section).strip
18
- unless summary.blank?
19
- title = render("title", :title => section).strip
20
- "#{title}\n\n#{summary.gsub(/^/, " ")}\n\n"
21
- end
22
-
23
- rescue Exception => e
24
- title = render("title", :title => section).strip
25
- summary = ["ERROR: Failed to generate exception summary:", [e.class.to_s, e.message].join(": "), e.backtrace && e.backtrace.join("\n")].compact.join("\n\n")
26
-
27
- [title, summary.gsub(/^/, " "), nil].join("\n\n")
10
+ sections_content = @sections.map do |section|
11
+ begin
12
+ summary = render(section).strip
13
+ unless summary.blank?
14
+ title = render("title", title: section).strip
15
+ [title, summary]
28
16
  end
29
- end.join
30
- sections = sections.force_encoding('UTF-8').encode('UTF-16LE', :invalid => :replace).encode('UTF-8') if sections.respond_to?(:force_encoding)
17
+ rescue Exception => e
18
+ title = render("title", title: section).strip
19
+ summary = ["ERROR: Failed to generate exception summary:", [e.class.to_s, e.message].join(": "), e.backtrace && e.backtrace.join("\n")].compact.join("\n\n")
20
+ [title, summary]
21
+ end
22
+ end
31
23
  %>
32
24
 
33
- <%= raw sections %>
34
- </pre>
25
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
26
+ <tr><td align="center" valign="top">
27
+ <table width="650" border="0" cellpadding="0" cellspacing="20">
28
+ <tr>
29
+ <td style="padding: 10px; border: 1px solid #eed3d7; background-color: #f2dede">
30
+ <h3 style="color: #b94a48">
31
+ <%= @exception.class.to_s =~ /^[aeiou]/i ? 'An' : 'A' %> <%= @exception.class %> occurred in <%= @kontroller.controller_name %>#<%= @kontroller.action_name %>:
32
+ </h3>
33
+ <p style="color: #b94a48"><%= @exception.message %></p>
34
+ <pre style="font-size: 12px; padding: 5px; background-color:#f5f5f5">
35
+ <%= @backtrace.first %>
36
+ </pre>
37
+ </td>
38
+ </tr>
39
+ <% sections_content.each do |title, summary| %>
40
+ <tr>
41
+ <td style="border-bottom: 1px solid #eeeeee;"><%= raw title %></td>
42
+ </tr>
43
+ <tr>
44
+ <td><%= raw summary %></td>
45
+ </tr>
46
+ <% end %>
47
+ </table>
48
+ </td></tr>
49
+ </table>
50
+
35
51
  </body>
36
52
  </html>