babysitter 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -28,13 +28,27 @@ Or install it yourself as:
28
28
 
29
29
  The default logger does nothing, override if you want to see log output.
30
30
 
31
+ ### Amazon Simple Notification Service Integration
32
+
33
+ Babysitter can also make use of Amazons Simple Notification Service to provide notifications of when exceptions occur.
34
+
35
+ Babysitter.configure do |c|
36
+ c.enable_simple_notification_service(
37
+ access_key_id: "YOUR_ACCESS_KEY_ID",
38
+ secret_address_key: "YOUR_SECRET_ADDRESS_KEY",
39
+ topic_arn: "my-topic-arn"
40
+ )
41
+ end
42
+
31
43
  ### Monitoring
32
44
 
33
45
  monitor = Babysitter.monitor("statsd.bucket.name")
34
- monitor.start("Workername: description") do |progress|
46
+ monitor.start("Workername: description") do |tracker|
35
47
  things_to_do.each do |work|
36
48
  do_some work
37
- progress.inc("Workername: {{count}} tasks completed", 1, counting: :work_things) # report progress here
49
+ tracker.error(:badness,'Something bad happened') if something_bad?
50
+ tracker.warn(:suspicions,'Something supicious happenedd') if something_bad?
51
+ tracker.inc("Workername: {{count}} tasks completed", 1, counting: :things_to_do) # report progress here
38
52
  end
39
53
  end
40
54
 
@@ -42,10 +56,15 @@ The default logger does nothing, override if you want to see log output.
42
56
  This will send statistics to StatsD in the supplied bucket name and will generate logs like this:
43
57
 
44
58
 
45
- INFO -- : Start: update.combinations Matcher generating possible combinations
59
+ INFO -- : Start: statsd.bucket.name Matcher generating possible combinations
46
60
  INFO -- : Done: 100 combinations generated
47
61
  INFO -- : Rate: 20746.88796680498 combinations per second
48
- INFO -- : End: update.combinations
62
+ INFO -- : End: statsd.bucket.name
63
+
64
+ Logging statistics will incremented for bucket names
65
+
66
+ statsd.bucket.name.badness.errors
67
+ statsd.bucket.name.suspicions.warnings
49
68
 
50
69
 
51
70
  Any exceptions that occur will be logged nicely. Exceptions will abort the process.
@@ -6,8 +6,8 @@ require 'babysitter/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "babysitter"
8
8
  gem.version = Babysitter::VERSION
9
- gem.authors = ["Nicolas Overloop", "Paul Grayson", "Andy Roberts"]
10
- gem.email = ["noverloop@gmail.com", "paul.grayson@lonelyplanet.com", "coder@onesandthrees.com"]
9
+ gem.authors = ["Nicolas Overloop", "Paul Grayson", "Andy Roberts", "Mike Wagg"]
10
+ gem.email = ["noverloop@gmail.com", "paul.grayson@lonelyplanet.com", "coder@onesandthrees.com", "michael@guerillatactics.co.uk"]
11
11
  gem.description = %q{Babysits long-running processes and reports progress or failures}
12
12
  gem.summary = %q{Babysits long-running processes and reports progress or failures}
13
13
  gem.homepage = ""
@@ -18,6 +18,7 @@ Gem::Specification.new do |gem|
18
18
  gem.require_paths = ["lib"]
19
19
  gem.add_dependency 'fozzie'
20
20
  gem.add_dependency 'timecop'
21
+ gem.add_dependency 'aws-sdk'
21
22
 
22
23
  gem.add_development_dependency 'awesome_print'
23
24
  gem.add_development_dependency 'rspec'
@@ -4,9 +4,11 @@ require_relative "babysitter/version"
4
4
  require_relative "babysitter/null_logger"
5
5
  require_relative "babysitter/configuration"
6
6
  require_relative "babysitter/logging"
7
- require_relative "babysitter/progress"
7
+ require_relative "babysitter/logger_with_stats"
8
+ require_relative "babysitter/tracker"
8
9
  require_relative "babysitter/monitor"
9
10
  require_relative "babysitter/counter"
11
+ require_relative "babysitter/exception_notifiers"
10
12
  require 'fozzie'
11
13
 
12
14
  module Babysitter
@@ -27,5 +29,8 @@ module Babysitter
27
29
  configuration.logger
28
30
  end
29
31
 
32
+ def self.exception_notifiers
33
+ configuration.exception_notifiers
34
+ end
30
35
 
31
36
  end
@@ -3,11 +3,24 @@ module Babysitter
3
3
  class Configuration
4
4
 
5
5
  attr_writer :logger
6
+ attr_reader :exception_notifiers
7
+
8
+ def initialize
9
+ @exception_notifiers = []
10
+ end
6
11
 
7
12
  def logger
8
13
  @logger ||= NullLogger.new
9
14
  end
10
15
 
16
+ def enable_simple_notification_service(opts = {})
17
+ [:access_key_id, :secret_access_key, :topic_arn].each do |key|
18
+ raise ArgumentError, "#{key} is required" unless opts.has_key?(key)
19
+ end
20
+
21
+ @exception_notifiers << ExceptionNotifiers::SimpleNotificationService.new(opts)
22
+ end
23
+
11
24
  end
12
25
 
13
- end
26
+ end
@@ -0,0 +1 @@
1
+ require_relative "exception_notifiers/simple_notification_service"
@@ -0,0 +1,25 @@
1
+ require 'aws-sdk'
2
+
3
+ module Babysitter
4
+ module ExceptionNotifiers
5
+ class SimpleNotificationService
6
+ def initialize(opts)
7
+ access_key = opts.delete :access_key_id
8
+ secret_access_key = opts.delete :secret_access_key
9
+ @sns = AWS::SNS.new(access_key_id: access_key, secret_access_key: secret_access_key)
10
+ @topic = @sns.topics[opts.delete(:topic_arn)]
11
+ validate_topic
12
+ end
13
+
14
+ def notify(subject, msg)
15
+ @topic.publish(msg, subject: subject)
16
+ end
17
+
18
+ private
19
+
20
+ def validate_topic
21
+ @topic.display_name
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,43 @@
1
+ module Babysitter
2
+ class LoggerWithStats
3
+ include Logging
4
+
5
+ attr_accessor :stat_name_prefix
6
+
7
+ STATS_SUFFIX_BY_METHOD = { warn: :warnings, error: :errors, fatal: :fatals }
8
+
9
+ def initialize(stat_name_prefix)
10
+ @stat_name_prefix = stat_name_prefix
11
+ end
12
+
13
+ def method_missing(meth, *opts)
14
+ unless %w{ info debug error fatal}.include?(meth.to_s)
15
+ super
16
+ return
17
+ end
18
+ stats_suffix_from_method(meth).tap{ |suffix| increment(suffix) if suffix }
19
+ logger.send(meth, *opts)
20
+ end
21
+
22
+ def warn(*opts)
23
+ increment(stats_suffix_from_method(:warn))
24
+ logger.warn(*opts)
25
+ end
26
+
27
+ private
28
+
29
+ def stats_suffix_from_method(meth)
30
+ STATS_SUFFIX_BY_METHOD[meth]
31
+ end
32
+
33
+ def increment(stat_name_suffix)
34
+ Stats.increment full_stat_name(stat_name_suffix)
35
+ end
36
+
37
+ def full_stat_name(stat_name_suffix)
38
+ stat_name_prefix + [stat_name_suffix]
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -11,21 +11,21 @@ module Babysitter
11
11
  def start(msg=nil, log_every=100, &blk)
12
12
  raise ArgumentError, "Stats bucket name must not be blank" if stat_name.nil? or stat_name.empty?
13
13
  log_msg = format_log_message(msg)
14
- progress = Progress.new(log_every, stat_name)
14
+ tracker = Tracker.new(log_every, stat_name)
15
15
  logger.info "Start: #{log_msg}"
16
16
 
17
17
  begin
18
18
  result = Stats.time_to_do stat_name+[:overall] do
19
- blk.call(progress)
19
+ blk.call(tracker)
20
20
  end
21
21
  rescue Exception => e
22
- progress.final_report rescue nil
23
- log_exception_details( log_msg, e )
22
+ tracker.final_report rescue nil
23
+ log_exception_details(log_msg, e)
24
24
  raise
