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 CHANGED
@@ -1,6 +1,17 @@
1
1
  module Tocsin
2
2
  class Config
3
- attr_accessor :logger, :queue, :recipient_groups, :from_address
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
@@ -1,3 +1,3 @@
1
1
  module Tocsin
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
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
- notifier.notify(recipient_list, alert)
124
- Tocsin.logger.info { "Notification sent to #{recipient_list.inspect} via #{notifier_key} for alert #{alert.id}." }
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
- Tocsin.logger.error { "No recipients associated with alert: \n #{alert.inspect}" }
134
+ logger.error { "No recipients associated with alert: \n #{alert.inspect}" }
127
135
  elsif notifier.nil?
128
- Tocsin.logger.error { "Raised alert with ID=#{alert.id} for unregistered notifier '#{notifier_key}'." }
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
- def id
13
- 1
14
- end
15
-
16
- def category
17
- end
18
-
19
- def severity
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(stub("alert", :id => 1))
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.0
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-09 00:00:00.000000000 Z
13
+ date: 2013-04-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec