tocsin 0.1.0 → 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/lib/tocsin/config.rb +12 -15
- data/lib/tocsin/version.rb +1 -1
- data/lib/tocsin.rb +14 -6
- data/spec/spec_helper.rb +11 -14
- data/spec/tocsin_spec.rb +56 -10
- metadata +2 -2
data/lib/tocsin/config.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
module Tocsin
|
2
2
|
class Config
|
3
|
-
attr_accessor :logger, :queue, :recipient_groups
|
3
|
+
attr_accessor :exception_level, :from_address, :logger, :queue, :recipient_groups
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@exception_level = StandardError
|
7
|
+
@logger = select_logger
|
8
|
+
@queue = :high
|
9
|
+
end
|
10
|
+
|
11
|
+
def select_logger
|
12
|
+
rails = defined?(Rails) && Rails.respond_to?(:logger)
|
13
|
+
rails ? Rails.logger : Logger.new($stderr)
|
14
|
+
end
|
4
15
|
|
5
16
|
# notify [r1, r2], :of => filters, :by => notifier
|
6
17
|
def notify(recipients, parameters)
|
@@ -14,19 +25,5 @@ module Tocsin
|
|
14
25
|
:notifier => notifier}.merge(filters)
|
15
26
|
self.recipient_groups.push(group_config)
|
16
27
|
end
|
17
|
-
|
18
|
-
def queue
|
19
|
-
@queue ||= :high
|
20
|
-
end
|
21
|
-
|
22
|
-
def logger
|
23
|
-
@logger ||= Rails.logger
|
24
|
-
rescue NameError, NoMethodError => e
|
25
|
-
ok = [ /^uninitialized constant .*Rails$/,
|
26
|
-
/^undefined method `logger'/
|
27
|
-
].any?{|regex| e.message =~ regex }
|
28
|
-
raise unless ok
|
29
|
-
@logger ||= Logger.new($stderr)
|
30
|
-
end
|
31
28
|
end
|
32
29
|
end
|
data/lib/tocsin/version.rb
CHANGED
data/lib/tocsin.rb
CHANGED
@@ -42,7 +42,7 @@ module Tocsin
|
|
42
42
|
def self.watch(options={})
|
43
43
|
begin
|
44
44
|
yield
|
45
|
-
rescue => e
|
45
|
+
rescue exception_level => e
|
46
46
|
raise_alert(e, options)
|
47
47
|
end
|
48
48
|
end
|
@@ -51,7 +51,7 @@ module Tocsin
|
|
51
51
|
def self.watch!(options={})
|
52
52
|
begin
|
53
53
|
yield
|
54
|
-
rescue => e
|
54
|
+
rescue exception_level => e
|
55
55
|
raise_alert(e, options)
|
56
56
|
raise e
|
57
57
|
end
|
@@ -112,6 +112,10 @@ module Tocsin
|
|
112
112
|
|
113
113
|
private
|
114
114
|
|
115
|
+
def self.exception_level
|
116
|
+
config.exception_level
|
117
|
+
end
|
118
|
+
|
115
119
|
def self.sound(alert)
|
116
120
|
alert = Tocsin::Alert.find(alert) unless alert.is_a?(Tocsin::Alert)
|
117
121
|
recipients = Tocsin.recipients(alert)
|
@@ -120,12 +124,16 @@ module Tocsin
|
|
120
124
|
notifier = Tocsin::Notifiers[notifier_key]
|
121
125
|
|
122
126
|
if notifier && recipient_list.any?
|
123
|
-
|
124
|
-
|
127
|
+
logger.info { "Sending notification to #{recipient_list.inspect} via #{notifier_key} for alert #{alert.id}." }
|
128
|
+
begin
|
129
|
+
notifier.notify(recipient_list, alert)
|
130
|
+
rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Errno::ENETUNREACH, Errno::ETIMEDOUT => e
|
131
|
+
logger.error { "Notification failed. #{e.to_s}:\n#{e.backtrace.join('\n')}" }
|
132
|
+
end
|
125
133
|
elsif recipient_list.empty?
|
126
|
-
|
134
|
+
logger.error { "No recipients associated with alert: \n #{alert.inspect}" }
|
127
135
|
elsif notifier.nil?
|
128
|
-
|
136
|
+
logger.error { "Raised alert with ID=#{alert.id} for unregistered notifier '#{notifier_key}'." }
|
129
137
|
end
|
130
138
|
end
|
131
139
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -9,26 +9,23 @@ Mail.defaults do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
class Tocsin::Alert
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
attr_accessor :id, :exception, :backtrace, :category, :severity, :message
|
13
|
+
|
14
|
+
def initialize(args = {})
|
15
|
+
@id = 1
|
16
|
+
@backtrace = args[:backtrace]
|
17
|
+
@exception = args[:exception]
|
18
|
+
@category = args[:category]
|
19
|
+
@severity = args[:severity]
|
20
|
+
@message = args[:message]
|
20
21
|
end
|
21
22
|
|
22
23
|
def self.create(*args)
|
23
|
-
self.new
|
24
|
+
self.new(*args)
|
24
25
|
end
|
25
26
|
|
26
27
|
def self.find(*args)
|
27
|
-
self.new
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.logger
|
31
|
-
@logger ||= Logger.new($stdout)
|
28
|
+
self.new(*args)
|
32
29
|
end
|
33
30
|
end
|
34
31
|
|
data/spec/tocsin_spec.rb
CHANGED
@@ -22,13 +22,13 @@ describe Tocsin do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
context "when an exception has already been rescued" do
|
25
|
-
it "raises an alert" do
|
26
|
-
Tocsin::Alert.expects(:create).returns(
|
25
|
+
it "raises (and returns) an alert" do
|
26
|
+
Tocsin::Alert.expects(:create).returns(Tocsin::Alert.new)
|
27
27
|
|
28
28
|
begin
|
29
29
|
raise "Testing"
|
30
30
|
rescue => e
|
31
|
-
Tocsin.raise_alert(e, alert_options)
|
31
|
+
Tocsin.raise_alert(e, alert_options).should be_a_kind_of(Tocsin::Alert)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -44,6 +44,25 @@ describe Tocsin do
|
|
44
44
|
}.should_not raise_error
|
45
45
|
end
|
46
46
|
|
47
|
+
it "normally does not rescue low-level Exceptions" do
|
48
|
+
expect { Tocsin.watch(alert_options) do raise Exception.new end }.to raise_error
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when configured to catch all Exceptions" do
|
52
|
+
before {
|
53
|
+
Tocsin.config.exception_level = Exception
|
54
|
+
}
|
55
|
+
|
56
|
+
it "can rescue low-level Exceptions too" do
|
57
|
+
expect { Tocsin.watch(alert_options) do raise Exception.new end }.to_not raise_error
|
58
|
+
end
|
59
|
+
|
60
|
+
it "still creates an alert when watch!-ing a block which raises an Exception" do
|
61
|
+
Tocsin.expects(:raise_alert).once
|
62
|
+
expect { Tocsin.watch!(alert_options) do raise Exception.new end }.to raise_error
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
47
66
|
it "provides a watch! method which both send an alert and re-raises the exception" do
|
48
67
|
Tocsin.expects(:raise_alert).with(is_a(Exception), has_entries(alert_options))
|
49
68
|
|
@@ -163,15 +182,18 @@ describe Tocsin do
|
|
163
182
|
Tocsin.raise_alert(exception, alert_options)
|
164
183
|
end
|
165
184
|
|
185
|
+
let(:attributes) do
|
186
|
+
{ :exception => exception.to_s,
|
187
|
+
:backtrace => exception.backtrace.join("\n"),
|
188
|
+
:severity => alert_options[:severity].to_s,
|
189
|
+
:message => alert_options[:message].to_s,
|
190
|
+
:category => alert_options[:category].to_s
|
191
|
+
}
|
192
|
+
end
|
193
|
+
|
166
194
|
describe "the created Tocsin::Alert object" do
|
167
195
|
it "is created with appropriate fields" do
|
168
|
-
Tocsin::Alert.expects(:create).with(has_entries(
|
169
|
-
:exception => exception.to_s,
|
170
|
-
:backtrace => exception.backtrace.join("\n"),
|
171
|
-
:severity => alert_options[:severity].to_s,
|
172
|
-
:message => alert_options[:message].to_s,
|
173
|
-
:category => alert_options[:category].to_s
|
174
|
-
)).returns(stub("alert", :id => 1))
|
196
|
+
Tocsin::Alert.expects(:create).with(has_entries(attributes)).returns(Tocsin::Alert.new)
|
175
197
|
alert
|
176
198
|
end
|
177
199
|
end
|
@@ -198,6 +220,30 @@ describe Tocsin do
|
|
198
220
|
expect { alert }.to_not raise_error
|
199
221
|
end
|
200
222
|
|
223
|
+
context "common communication errors" do
|
224
|
+
before do
|
225
|
+
Tocsin.configure do |c|
|
226
|
+
c.notify ["a@b.com"], :of => { :severity => /.*/ }
|
227
|
+
c.logger = Logger.new('/dev/null')
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
errors = [ Timeout::Error,
|
232
|
+
Errno::EHOSTUNREACH,
|
233
|
+
Errno::ECONNREFUSED,
|
234
|
+
Errno::ENETUNREACH,
|
235
|
+
Errno::ETIMEDOUT ]
|
236
|
+
|
237
|
+
errors.each do |err|
|
238
|
+
it "logs #{err.to_s} without exploding" do
|
239
|
+
alert_options.merge!(now: true)
|
240
|
+
Mail.expects(:deliver).raises(err)
|
241
|
+
Tocsin.logger.expects(:error)
|
242
|
+
expect { alert }.to_not raise_error
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
201
247
|
end
|
202
248
|
|
203
249
|
describe Tocsin::NotificationJob do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tocsin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-04-
|
13
|
+
date: 2013-04-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|