babysitter 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -1
- data/babysitter.gemspec +1 -0
- data/lib/babysitter.rb +5 -4
- data/lib/babysitter/{progress_counter.rb → counter.rb} +16 -13
- data/lib/babysitter/monitor.rb +56 -0
- data/lib/babysitter/progress.rb +31 -36
- data/lib/babysitter/version.rb +1 -1
- data/spec/lib/babysitter/{progress_spec.rb → monitor_spec.rb} +72 -10
- data/spec/lib/babysitter_spec.rb +41 -0
- data/spec/spec_helper.rb +1 -1
- metadata +25 -6
data/README.md
CHANGED
data/babysitter.gemspec
CHANGED
@@ -17,6 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
gem.add_dependency 'fozzie'
|
20
|
+
gem.add_dependency 'timecop'
|
20
21
|
|
21
22
|
gem.add_development_dependency 'awesome_print'
|
22
23
|
gem.add_development_dependency 'rspec'
|
data/lib/babysitter.rb
CHANGED
@@ -4,14 +4,15 @@ 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_counter"
|
8
7
|
require_relative "babysitter/progress"
|
9
|
-
|
8
|
+
require_relative "babysitter/monitor"
|
9
|
+
require_relative "babysitter/counter"
|
10
|
+
require 'fozzie'
|
10
11
|
|
11
12
|
module Babysitter
|
12
13
|
|
13
14
|
def self.monitor(*args)
|
14
|
-
|
15
|
+
Monitor.new(*args)
|
15
16
|
end
|
16
17
|
|
17
18
|
def self.configuration
|
@@ -27,4 +28,4 @@ module Babysitter
|
|
27
28
|
end
|
28
29
|
|
29
30
|
|
30
|
-
end
|
31
|
+
end
|
@@ -1,16 +1,17 @@
|
|
1
1
|
module Babysitter
|
2
|
-
class
|
2
|
+
class Counter
|
3
3
|
include Logging
|
4
4
|
|
5
|
-
attr_reader :count, :
|
6
|
-
attr_accessor :log_every
|
5
|
+
attr_reader :count, :log_every, :template, :logged_count, :stat_name, :counting
|
7
6
|
|
8
|
-
|
7
|
+
attr_accessor :template
|
8
|
+
|
9
|
+
def initialize(log_every, opts)
|
9
10
|
@count = 0
|
10
11
|
@logged_count = 0
|
11
|
-
@stat_name = stat_name
|
12
|
-
@counting = :iterations
|
13
12
|
@log_every = log_every
|
13
|
+
@stat_name = opts.delete(:stat_name)
|
14
|
+
@counting = opts.delete(:counting)
|
14
15
|
@timer_start = Time.now
|
15
16
|
end
|
16
17
|
|
@@ -23,16 +24,14 @@ module Babysitter
|
|
23
24
|
log_counter_messsage if log_this_time
|
24
25
|
end
|
25
26
|
|
26
|
-
def final_report
|
27
|
-
log_counter_messsage if !(template.nil? or template.empty?) && count != logged_count
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
27
|
def block_number(count)
|
33
28
|
count / @log_every
|
34
29
|
end
|
35
30
|
|
31
|
+
def final_report?
|
32
|
+
!(template.nil? or template.empty?) && count != logged_count
|
33
|
+
end
|
34
|
+
|
36
35
|
def log_counter_messsage
|
37
36
|
logger.info( "Done: #{template.gsub("{{count}}", count.to_s)}" )
|
38
37
|
send_progress_stats(count - logged_count)
|
@@ -53,5 +52,9 @@ module Babysitter
|
|
53
52
|
Stats.count stat_name+[counting, :progress], progress unless stat_name.nil?
|
54
53
|
end
|
55
54
|
|
55
|
+
def send_total_stats
|
56
|
+
Stats.gauge stat_name+[counting, :total], count
|
57
|
+
end
|
58
|
+
|
56
59
|
end
|
57
|
-
end
|
60
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Babysitter
|
2
|
+
class Monitor
|
3
|
+
include Logging
|
4
|
+
|
5
|
+
attr_accessor :stat_name
|
6
|
+
|
7
|
+
def initialize(stat_name=nil)
|
8
|
+
@stat_name = convert_stat_name_to_array(stat_name)
|
9
|
+
end
|
10
|
+
|
11
|
+
def start(msg=nil, log_every=100, &blk)
|
12
|
+
raise ArgumentError, "Stats bucket name must not be blank" if stat_name.nil? or stat_name.empty?
|
13
|
+
log_msg = format_log_message(msg)
|
14
|
+
progress = Progress.new(log_every, stat_name)
|
15
|
+
logger.info "Start: #{log_msg}"
|
16
|
+
|
17
|
+
begin
|
18
|
+
result = Stats.time_to_do stat_name+[:overall] do
|
19
|
+
blk.call(progress)
|
20
|
+
end
|
21
|
+
rescue Exception => e
|
22
|
+
progress.final_report rescue nil
|
23
|
+
log_exception_details( log_msg, e )
|
24
|
+
raise
|
25
|
+
end
|
26
|
+
|
27
|
+
progress.send_total_stats
|
28
|
+
progress.final_report
|
29
|
+
logger.info "End: #{log_msg}"
|
30
|
+
result
|
31
|
+
end
|
32
|
+
|
33
|
+
def completed(msg)
|
34
|
+
logger.info "Done: #{msg}"
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def format_log_message(msg)
|
40
|
+
log_msg = stat_name.join('.')
|
41
|
+
[log_msg,msg].compact.join(' ')
|
42
|
+
end
|
43
|
+
|
44
|
+
def convert_stat_name_to_array(stat_name)
|
45
|
+
stat_name.is_a?(Array) ? stat_name : stat_name.split('.') unless stat_name.nil? or stat_name.empty?
|
46
|
+
end
|
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
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/lib/babysitter/progress.rb
CHANGED
@@ -2,56 +2,51 @@ module Babysitter
|
|
2
2
|
class Progress
|
3
3
|
include Logging
|
4
4
|
|
5
|
-
|
5
|
+
attr_reader :counting, :stat_name, :counter
|
6
|
+
attr_accessor :log_every
|
7
|
+
|
8
|
+
def initialize(log_every, stat_name=nil)
|
9
|
+
@stat_name = stat_name
|
10
|
+
@counting = :iterations
|
11
|
+
@log_every = log_every
|
12
|
+
@counter = Counter.new(log_every, stat_name: stat_name, counting: counting)
|
13
|
+
end
|
14
|
+
|
15
|
+
def inc(*args)
|
16
|
+
counter.inc(*args)
|
17
|
+
end
|
6
18
|
|
7
|
-
def
|
8
|
-
|
19
|
+
def count
|
20
|
+
counter.count
|
9
21
|
end
|
10
22
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
counter = ProgressCounter.new(log_every, stat_name)
|
15
|
-
logger.info "Start: #{log_msg}"
|
23
|
+
def final_report
|
24
|
+
counter.log_counter_messsage if counter.final_report?
|
25
|
+
end
|
16
26
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
rescue Exception => e
|
22
|
-
counter.final_report rescue nil
|
23
|
-
log_exception_details( log_msg, e )
|
24
|
-
raise
|
25
|
-
end
|
27
|
+
def warn(partial_bucket_name, message)
|
28
|
+
logger.warn(message)
|
29
|
+
send_warning_stat(partial_bucket_name)
|
30
|
+
end
|
26
31
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
result
|
32
|
+
def error(partial_bucket_name, message)
|
33
|
+
logger.error(message)
|
34
|
+
send_error_stat(partial_bucket_name)
|
31
35
|
end
|
32
36
|
|
33
|
-
def
|
34
|
-
|
37
|
+
def send_total_stats
|
38
|
+
counter.send_total_stats
|
35
39
|
end
|
36
40
|
|
37
41
|
private
|
38
42
|
|
39
|
-
def
|
40
|
-
|
41
|
-
[log_msg,msg].compact.join(' ')
|
43
|
+
def send_warning_stat(partial_bucket_name)
|
44
|
+
Stats.increment stat_name+[partial_bucket_name, :warnings] unless stat_name.nil?
|
42
45
|
end
|
43
46
|
|
44
|
-
def
|
45
|
-
|
47
|
+
def send_error_stat(partial_bucket_name)
|
48
|
+
Stats.increment stat_name+[partial_bucket_name, :errors] unless stat_name.nil?
|
46
49
|
end
|
47
50
|
|
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| Babysitter.logger.error " #{line}" }
|
52
|
-
end
|
53
|
-
end
|
54
51
|
end
|
55
|
-
|
56
|
-
|
57
52
|
end
|
data/lib/babysitter/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
module Babysitter
|
4
|
-
describe
|
4
|
+
describe Monitor do
|
5
5
|
before(:each) do
|
6
6
|
Stats.stub!(:count).with(anything, anything)
|
7
7
|
Stats.stub!(:gauge).with(anything, anything)
|
@@ -9,7 +9,7 @@ module Babysitter
|
|
9
9
|
|
10
10
|
context 'when initialized with a dot separated bucket name' do
|
11
11
|
|
12
|
-
subject{
|
12
|
+
subject{ Monitor.new(bucket_name) }
|
13
13
|
let(:bucket_name) { 'my.splendid.bucket.name' }
|
14
14
|
let(:start_block) { Proc.new{ block_result } }
|
15
15
|
let(:block_result) { double('block result').as_null_object }
|
@@ -17,7 +17,7 @@ module Babysitter
|
|
17
17
|
|
18
18
|
describe '#completed' do
|
19
19
|
it 'logs a done message' do
|
20
|
-
|
20
|
+
Monitor.any_instance.stub(:logger).and_return(logger)
|
21
21
|
logger.should_receive(:info).with("Done: the completed thing")
|
22
22
|
subject.completed('the completed thing')
|
23
23
|
end
|
@@ -36,26 +36,26 @@ module Babysitter
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'calls logger.info with start message' do
|
39
|
-
|
39
|
+
Monitor.any_instance.stub(:logger).and_return(logger)
|
40
40
|
logger.should_receive(:info).with("Start: #{bucket_name}")
|
41
41
|
subject.start(&start_block)
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'calls logger.info with end message' do
|
45
|
-
|
45
|
+
Monitor.any_instance.stub(:logger).and_return(logger)
|
46
46
|
logger.should_receive(:info).with("End: #{bucket_name}")
|
47
47
|
subject.start(&start_block)
|
48
48
|
end
|
49
49
|
|
50
50
|
context 'when the start method is given a message' do
|
51
51
|
it 'calls logger.info with start message' do
|
52
|
-
|
52
|
+
Monitor.any_instance.stub(:logger).and_return(logger)
|
53
53
|
logger.should_receive(:info).with("Start: #{bucket_name} special message")
|
54
54
|
subject.start('special message', &start_block)
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'calls logger.info with end message' do
|
58
|
-
|
58
|
+
Monitor.any_instance.stub(:logger).and_return(logger)
|
59
59
|
logger.should_receive(:info).with("End: #{bucket_name} special message")
|
60
60
|
subject.start('special message', &start_block)
|
61
61
|
end
|
@@ -75,7 +75,7 @@ module Babysitter
|
|
75
75
|
end
|
76
76
|
|
77
77
|
it 'calls logger.info with each done message once' do
|
78
|
-
|
78
|
+
Counter.any_instance.stub(:logger).and_return(logger)
|
79
79
|
[5,10].each { |inc| logger.should_receive(:info).with( "Done: incrementing by #{inc} things").once }
|
80
80
|
subject.start('short message', 5, &start_block_two_increments)
|
81
81
|
end
|
@@ -95,7 +95,7 @@ module Babysitter
|
|
95
95
|
end
|
96
96
|
|
97
97
|
it 'calls logger.info with each done message once' do
|
98
|
-
|
98
|
+
Counter.any_instance.stub(:logger).and_return(logger)
|
99
99
|
[5,7].each { |inc| logger.should_receive(:info).with( "Done: incrementing by #{inc} things").once }
|
100
100
|
subject.start('short message', 5, &start_block_seven_increments)
|
101
101
|
end
|
@@ -109,12 +109,74 @@ module Babysitter
|
|
109
109
|
end
|
110
110
|
|
111
111
|
it 'calls logger.info with increments 18,27,36,45,54,63' do
|
112
|
-
|
112
|
+
Counter.any_instance.stub(:logger).and_return(logger)
|
113
113
|
[18,27,36,45,54,63].each { |inc| logger.should_receive(:info).with( "Done: incrementing by #{inc} things").once }
|
114
114
|
subject.start('short message', 10, &start_block_three_increments)
|
115
115
|
end
|
116
116
|
end # context 'when logging every 10th call, and the block increments the counter 7 times, each with a count of 9, and identifies counted objects' do
|
117
117
|
|
118
|
+
context "when the block logs a warning" do
|
119
|
+
let(:start_block_with_warning) do
|
120
|
+
Proc.new do |monitor|
|
121
|
+
monitor.warn(:my_warning_bucket, 'my warning message')
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'calls logger.info with the warning message' do
|
126
|
+
Progress.any_instance.stub(:logger).and_return(logger)
|
127
|
+
logger.should_receive(:warn).with( "my warning message")
|
128
|
+
Stats.stub!(:increment)
|
129
|
+
subject.start(&start_block_with_warning)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'calls Stats.count with warning bucket name' do
|
133
|
+
expected_bucket_name = bucket_name.split('.') + [:my_warning_bucket, :warnings]
|
134
|
+
Stats.should_receive(:increment).with(expected_bucket_name)
|
135
|
+
subject.start(&start_block_with_warning)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context "when the block logs an error" do
|
140
|
+
let(:start_block_with_error) do
|
141
|
+
Proc.new do |monitor|
|
142
|
+
monitor.error(:my_error_bucket, 'my error message')
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'calls logger.error with the error message' do
|
147
|
+
Progress.any_instance.stub(:logger).and_return(logger)
|
148
|
+
logger.should_receive(:error).with( "my error message")
|
149
|
+
Stats.stub!(:increment)
|
150
|
+
subject.start(&start_block_with_error)
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'calls Stats.count with error bucket name' do
|
154
|
+
expected_bucket_name = bucket_name.split('.') + [:my_error_bucket, :errors]
|
155
|
+
Stats.should_receive(:increment).with(expected_bucket_name)
|
156
|
+
subject.start(&start_block_with_error)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'when the block increments 2 times at intervals of 2 seconds' do
|
161
|
+
let(:start_block_for_timing) do
|
162
|
+
Proc.new do |counter|
|
163
|
+
2.times do
|
164
|
+
Timecop.travel(Time.now+2) # move on 2 seconds
|
165
|
+
counter.inc('doing increment',1)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
before(:each) { Timecop.travel(Time.now) }
|
170
|
+
after(:each) { Timecop.return }
|
171
|
+
|
172
|
+
it 'calculates a rate close to 0.5 per second' do
|
173
|
+
Counter.any_instance.should_receive(:send_rate_stats) do |rate|
|
174
|
+
rate.should be_within(0.01).of(0.5)
|
175
|
+
end
|
176
|
+
subject.start(&start_block_for_timing)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
118
180
|
end
|
119
181
|
|
120
182
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Babysitter do
|
4
|
+
|
5
|
+
describe '.monitor' do
|
6
|
+
it 'returns an instance of Monitor' do
|
7
|
+
Babysitter.monitor.should be_an_instance_of(Babysitter::Monitor)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.configuration' do
|
12
|
+
it 'returns an instance of Configuration' do
|
13
|
+
Babysitter.configuration.should be_an_instance_of(Babysitter::Configuration)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns the same instance every time' do
|
17
|
+
c = Babysitter.configuration
|
18
|
+
Babysitter.configuration.should eql(c)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.configure' do
|
23
|
+
describe 'object yielded to block' do
|
24
|
+
it 'is the unique configuration object' do
|
25
|
+
Babysitter.configure do |c|
|
26
|
+
c.should eql(Babysitter.configuration)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '.logger' do
|
33
|
+
let(:configured_logger) { double('configured logger').as_null_object }
|
34
|
+
|
35
|
+
it 'returns the logger from the configuration' do
|
36
|
+
Babysitter::Configuration.any_instance.stub(:logger).and_return(configured_logger)
|
37
|
+
Babysitter.logger.should eql(configured_logger)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: babysitter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-01-
|
14
|
+
date: 2013-01-23 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: fozzie
|
@@ -29,6 +29,22 @@ dependencies:
|
|
29
29
|
- - ! '>='
|
30
30
|
- !ruby/object:Gem::Version
|
31
31
|
version: '0'
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: timecop
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
32
48
|
- !ruby/object:Gem::Dependency
|
33
49
|
name: awesome_print
|
34
50
|
requirement: !ruby/object:Gem::Requirement
|
@@ -78,13 +94,15 @@ files:
|
|
78
94
|
- babysitter.gemspec
|
79
95
|
- lib/babysitter.rb
|
80
96
|
- lib/babysitter/configuration.rb
|
97
|
+
- lib/babysitter/counter.rb
|
81
98
|
- lib/babysitter/logging.rb
|
99
|
+
- lib/babysitter/monitor.rb
|
82
100
|
- lib/babysitter/null_logger.rb
|
83
101
|
- lib/babysitter/progress.rb
|
84
|
-
- lib/babysitter/progress_counter.rb
|
85
102
|
- lib/babysitter/version.rb
|
86
103
|
- spec/lib/babysitter/configuration_spec.rb
|
87
|
-
- spec/lib/babysitter/
|
104
|
+
- spec/lib/babysitter/monitor_spec.rb
|
105
|
+
- spec/lib/babysitter_spec.rb
|
88
106
|
- spec/spec_helper.rb
|
89
107
|
homepage: ''
|
90
108
|
licenses: []
|
@@ -106,11 +124,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
124
|
version: '0'
|
107
125
|
requirements: []
|
108
126
|
rubyforge_project:
|
109
|
-
rubygems_version: 1.8.
|
127
|
+
rubygems_version: 1.8.22
|
110
128
|
signing_key:
|
111
129
|
specification_version: 3
|
112
130
|
summary: Babysits long-running processes and reports progress or failures
|
113
131
|
test_files:
|
114
132
|
- spec/lib/babysitter/configuration_spec.rb
|
115
|
-
- spec/lib/babysitter/
|
133
|
+
- spec/lib/babysitter/monitor_spec.rb
|
134
|
+
- spec/lib/babysitter_spec.rb
|
116
135
|
- spec/spec_helper.rb
|