25
25
  end
26
26
 
27
- progress.send_total_stats
28
- progress.final_report
27
+ tracker.send_total_stats
28
+ tracker.final_report
29
29
  logger.info "End: #{log_msg}"
30
30
  result
31
31
  end
@@ -45,11 +45,12 @@ module Babysitter
45
45
  stat_name.is_a?(Array) ? stat_name : stat_name.split('.') unless stat_name.nil? or stat_name.empty?
46
46
  end
47
47
 
48
- def log_exception_details( msg, exception )
49
- logger.error "Aborting: #{msg} due to exception #{exception.class}: #{exception}"
50
- if exception.backtrace
51
- exception.backtrace.each { |line| logger.error " #{line}" }
52
- end
48
+ def log_exception_details(msg, exception)
49
+ lines = ["Aborting: #{msg} due to exception #{exception.class}: #{exception}"]
50
+ lines.concat(exception.backtrace) if exception.backtrace
51
+
52
+ lines.each { |line| logger.error(line) }
53
+ Babysitter.exception_notifiers.each { |notifier| notifier.notify(exception.to_s, lines.join("\n")) }
53
54
  end
54
55
  end
55
56
 
@@ -8,4 +8,4 @@ module Babysitter
8
8
 
9
9
  end
10
10
 
11
- end
11
+ end
@@ -1,5 +1,5 @@
1
1
  module Babysitter
2
- class Progress
2
+ class Tracker
3
3
  include Logging
4
4
 
5
5
  attr_reader :counting, :stat_name, :counter
@@ -24,29 +24,29 @@ module Babysitter
24
24
  counter.log_counter_messsage if counter.final_report?
25
25
  end
26
26
 
27
- def warn(partial_bucket_name, message)
28
- logger.warn(message)
29
- send_warning_stat(partial_bucket_name)
27
+ def warn(topic_name, message)
28
+ logger_with_stats_for(topic_name).warn(message)
30
29
  end
31
30
 
32
- def error(partial_bucket_name, message)
33
- logger.error(message)
34
- send_error_stat(partial_bucket_name)
31
+ def error(topic_name, message)
32
+ logger_with_stats_for(topic_name).error(message)
35
33
  end
36
34
 
37
35
  def send_total_stats
38
36
  counter.send_total_stats
39
37
  end
40
38
 
41
- private
42
-
43
- def send_warning_stat(partial_bucket_name)
44
- Stats.increment stat_name+[partial_bucket_name, :warnings] unless stat_name.nil?
39
+ def logger_with_stats_for(topic_name)
40
+ @loggers ||= {}
41
+ @loggers[topic_name] ||= LoggerWithStats.new(stats_prefix_for_topic(topic_name))
45
42
  end
46
43
 
47
- def send_error_stat(partial_bucket_name)
48
- Stats.increment stat_name+[partial_bucket_name, :errors] unless stat_name.nil?
44
+ private
45
+
46
+ def stats_prefix_for_topic(topic_name)
47
+ stat_name+[topic_name]
49
48
  end
50
49
 
51
50
  end
51
+
52
52
  end
@@ -1,3 +1,3 @@
1
1
  module Babysitter
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -11,7 +11,52 @@ module Babysitter
11
11
  subject.logger.should === null_logger
12
12
  end
13
13
 
