sidekiq-spy 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -3
- data/CHANGELOG.md +27 -0
- data/README.md +17 -12
- data/lib/sidekiq-spy.rb +6 -0
- data/lib/sidekiq-spy/app.rb +49 -12
- data/lib/sidekiq-spy/display/panel.rb +10 -1
- data/lib/sidekiq-spy/display/panels/header.rb +25 -0
- data/lib/sidekiq-spy/display/panels/redis_stats.rb +37 -0
- data/lib/sidekiq-spy/display/panels/sidekiq_stats.rb +33 -0
- data/lib/sidekiq-spy/display/panels/workers.rb +50 -0
- data/lib/sidekiq-spy/display/screen.rb +12 -47
- data/lib/sidekiq-spy/display/subpanel.rb +15 -7
- data/lib/sidekiq-spy/spy/stats.rb +1 -1
- data/lib/sidekiq-spy/spy/workers.rb +35 -0
- data/lib/sidekiq-spy/translatable.rb +7 -4
- data/lib/sidekiq-spy/version.rb +1 -1
- data/sidekiq-spy.gemspec +1 -2
- data/test/helper.rb +1 -5
- data/test/sidekiq-spy/app_test.rb +149 -3
- data/test/sidekiq-spy/config_test.rb +0 -92
- data/test/sidekiq-spy/display/panel_test.rb +161 -0
- data/test/sidekiq-spy/display/screen_test.rb +98 -0
- data/test/sidekiq-spy/display/subpanel_test.rb +186 -0
- data/test/sidekiq-spy/spy/stats_test.rb +23 -36
- data/test/sidekiq-spy/spy/workers_test.rb +81 -0
- data/test/sidekiq-spy/translatable_test.rb +18 -0
- metadata +24 -8
@@ -0,0 +1,98 @@
|
|
1
|
+
require File.expand_path('../../../helper', __FILE__)
|
2
|
+
|
3
|
+
require File.expand_path('../../../../lib/sidekiq-spy/display/screen', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
module SidekiqSpy
|
7
|
+
module Display
|
8
|
+
module Panels
|
9
|
+
class Header; end
|
10
|
+
class RedisStats; end
|
11
|
+
class SidekiqStats; end
|
12
|
+
class Workers; end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
describe SidekiqSpy::Display::Screen do
|
19
|
+
|
20
|
+
before do
|
21
|
+
Object.send(:remove_const, :Curses) if Object.constants.include?(:Curses)
|
22
|
+
|
23
|
+
Curses = stub(
|
24
|
+
:init_screen => nil,
|
25
|
+
:close_screen => nil,
|
26
|
+
:nl => nil,
|
27
|
+
:noecho => nil,
|
28
|
+
:curs_set => nil,
|
29
|
+
:timeout= => nil,
|
30
|
+
:lines => 24,
|
31
|
+
:cols => 80
|
32
|
+
)
|
33
|
+
|
34
|
+
@panel = stub(
|
35
|
+
:close => nil
|
36
|
+
)
|
37
|
+
|
38
|
+
SidekiqSpy::Display::Panels::Header.stubs(:new).returns(@panel)
|
39
|
+
SidekiqSpy::Display::Panels::RedisStats.stubs(:new).returns(@panel)
|
40
|
+
SidekiqSpy::Display::Panels::SidekiqStats.stubs(:new).returns(@panel)
|
41
|
+
SidekiqSpy::Display::Panels::Workers.stubs(:new).returns(@panel)
|
42
|
+
|
43
|
+
@screen = SidekiqSpy::Display::Screen.new
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#initialize" do
|
47
|
+
it "inits screen" do
|
48
|
+
Curses.expects(:init_screen)
|
49
|
+
|
50
|
+
SidekiqSpy::Display::Screen.new
|
51
|
+
end
|
52
|
+
|
53
|
+
it "sets height" do
|
54
|
+
@screen.height.must_equal 24
|
55
|
+
end
|
56
|
+
|
57
|
+
it "sets width" do
|
58
|
+
@screen.width.must_equal 80
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#close" do
|
63
|
+
it "closes screen" do
|
64
|
+
Curses.expects(:close_screen)
|
65
|
+
|
66
|
+
@screen.close
|
67
|
+
end
|
68
|
+
|
69
|
+
it "closes panels" do
|
70
|
+
@panel2 = stub
|
71
|
+
@panel2.expects(:close)
|
72
|
+
|
73
|
+
@screen.instance_variable_set(:@panels, { :panel2 => @panel2 })
|
74
|
+
|
75
|
+
@screen.close
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#refresh" do
|
80
|
+
it "refreshes panels" do
|
81
|
+
@panel2 = stub
|
82
|
+
@panel2.expects(:refresh)
|
83
|
+
|
84
|
+
@screen.instance_variable_set(:@panels, { :panel2 => @panel2 })
|
85
|
+
|
86
|
+
@screen.refresh
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#next_key" do
|
91
|
+
it "gets next key" do
|
92
|
+
Curses.expects(:getch)
|
93
|
+
|
94
|
+
@screen.next_key
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require File.expand_path('../../../helper', __FILE__)
|
2
|
+
|
3
|
+
require File.expand_path('../../../../lib/sidekiq-spy/display/subpanel', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
describe SidekiqSpy::Display::Subpanel do
|
7
|
+
|
8
|
+
describe "#initialize" do
|
9
|
+
describe "required" do
|
10
|
+
before do
|
11
|
+
@window = stub
|
12
|
+
|
13
|
+
@subpanel = SidekiqSpy::Display::Subpanel.new(@window, 24, 80, 1, 2)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "sets window" do
|
17
|
+
@subpanel.instance_variable_get(:@window).must_equal @window
|
18
|
+
end
|
19
|
+
|
20
|
+
it "sets height" do
|
21
|
+
@subpanel.height.must_equal 24
|
22
|
+
end
|
23
|
+
|
24
|
+
it "sets width" do
|
25
|
+
@subpanel.width.must_equal 80
|
26
|
+
end
|
27
|
+
|
28
|
+
it "sets top" do
|
29
|
+
@subpanel.top.must_equal 1
|
30
|
+
end
|
31
|
+
|
32
|
+
it "sets left" do
|
33
|
+
@subpanel.left.must_equal 2
|
34
|
+
end
|
35
|
+
|
36
|
+
it "defaults data" do
|
37
|
+
@subpanel.data.must_equal({
|
38
|
+
:left => '',
|
39
|
+
:right => '',
|
40
|
+
})
|
41
|
+
end
|
42
|
+
|
43
|
+
it "defaults dividers" do
|
44
|
+
@subpanel.dividers.must_equal({
|
45
|
+
:left => '',
|
46
|
+
:right => '',
|
47
|
+
})
|
48
|
+
end
|
49
|
+
|
50
|
+
it "calculates content_width" do
|
51
|
+
@subpanel.content_width.must_equal 80
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "optional" do
|
56
|
+
before do
|
57
|
+
@subpanel = SidekiqSpy::Display::Subpanel.new(stub, 24, 80, 1, 2, {
|
58
|
+
:data_l => 'key:',
|
59
|
+
:data_r => 'value',
|
60
|
+
:divider_l => '<',
|
61
|
+
:divider_r => '/>',
|
62
|
+
})
|
63
|
+
end
|
64
|
+
|
65
|
+
it "sets data" do
|
66
|
+
@subpanel.data.must_equal({
|
67
|
+
:left => 'key:',
|
68
|
+
:right => 'value',
|
69
|
+
})
|
70
|
+
end
|
71
|
+
|
72
|
+
it "sets dividers" do
|
73
|
+
@subpanel.dividers.must_equal({
|
74
|
+
:left => '<',
|
75
|
+
:right => '/>',
|
76
|
+
})
|
77
|
+
end
|
78
|
+
|
79
|
+
it "calculates content_width" do
|
80
|
+
@subpanel.content_width.must_equal 77
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#refresh" do
|
86
|
+
describe "strings and dividers" do
|
87
|
+
before do
|
88
|
+
@window = stub
|
89
|
+
|
90
|
+
@subpanel = SidekiqSpy::Display::Subpanel.new(@window, 24, 80, 1, 2, {
|
91
|
+
:data_l => 'key:',
|
92
|
+
:data_r => 'value',
|
93
|
+
:divider_l => '<-',
|
94
|
+
:divider_r => '|',
|
95
|
+
})
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "when changed" do
|
99
|
+
it "sets position" do
|
100
|
+
@window.stubs(:addstr)
|
101
|
+
|
102
|
+
@window.expects(:setpos).with(1, 2)
|
103
|
+
|
104
|
+
@subpanel.refresh
|
105
|
+
end
|
106
|
+
|
107
|
+
it "sets data" do
|
108
|
+
@window.stubs(:setpos)
|
109
|
+
|
110
|
+
@window.expects(:addstr).with("<-key: value|")
|
111
|
+
|
112
|
+
@subpanel.refresh
|
113
|
+
end
|
114
|
+
|
115
|
+
it "sets truncated data when too long" do
|
116
|
+
@subpanel = SidekiqSpy::Display::Subpanel.new(@window, 24, 10, 1, 2, {
|
117
|
+
:data_l => 'key:',
|
118
|
+
:data_r => 'value',
|
119
|
+
:divider_l => '<-',
|
120
|
+
:divider_r => '|',
|
121
|
+
})
|
122
|
+
|
123
|
+
@window.stubs(:setpos)
|
124
|
+
|
125
|
+
@window.expects(:addstr).with("<-key:val|")
|
126
|
+
|
127
|
+
@subpanel.refresh
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "when unchanged" do
|
132
|
+
before do
|
133
|
+
@window.stubs(:setpos)
|
134
|
+
@window.stubs(:addstr)
|
135
|
+
|
136
|
+
@subpanel.refresh
|
137
|
+
end
|
138
|
+
|
139
|
+
it "skips position" do
|
140
|
+
@window.expects(:setpos).never
|
141
|
+
|
142
|
+
@subpanel.refresh
|
143
|
+
end
|
144
|
+
|
145
|
+
it "skips data" do
|
146
|
+
@window.expects(:addstr).never
|
147
|
+
|
148
|
+
@subpanel.refresh
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "lambdas" do
|
154
|
+
before do
|
155
|
+
@window = stub
|
156
|
+
|
157
|
+
@subpanel = SidekiqSpy::Display::Subpanel.new(@window, 24, 80, 0, 0, {
|
158
|
+
:data_l => -> { "the answer:" },
|
159
|
+
:data_r => -> { 2 * 3 * 7 }
|
160
|
+
})
|
161
|
+
end
|
162
|
+
|
163
|
+
it "sets data when changed" do
|
164
|
+
@window.stubs(:setpos)
|
165
|
+
|
166
|
+
@window.expects(:addstr).with("the answer: 42")
|
167
|
+
|
168
|
+
@subpanel.refresh
|
169
|
+
end
|
170
|
+
|
171
|
+
it "sets empty data when nil" do
|
172
|
+
@subpanel = SidekiqSpy::Display::Subpanel.new(@window, 24, 10, 0, 0, {
|
173
|
+
:data_l => -> { nil },
|
174
|
+
:data_r => -> { nil }
|
175
|
+
})
|
176
|
+
|
177
|
+
@window.stubs(:setpos)
|
178
|
+
|
179
|
+
@window.expects(:addstr).with(" ")
|
180
|
+
|
181
|
+
@subpanel.refresh
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
@@ -11,40 +11,35 @@ describe SidekiqSpy::Spy::Stats do
|
|
11
11
|
before do
|
12
12
|
@redis = Redis::Namespace.new('resque', :redis => Redis.new)
|
13
13
|
|
14
|
+
@redis.stubs(:info).returns(JSON.parse(File.read(
|
15
|
+
File.expand_path('../../../fixtures/redis_info.json', __FILE__)
|
16
|
+
)))
|
17
|
+
|
18
|
+
@redis.client.stubs(:location).returns('da.example.com:237')
|
19
|
+
@redis.client.stubs(:db).returns(42)
|
20
|
+
|
14
21
|
Sidekiq.configure_client do |config|
|
15
22
|
config.redis = ConnectionPool.new(:size => 1, &proc { @redis })
|
16
23
|
end
|
17
24
|
|
18
|
-
|
19
|
-
:
|
20
|
-
|
21
|
-
|
22
|
-
|
25
|
+
Sidekiq::Stats.stubs(:new).returns(stub(
|
26
|
+
:enqueued => 16776977673,
|
27
|
+
:retry_size => 924984826746,
|
28
|
+
:scheduled_size => 317321542620,
|
29
|
+
:processed => 923531545885,
|
30
|
+
:failed => 779187529140
|
31
|
+
))
|
23
32
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@sidekiq_stats.expect(:scheduled_size, 317321542620)
|
28
|
-
@sidekiq_stats.expect(:processed, 923531545885)
|
29
|
-
@sidekiq_stats.expect(:failed, 779187529140)
|
33
|
+
Sidekiq::Workers.stubs(:new).returns(stub(
|
34
|
+
:size => 162165179294
|
35
|
+
))
|
30
36
|
|
31
|
-
@
|
32
|
-
@sidekiq_workers.expect(:size, 162165179294)
|
33
|
-
|
34
|
-
Sidekiq::Stats.stub(:new, @sidekiq_stats) do
|
35
|
-
Sidekiq::Workers.stub(:new, @sidekiq_workers) do
|
36
|
-
@stats = SidekiqSpy::Spy::Stats.new
|
37
|
-
end
|
38
|
-
end
|
37
|
+
@stats = SidekiqSpy::Spy::Stats.new
|
39
38
|
end
|
40
39
|
|
41
40
|
describe "#connection" do
|
42
41
|
it "returns stat connection" do
|
43
|
-
@
|
44
|
-
@redis.client.stub(:db, 42) do
|
45
|
-
@stats.connection.must_equal 'da.example.com:237/42'
|
46
|
-
end
|
47
|
-
end
|
42
|
+
@stats.connection.must_equal 'da.example.com:237/42'
|
48
43
|
end
|
49
44
|
end
|
50
45
|
|
@@ -56,33 +51,25 @@ describe SidekiqSpy::Spy::Stats do
|
|
56
51
|
|
57
52
|
describe "#uptime" do
|
58
53
|
it "returns stat uptime" do
|
59
|
-
@
|
60
|
-
@stats.uptime.must_equal '7'
|
61
|
-
end
|
54
|
+
@stats.uptime.must_equal '7'
|
62
55
|
end
|
63
56
|
end
|
64
57
|
|
65
58
|
describe "#connections" do
|
66
59
|
it "returns stat connections" do
|
67
|
-
@
|
68
|
-
@stats.connections.must_equal '8'
|
69
|
-
end
|
60
|
+
@stats.connections.must_equal '8'
|
70
61
|
end
|
71
62
|
end
|
72
63
|
|
73
64
|
describe "#memory" do
|
74
65
|
it "returns stat memory" do
|
75
|
-
@
|
76
|
-
@stats.memory.must_equal '5.16M'
|
77
|
-
end
|
66
|
+
@stats.memory.must_equal '5.16M'
|
78
67
|
end
|
79
68
|
end
|
80
69
|
|
81
70
|
describe "#memory_peak" do
|
82
71
|
it "returns stat memory_peak" do
|
83
|
-
@
|
84
|
-
@stats.memory_peak.must_equal '5.14M'
|
85
|
-
end
|
72
|
+
@stats.memory_peak.must_equal '5.14M'
|
86
73
|
end
|
87
74
|
end
|
88
75
|
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
|
4
|
+
require File.expand_path('../../../helper', __FILE__)
|
5
|
+
|
6
|
+
require File.expand_path('../../../../lib/sidekiq-spy/spy/workers', __FILE__)
|
7
|
+
|
8
|
+
|
9
|
+
describe SidekiqSpy::Spy::Workers do
|
10
|
+
|
11
|
+
before do
|
12
|
+
@sidekiq_workers_data = {
|
13
|
+
'worker1' => {
|
14
|
+
'queue' => 'Q',
|
15
|
+
'run_at' => 11202710605,
|
16
|
+
'payload' => {
|
17
|
+
'class' => 'Geometry',
|
18
|
+
'args' => ['Euclid', 360],
|
19
|
+
}
|
20
|
+
},
|
21
|
+
}
|
22
|
+
|
23
|
+
@spy_workers_data = {
|
24
|
+
'worker1' => {
|
25
|
+
:name => 'worker1',
|
26
|
+
:queue => 'Q',
|
27
|
+
:class => 'Geometry',
|
28
|
+
:args => ['Euclid', 360],
|
29
|
+
:started_at => Time.parse('2325-01-01 00:03:25 +0000')
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
@sidekiq_workers_data2 = {
|
34
|
+
'worker2' => {
|
35
|
+
'queue' => 'Queueueue',
|
36
|
+
'run_at' => -1316908800,
|
37
|
+
'payload' => {
|
38
|
+
'class' => 'Elements',
|
39
|
+
'args' => ['Lehrer', 102],
|
40
|
+
}
|
41
|
+
},
|
42
|
+
}
|
43
|
+
|
44
|
+
@spy_workers_data2 = {
|
45
|
+
'worker2' => {
|
46
|
+
:name => 'worker2',
|
47
|
+
:queue => 'Queueueue',
|
48
|
+
:class => 'Elements',
|
49
|
+
:args => ['Lehrer', 102],
|
50
|
+
:started_at => Time.parse('1928-04-09 00:00:00 +0000')
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
Sidekiq::Workers.stubs(:new).returns(@sidekiq_workers_data)
|
55
|
+
|
56
|
+
@workers = SidekiqSpy::Spy::Workers.new
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#initialize" do
|
60
|
+
it "sets data list of workers" do
|
61
|
+
@workers.data.must_equal(@spy_workers_data)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#refresh" do
|
66
|
+
it "doesn't refresh if not called" do
|
67
|
+
@sidekiq_workers_data.merge!(@sidekiq_workers_data2)
|
68
|
+
|
69
|
+
@workers.data.must_equal(@spy_workers_data)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "refreshes if called" do
|
73
|
+
@sidekiq_workers_data.merge!(@sidekiq_workers_data2)
|
74
|
+
|
75
|
+
@workers.refresh
|
76
|
+
|
77
|
+
@workers.data.must_equal(@spy_workers_data.merge(@spy_workers_data2))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|