exception_handling 0.1.1
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.
- data/.gitignore +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +79 -0
- data/LICENSE +22 -0
- data/README +1 -0
- data/Rakefile +9 -0
- data/config/exception_filters.yml +138 -0
- data/exception_handling.gemspec +24 -0
- data/lib/exception_handling/version.rb +3 -0
- data/lib/exception_handling.rb +630 -0
- data/lib/exception_handling_mailer.rb +77 -0
- data/test/exception_handling_test.rb +923 -0
- data/test/mocha_patch.rb +63 -0
- data/test/test_helper.rb +93 -0
- data/views/exception_handling/mailer/escalation_notification.html.erb +14 -0
- data/views/exception_handling/mailer/exception_notification.html.erb +81 -0
- data/views/exception_handling/mailer/log_parser_exception_notification.html.erb +82 -0
- metadata +177 -0
data/test/mocha_patch.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
_ = ActiveSupport::Testing::SetupAndTeardown::ForClassicTestUnit
|
2
|
+
module ActiveSupport::Testing::SetupAndTeardown::ForClassicTestUnit
|
3
|
+
# This redefinition is unfortunate but test/unit shows us no alternative.
|
4
|
+
# Doubly unfortunate: hax to support Mocha's hax.
|
5
|
+
# Triply unfortunate to be monkey patching it here. -Colin
|
6
|
+
def run(result)
|
7
|
+
return if @method_name.to_s == "default_test"
|
8
|
+
|
9
|
+
mocha_counter = retrieve_mocha_counter(self, result)
|
10
|
+
yield(Test::Unit::TestCase::STARTED, name)
|
11
|
+
@_result = result
|
12
|
+
|
13
|
+
begin
|
14
|
+
begin
|
15
|
+
run_callbacks :setup do
|
16
|
+
setup
|
17
|
+
__send__(@method_name)
|
18
|
+
mocha_verify(mocha_counter) if mocha_counter
|
19
|
+
end
|
20
|
+
rescue Mocha::ExpectationError => e
|
21
|
+
add_failure(e.message, e.backtrace)
|
22
|
+
rescue Test::Unit::AssertionFailedError => e
|
23
|
+
add_failure(e.message, e.backtrace)
|
24
|
+
rescue Exception => e
|
25
|
+
raise if PASSTHROUGH_EXCEPTIONS.include?(e.class)
|
26
|
+
add_error(e)
|
27
|
+
ensure
|
28
|
+
begin
|
29
|
+
teardown
|
30
|
+
run_callbacks :teardown
|
31
|
+
rescue Mocha::ExpectationError => e
|
32
|
+
add_failure(e.message, e.backtrace)
|
33
|
+
rescue Test::Unit::AssertionFailedError => e
|
34
|
+
add_failure(e.message, e.backtrace)
|
35
|
+
rescue Exception => e
|
36
|
+
raise if PASSTHROUGH_EXCEPTIONS.include?(e.class)
|
37
|
+
add_error(e)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
ensure
|
41
|
+
mocha_teardown if mocha_counter
|
42
|
+
end
|
43
|
+
|
44
|
+
result.add_run
|
45
|
+
yield(Test::Unit::TestCase::FINISHED, name)
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def retrieve_mocha_counter(test_case, result) #:nodoc:
|
51
|
+
if respond_to?(:mocha_verify) # using mocha
|
52
|
+
if defined?(Mocha::TestCaseAdapter::AssertionCounter)
|
53
|
+
Mocha::TestCaseAdapter::AssertionCounter.new(result)
|
54
|
+
elsif defined?(Mocha::Integration::TestUnit::AssertionCounter)
|
55
|
+
Mocha::Integration::TestUnit::AssertionCounter.new(result)
|
56
|
+
elsif defined?(Mocha::MonkeyPatching::TestUnit::AssertionCounter)
|
57
|
+
Mocha::MonkeyPatching::TestUnit::AssertionCounter.new(result)
|
58
|
+
else
|
59
|
+
Mocha::Integration::AssertionCounter.new(test_case)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/time'
|
3
|
+
require 'active_support/test_case'
|
4
|
+
require 'action_mailer'
|
5
|
+
require 'shoulda'
|
6
|
+
require 'mocha/setup'
|
7
|
+
require 'test/mocha_patch'
|
8
|
+
|
9
|
+
ActionMailer::Base.delivery_method = :test
|
10
|
+
|
11
|
+
_ = ActiveSupport
|
12
|
+
_ = ActiveSupport::TestCase
|
13
|
+
|
14
|
+
class ActiveSupport::TestCase
|
15
|
+
@@constant_overrides = []
|
16
|
+
|
17
|
+
setup do
|
18
|
+
unless @@constant_overrides.nil? || @@constant_overrides.empty?
|
19
|
+
raise "Uh-oh! constant_overrides left over: #{@@constant_overrides.inspect}"
|
20
|
+
end
|
21
|
+
|
22
|
+
Time.now_override = nil
|
23
|
+
|
24
|
+
ActionMailer::Base.deliveries.clear
|
25
|
+
end
|
26
|
+
|
27
|
+
teardown do
|
28
|
+
@@constant_overrides && @@constant_overrides.reverse.each do |parent_module, k, v|
|
29
|
+
ExceptionHandling.ensure_safe "constant cleanup #{k.inspect}, #{parent_module}(#{parent_module.class})::#{v.inspect}(#{v.class})" do
|
30
|
+
silence_warnings do
|
31
|
+
if v == :never_defined
|
32
|
+
parent_module.send(:remove_const, k)
|
33
|
+
else
|
34
|
+
parent_module.const_set(k, v)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
@@constant_overrides = []
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_test_const(const_name, value)
|
43
|
+
const_name.is_a?(Symbol) and const_name = const_name.to_s
|
44
|
+
const_name.is_a?(String) or raise "Pass the constant name, not its value!"
|
45
|
+
|
46
|
+
final_parent_module = final_const_name = nil
|
47
|
+
original_value =
|
48
|
+
const_name.split('::').reduce(Object) do |parent_module, nested_const_name|
|
49
|
+
parent_module == :never_defined and raise "You need to set each parent constant earlier! #{nested_const_name}"
|
50
|
+
final_parent_module = parent_module
|
51
|
+
final_const_name = nested_const_name
|
52
|
+
parent_module.const_get(nested_const_name) rescue :never_defined
|
53
|
+
end
|
54
|
+
|
55
|
+
@@constant_overrides << [final_parent_module, final_const_name, original_value]
|
56
|
+
|
57
|
+
silence_warnings { final_parent_module.const_set(final_const_name, value) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def assert_emails(expected, message = nil)
|
61
|
+
if block_given?
|
62
|
+
original_count = ActionMailer::Base.deliveries.size
|
63
|
+
yield
|
64
|
+
else
|
65
|
+
original_count = 0
|
66
|
+
end
|
67
|
+
assert_equal expected, ActionMailer::Base.deliveries.size - original_count, "wrong number of emails#{ ': ' + message.to_s if message}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Time
|
72
|
+
class << self
|
73
|
+
attr_reader :now_override
|
74
|
+
|
75
|
+
def now_override= override_time
|
76
|
+
if ActiveSupport::TimeWithZone === override_time
|
77
|
+
override_time = override_time.localtime
|
78
|
+
else
|
79
|
+
override_time.nil? || Time === override_time or raise "override_time should be a Time object, but was a #{override_time.class.name}"
|
80
|
+
end
|
81
|
+
@now_override = override_time
|
82
|
+
end
|
83
|
+
|
84
|
+
unless defined? @@_old_now_defined
|
85
|
+
alias old_now now
|
86
|
+
@@_old_now_defined = true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.now
|
91
|
+
now_override ? now_override.dup : old_now
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<title>Exception Escalation</title>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<h3><%=h @summary %></h3>
|
10
|
+
<b>Error #:</b> <%= h(@cleaned_data[:timestamp]).presence || '<i>no error #</i>'.html_safe -%><br />
|
11
|
+
<b>Exception:</b> <%= h(@cleaned_data[:error_string]).gsub("\n","<br/>\n").gsub(/ {2,}/) { |spaces| ' '*spaces.size }.html_safe %><br />
|
12
|
+
<b>Server:</b> <%= h(@server).presence || '<i>hostname not set</i>'.html_safe -%><br />
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1,81 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<title>Exception Email</title>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
|
10
|
+
<% if @cleaned_data[:first_seen_at] %>
|
11
|
+
<p> This exception occurred <%= @cleaned_data[:occurrences] %> times since <%= @cleaned_data[:first_seen_at] %>.</p>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<b>Error #:</b> <%= @cleaned_data[:timestamp] -%><br />
|
15
|
+
<b>Server:</b> <%= @cleaned_data[:server].presence || '<i>hostname not set</i>'.html_safe -%><br />
|
16
|
+
|
17
|
+
<b>URL:</b><br />
|
18
|
+
<% if (request = @cleaned_data[:request]) %>
|
19
|
+
<%= request[:url] || '<i>no URL in request data</i>'.html_safe %> <br />
|
20
|
+
Referred from: <%= @cleaned_data[:environment]['HTTP_REFERER'] || '<i>no referrer</i>'.html_safe -%><br/>
|
21
|
+
<% else %>
|
22
|
+
<i>no URL accessed</i>
|
23
|
+
<% end %>
|
24
|
+
<br />
|
25
|
+
<br />
|
26
|
+
|
27
|
+
<b>User summary:</b><br />
|
28
|
+
<% if (user_details = @cleaned_data[:user_details]) && ( user_details[:user] || user_details[:organization] ) %>
|
29
|
+
User: <%= user_details[:user] %> (<%= user_details[:username] %>)<br />
|
30
|
+
Organization: <%= user_details[:organization] %> <br />
|
31
|
+
|
32
|
+
<% if user_details[:impersonated_organization] %>
|
33
|
+
<br />
|
34
|
+
<b>Impersonating:</b><br />
|
35
|
+
Organization: <%= user_details[:impersonated_organization] %>
|
36
|
+
<% end %>
|
37
|
+
<% else %>
|
38
|
+
<i>No user logged in.</i>
|
39
|
+
<% end %>
|
40
|
+
|
41
|
+
<br />
|
42
|
+
<br />
|
43
|
+
<hr />
|
44
|
+
|
45
|
+
<h3>Exception:</h3>
|
46
|
+
<%= h(@cleaned_data[:error]).gsub("\n","<br/>\n").gsub(/ {2,}/) { |spaces| ' '*spaces.size }.html_safe %>
|
47
|
+
|
48
|
+
<br />
|
49
|
+
<br />
|
50
|
+
|
51
|
+
<h3>Where:</h3>
|
52
|
+
<% location = @cleaned_data[:location] %>
|
53
|
+
<%= "#{location[:controller]}##{location[:action]}<br />" if location && location[:controller] -%>
|
54
|
+
<%= "#{location[:file]}, line #{location[:line]}<br />" if location && location[:file] -%>
|
55
|
+
|
56
|
+
<% for section in ExceptionHandling::SECTIONS %>
|
57
|
+
<% section_value = @cleaned_data[section] %>
|
58
|
+
<% if section_value %>
|
59
|
+
<h3><%= section.to_s.capitalize -%>:</h3>
|
60
|
+
<pre style="font-size: 12px; font-family: 'Courier New','Arial',sans-serif">
|
61
|
+
<%= case section_value
|
62
|
+
when Hash
|
63
|
+
section_value[:to_s]
|
64
|
+
when Array
|
65
|
+
section_value.join( "\n" )
|
66
|
+
when NilClass # omitted
|
67
|
+
else
|
68
|
+
if section_value.respond_to?(:to_s)
|
69
|
+
section_value.to_s
|
70
|
+
else
|
71
|
+
raise "Unexpected value #{section_value.inspect} for section #{section}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
-%>
|
75
|
+
</pre>
|
76
|
+
<% end %>
|
77
|
+
|
78
|
+
<% end %>
|
79
|
+
|
80
|
+
</body>
|
81
|
+
</html>
|
@@ -0,0 +1,82 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<title>Exception Email</title>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
|
10
|
+
<% if @cleaned_data[:first_seen_at] %>
|
11
|
+
<p> This exception occurred <%= @cleaned_data[:occurrences] %> times since <%= @cleaned_data[:first_seen_at] %>.</p>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<b>Error # </b><%= @cleaned_data[:timestamp] -%><br />
|
15
|
+
|
16
|
+
<b>URL:</b><br />
|
17
|
+
<% if (request = @cleaned_data[:request]) %>
|
18
|
+
<%= request[:url] || '<i>no URL in request data</i>'.html_safe %> <br />
|
19
|
+
Referred from: <%= (@cleaned_data[:environment]['HTTP_REFERER'] || '<i>no referrer</i>').html_safe %>
|
20
|
+
<% else %>
|
21
|
+
<i>no URL accessed</i>
|
22
|
+
<% end %>
|
23
|
+
<br />
|
24
|
+
<br />
|
25
|
+
|
26
|
+
<b>User summary:</b><br />
|
27
|
+
<% if (user_details = @cleaned_data[:user_details]) && ( user_details[:user] || user_details[:organization] ) %>
|
28
|
+
User: <%= h user_details[:user] %> (<%= h user_details[:username] %>)<br />
|
29
|
+
Organization: <%= user_details[:organization] %> <br />
|
30
|
+
<%= "Network: #{h user_details[:organization].network if user_details[:organization]}" if !user_details[:organization].is_a?(Network) %>
|
31
|
+
|
32
|
+
<% if @cleaned_data[:user_details][:impersonated_organization] %>
|
33
|
+
<br />
|
34
|
+
<b>Impersonating:</b><br />
|
35
|
+
Organization: <%= h @cleaned_data[:user_details][:impersonated_organization] %>
|
36
|
+
<% end %>
|
37
|
+
<% else %>
|
38
|
+
<i>No user logged in.</i>
|
39
|
+
<% end %>
|
40
|
+
|
41
|
+
<br />
|
42
|
+
<br />
|
43
|
+
<hr />
|
44
|
+
|
45
|
+
<h3>Exception:</h3>
|
46
|
+
<span id="error">
|
47
|
+
<%= h(@cleaned_data[:error]).gsub("\n","<br/>\n").gsub(/ {2,}/) { |spaces| ' '*spaces.size }.html_safe %>
|
48
|
+
</span>
|
49
|
+
|
50
|
+
<br />
|
51
|
+
<br />
|
52
|
+
|
53
|
+
<h3>Where:</h3>
|
54
|
+
<%= "#{ h location[:controller]}##{ h location[:action]}<br />".html_safe if (location = @cleaned_data[:location]) && location[:controller] -%>
|
55
|
+
<%= "#{ h location[:file]}, line #{ h location[:line]}<br />".html_safe if (location = @cleaned_data[:location]) && location[:file] -%>
|
56
|
+
|
57
|
+
<br />
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
<% for section in ExceptionHandling::SECTIONS %>
|
62
|
+
<% section_value = @cleaned_data[section] %>
|
63
|
+
<% if section_value %>
|
64
|
+
<h3><%= section.to_s.capitalize -%>:</h3>
|
65
|
+
<pre id="<%= section.to_s.capitalize -%>" style="font-size: 12px; font-family: 'Courier New',Arial,sans-serif">
|
66
|
+
<%= case section_value
|
67
|
+
when Hash
|
68
|
+
section_value[:to_s]
|
69
|
+
when Array
|
70
|
+
section_value.join( "\n" )
|
71
|
+
when NilClass # omitted
|
72
|
+
else
|
73
|
+
raise "Unexpected value #{section_value.inspect} for section #{section}"
|
74
|
+
end
|
75
|
+
-%>
|
76
|
+
</pre>
|
77
|
+
<% end %>
|
78
|
+
|
79
|
+
<% end %>
|
80
|
+
|
81
|
+
</body>
|
82
|
+
</html>
|
metadata
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: exception_handling
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Colin Kelley
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2013-08-26 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
type: :runtime
|
22
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
segments:
|
27
|
+
- 0
|
28
|
+
- 12
|
29
|
+
- 10
|
30
|
+
version: 0.12.10
|
31
|
+
name: eventmachine
|
32
|
+
requirement: *id001
|
33
|
+
prerelease: false
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
segments:
|
41
|
+
- 3
|
42
|
+
- 2
|
43
|
+
- 13
|
44
|
+
version: 3.2.13
|
45
|
+
name: activesupport
|
46
|
+
requirement: *id002
|
47
|
+
prerelease: false
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 3
|
56
|
+
- 2
|
57
|
+
- 13
|
58
|
+
version: 3.2.13
|
59
|
+
name: actionpack
|
60
|
+
requirement: *id003
|
61
|
+
prerelease: false
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
type: :runtime
|
64
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
segments:
|
69
|
+
- 3
|
70
|
+
- 2
|
71
|
+
- 13
|
72
|
+
version: 3.2.13
|
73
|
+
name: actionmailer
|
74
|
+
requirement: *id004
|
75
|
+
prerelease: false
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
type: :development
|
78
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
- 9
|
85
|
+
version: "0.9"
|
86
|
+
name: rake
|
87
|
+
requirement: *id005
|
88
|
+
prerelease: false
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
type: :development
|
91
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
segments:
|
96
|
+
- 3
|
97
|
+
- 1
|
98
|
+
- 1
|
99
|
+
version: 3.1.1
|
100
|
+
name: shoulda
|
101
|
+
requirement: *id006
|
102
|
+
prerelease: false
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
type: :development
|
105
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
segments:
|
110
|
+
- 0
|
111
|
+
- 13
|
112
|
+
- 0
|
113
|
+
version: 0.13.0
|
114
|
+
name: mocha
|
115
|
+
requirement: *id007
|
116
|
+
prerelease: false
|
117
|
+
description: Exception handling logger/emailer
|
118
|
+
email:
|
119
|
+
- colindkelley@gmail.com
|
120
|
+
executables: []
|
121
|
+
|
122
|
+
extensions: []
|
123
|
+
|
124
|
+
extra_rdoc_files: []
|
125
|
+
|
126
|
+
files:
|
127
|
+
- .gitignore
|
128
|
+
- Gemfile
|
129
|
+
- Gemfile.lock
|
130
|
+
- LICENSE
|
131
|
+
- README
|
132
|
+
- Rakefile
|
133
|
+
- config/exception_filters.yml
|
134
|
+
- exception_handling.gemspec
|
135
|
+
- lib/exception_handling.rb
|
136
|
+
- lib/exception_handling/version.rb
|
137
|
+
- lib/exception_handling_mailer.rb
|
138
|
+
- test/exception_handling_test.rb
|
139
|
+
- test/mocha_patch.rb
|
140
|
+
- test/test_helper.rb
|
141
|
+
- views/exception_handling/mailer/escalation_notification.html.erb
|
142
|
+
- views/exception_handling/mailer/exception_notification.html.erb
|
143
|
+
- views/exception_handling/mailer/log_parser_exception_notification.html.erb
|
144
|
+
has_rdoc: true
|
145
|
+
homepage: https://github.com/RingRevenue/exception_handling
|
146
|
+
licenses: []
|
147
|
+
|
148
|
+
post_install_message:
|
149
|
+
rdoc_options: []
|
150
|
+
|
151
|
+
require_paths:
|
152
|
+
- lib
|
153
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - ">="
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
segments:
|
158
|
+
- 0
|
159
|
+
version: "0"
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
segments:
|
165
|
+
- 0
|
166
|
+
version: "0"
|
167
|
+
requirements: []
|
168
|
+
|
169
|
+
rubyforge_project:
|
170
|
+
rubygems_version: 1.3.6
|
171
|
+
signing_key:
|
172
|
+
specification_version: 3
|
173
|
+
summary: RingRevenue's exception handling logger/emailer layer, based on exception_notifier. Works with Rails or EventMachine or EventMachine+Synchrony.
|
174
|
+
test_files:
|
175
|
+
- test/exception_handling_test.rb
|
176
|
+
- test/mocha_patch.rb
|
177
|
+
- test/test_helper.rb
|