14
+ it 'has no exception notifiers' do
15
+ subject.exception_notifiers.should be_empty
16
+ end
17
+
18
+ end
19
+
20
+ describe 'enabling Amazon simple notification service integration' do
21
+ let (:sns_exception_notifier) { double }
22
+ let (:valid_params) { {
23
+ access_key_id: "an-access-key",
24
+ secret_access_key: "a-secret-address-key",
25
+ topic_arn: "my-topic-arn"
26
+ } }
27
+
28
+ before :each do
29
+ Babysitter::ExceptionNotifiers::SimpleNotificationService.stub(:new).and_return(sns_exception_notifier)
30
+ end
31
+
32
+ it 'requires an access key id' do
33
+ valid_params.delete :access_key_id
34
+ -> { subject.enable_simple_notification_service(valid_params) }.should raise_error(ArgumentError, /access_key_id/)
35
+ end
36
+
37
+ it 'requires a secret address key' do
38
+ valid_params.delete :secret_access_key
39
+ -> { subject.enable_simple_notification_service(valid_params) }.should raise_error(ArgumentError, /secret_access_key/)
40
+ end
41
+
42
+ it 'requires a topic arn' do
43
+ valid_params.delete :topic_arn
44
+ -> { subject.enable_simple_notification_service(valid_params) }.should raise_error(ArgumentError, /topic_arn/)
45
+ end
46
+
47
+ it 'adds an exception notifier' do
48
+ subject.enable_simple_notification_service(valid_params)
49
+
50
+ subject.exception_notifiers.should_not be_empty
51
+ subject.exception_notifiers.first.should eql(sns_exception_notifier)
52
+ end
53
+
54
+ it 'configures the exception notifier' do
55
+ ExceptionNotifiers::SimpleNotificationService.should_receive(:new).with(hash_including(valid_params))
56
+
57
+ subject.enable_simple_notification_service(valid_params)
58
+ end
14
59
  end
15
60
 
16
61
  end
17
- end
62
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ module Babysitter
4
+ module ExceptionNotifiers
5
+ describe SimpleNotificationService do
6
+ subject { SimpleNotificationService.new(valid_opts) }
7
+ let(:valid_opts) { {
8
+ access_key_id: 'an-access-key-id',
9
+ secret_access_key: 'a-secret-address-key',
10
+ topic_arn: 'my-topic-arn'
11
+ } }
12
+ let(:sns) { double :sns, topics: { 'my-topic-arn' => topic } }
13
+ let(:topic) { double :topic, publish: nil, display_name: "A topic" }
14
+ before :each do
15
+ AWS::SNS.stub(:new).and_return(sns)
16
+ end
17
+
18
+ it 'uses the options passed to configure the credentials for sns' do
19
+ AWS::SNS.should_receive(:new).with(valid_opts.reject { |key| key == :topic_arn } )
20
+ subject
21
+ end
22
+
23
+ it 'validates the topic by checking it has a display name' do
24
+ topic.should_receive(:display_name)
25
+ subject
26
+ end
27
+
28
+ describe '.notify' do
29
+ let(:message) { "the message" }
30
+ let(:notification_subject) { "the subject" }
31
+
32
+ it 'publishes to the topic specified' do
33
+ topic.should_receive(:publish)
34
+
35
+ subject.notify(notification_subject, message)
36
+ end
37
+
38
+ it 'publishes the message' do
39
+ topic.should_receive(:publish).with(message, hash_including(subject: notification_subject))
40
+
41
+ subject.notify(notification_subject, message)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -121,11 +121,14 @@ module Babysitter
121
121
  monitor.warn(:my_warning_bucket, 'my warning message')
122
122
  end
123
123
  end
124
+ before(:each) do
125
+ Babysitter.stub(:logger).and_return(logger)
126
+ logger.stub!(:warn)
127
+ Stats.stub!(:increment)
128
+ end
124
129
 
125
130
  it 'calls logger.info with the warning message' do
126
- Progress.any_instance.stub(:logger).and_return(logger)
127
131
  logger.should_receive(:warn).with( "my warning message")
128
- Stats.stub!(:increment)
129
132
  subject.start(&start_block_with_warning)
130
133
  end
131
134
 
@@ -142,11 +145,14 @@ module Babysitter
142
145
  monitor.error(:my_error_bucket, 'my error message')
143
146
  end
144
147
  end
148
+ before(:each) do
149
+ Babysitter.stub(:logger).and_return(logger)
150
+ logger.stub!(:error)
151
+ Stats.stub!(:increment)
152
+ end
145
153
 
146
154
  it 'calls logger.error with the error message' do
147
- Progress.any_instance.stub(:logger).and_return(logger)
148
155
  logger.should_receive(:error).with( "my error message")
149
- Stats.stub!(:increment)
150
156
  subject.start(&start_block_with_error)
151
157
  end
152
158
 
@@ -157,6 +163,46 @@ module Babysitter
157
163
  end
158
164
  end
159
165
 
166
+ context 'when the block raises an error' do
167
+ let(:error) { RuntimeError.new(error_message) }
168
+ let(:backtrace) { 3.times.map { |i| "Line #{i}"} }
169
+ let(:error_message) { 'A big fat error' }
170
+ let(:expected_message) { "Aborting: #{bucket_name} due to exception RuntimeError: #{error_message}" }
171
+ let(:start_block_with_error) { Proc.new { raise error } }
172
+ before(:each) do
173
+ error.stub(:backtrace).and_return(backtrace)
174
+ Babysitter.stub(:logger).and_return(logger)
175
+ Babysitter.stub(:exception_notifiers).and_return(2.times.map { double notify: nil })
176
+ logger.stub!(:error)
177
+ Stats.stub!(:increment)
178
+ end
179
+
180
+ it 'calls logger.error with the exeption details' do
181
+ logger.should_receive(:error).with(expected_message)
182
+ backtrace.each do |line|
183
+ logger.should_receive(:error).with(/\w*#{line}/)
184
+ end
185
+
186
+ begin
187
+ subject.start(&start_block_with_error)
188
+ rescue
189
+ end
190
+ end
191
+
192
+ it 'calls each exception notifier with the exception details' do
193
+ message = [expected_message].concat(backtrace).join("\n")
194
+
195
+ Babysitter.exception_notifiers.each do |exception_notifier|
196
+ exception_notifier.should_receive(:notify).with(error_message, message)
197
+ end
198
+
199
+ begin
200
+ subject.start(&start_block_with_error)
201
+ rescue
202
+ end
203
+ end
204
+ end
205
+
160
206
  context 'when the block increments 2 times at intervals of 2 seconds' do
161
207
  let(:start_block_for_timing) do
162
208
  Proc.new do |counter|
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ module Babysitter
4
+ describe Tracker do
5
+
6
+ subject{ Tracker.new(log_interval, stat_bucket_prefix) }
7
+ let(:log_interval) { 5 }
8
+ let(:stat_bucket_prefix) { [:my, :stat, :bucket, :prefix] }
9
+ let(:logger) { double('boring old vanilla babysitter logger') }
10
+ before(:each) do
11
+ Babysitter.stub(:logger).and_return(logger)
12
+ end
13
+
14
+ describe '#logger_with_stats_for' do
15
+
16
+ it 'returns the same logger when passed the same symbol twice' do
17
+ l1 = subject.logger_with_stats_for(:lodgings)
18
+ l2 = subject.logger_with_stats_for(:lodgings)
19
+ l1.should be_equal(l2)
20
+ end
21
+
22
+ it 'returns different loggers when passed different symbols' do
23
+ l = subject.logger_with_stats_for(:lodgings)
24
+ p = subject.logger_with_stats_for(:places)
25
+ l.should_not be_equal(p)
26
+ end
27
+
28
+ end # describe '#logger_with_stats' do
29
+
30
+ describe 'logger returned by logger_with_stats_for(some_topic)' do
31
+ subject{ Tracker.new(log_interval, stat_bucket_prefix).logger_with_stats_for(some_topic) }
32
+ let(:some_topic) { :some_topic }
33
+ let(:text_of_the_message) {'the message we want in the logs'}
34
+
35
+ { warn: :warnings, error: :errors, fatal: :fatals }.each do |message_type, stats_bucket_suffix|
36
+ describe "##{message_type}" do
37
+ before(:each) do
38
+ logger.stub(message_type)
39
+ Stats.stub!(:increment)
40
+ end
41
+
42
+ it 'logs the message' do
43
+ logger.should_receive(message_type).with(text_of_the_message)
44
+ subject.send(message_type, text_of_the_message)
45
+ end
46
+
47
+ it 'sends the stats' do
48
+ expected_stats_bucket = stat_bucket_prefix + [some_topic, stats_bucket_suffix]
49
+ Stats.should_receive(:increment).with(expected_stats_bucket)
50
+ subject.send(message_type, text_of_the_message)
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ [:info, :debug].each do |message_type|
57
+ describe "##{message_type}" do
58
+ before(:each) do
59
+ logger.stub(message_type)
60
+ Stats.stub!(:increment)
61
+ end
62
+
63
+ it 'logs the message' do
64
+ logger.should_receive(message_type).with(text_of_the_message)
65
+ subject.send(message_type, text_of_the_message)
66
+ end
67
+
68
+ it 'sends no stats' do
69
+ Stats.should_not_receive(:increment)
70
+ subject.send(message_type, text_of_the_message)
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ end # describe 'logger returned by logger_with_stats_for(:something)' do
77
+
78
+ end
79
+ end
80
+
81
+
@@ -38,4 +38,13 @@ describe Babysitter do
38
38
  end
39
39
  end
40
40
 
41
+ describe '.exception_notifiers' do
42
+ let(:exception_notifiers) { double('notifiers').as_null_object}
43
+
44
+ it 'returns the notifiers from the configuration' do
45
+ Babysitter::Configuration.any_instance.stub(:exception_notifiers).and_return(exception_notifiers)
46
+ Babysitter.exception_notifiers.should eql(exception_notifiers)
47
+ end
48
+ end
49
+
41
50
  end
metadata CHANGED
@@ -1,17 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: babysitter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Nicolas Overloop
9
9
  - Paul Grayson
10
10
  - Andy Roberts
11
+ - Mike Wagg
11
12
  autorequire:
12
13
  bindir: bin
13
14
  cert_chain: []
14
- date: 2013-01-23 00:00:00.000000000 Z
15
+ date: 2013-01-29 00:00:00.000000000 Z
15
16
  dependencies:
16
17
  - !ruby/object:Gem::Dependency
17
18
  name: fozzie
@@ -45,6 +46,22 @@ dependencies:
45
46
  - - ! '>='
46
47
  - !ruby/object:Gem::Version
47
48
  version: '0'
49
+ - !ruby/object:Gem::Dependency
50
+ name: aws-sdk
51
+ requirement: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
48
65
  - !ruby/object:Gem::Dependency
49
66
  name: awesome_print
50
67
  requirement: !ruby/object:Gem::Requirement
@@ -82,6 +99,7 @@ email:
82
99
  - noverloop@gmail.com
83
100
  - paul.grayson@lonelyplanet.com
84
101
  - coder@onesandthrees.com
102
+ - michael@guerillatactics.co.uk
85
103
  executables: []
86
104
  extensions: []
87
105
  extra_rdoc_files: []
@@ -95,13 +113,18 @@ files:
95
113
  - lib/babysitter.rb
96
114
  - lib/babysitter/configuration.rb
97
115
  - lib/babysitter/counter.rb
116
+ - lib/babysitter/exception_notifiers.rb
117
+ - lib/babysitter/exception_notifiers/simple_notification_service.rb
118
+ - lib/babysitter/logger_with_stats.rb
98
119
  - lib/babysitter/logging.rb
99
120
  - lib/babysitter/monitor.rb
100
121
  - lib/babysitter/null_logger.rb
101
- - lib/babysitter/progress.rb
122
+ - lib/babysitter/tracker.rb
102
123
  - lib/babysitter/version.rb
103
124
  - spec/lib/babysitter/configuration_spec.rb
125
+ - spec/lib/babysitter/exception_notifiers/simple_notification_service_spec.rb
104
126
  - spec/lib/babysitter/monitor_spec.rb
127
+ - spec/lib/babysitter/tracker_spec.rb
105
128
  - spec/lib/babysitter_spec.rb
106
129
  - spec/spec_helper.rb
107
130
  homepage: ''
@@ -124,12 +147,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
147
  version: '0'
125
148
  requirements: []
126
149
  rubyforge_project:
127
- rubygems_version: 1.8.22
150
+ rubygems_version: 1.8.24
128
151
  signing_key:
129
152
  specification_version: 3
130
153
  summary: Babysits long-running processes and reports progress or failures
131
154
  test_files:
132
155
  - spec/lib/babysitter/configuration_spec.rb
156
+ - spec/lib/babysitter/exception_notifiers/simple_notification_service_spec.rb
133
157
  - spec/lib/babysitter/monitor_spec.rb
158
+ - spec/lib/babysitter/tracker_spec.rb
134
159
  - spec/lib/babysitter_spec.rb
135
160
  - spec/spec_helper.rb