sidekiq-spy 0.1.0 → 0.2.0
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.
- 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
@@ -2,6 +2,14 @@ module SidekiqSpy
|
|
2
2
|
module Display
|
3
3
|
class Subpanel
|
4
4
|
|
5
|
+
attr_reader :height
|
6
|
+
attr_reader :width
|
7
|
+
attr_reader :top
|
8
|
+
attr_reader :left
|
9
|
+
attr_reader :data
|
10
|
+
attr_reader :dividers
|
11
|
+
attr_reader :content_width
|
12
|
+
|
5
13
|
def initialize(window, height, width, top, left, opts = {})
|
6
14
|
@window = window
|
7
15
|
@height = height
|
@@ -10,13 +18,13 @@ module SidekiqSpy
|
|
10
18
|
@left = left
|
11
19
|
|
12
20
|
@data = {
|
13
|
-
:left => opts[:data_l],
|
14
|
-
:right => opts[:data_r],
|
21
|
+
:left => opts[:data_l] || '',
|
22
|
+
:right => opts[:data_r] || '',
|
15
23
|
}
|
16
24
|
|
17
25
|
@dividers = {
|
18
|
-
:left => opts[:divider_l]
|
19
|
-
:right => opts[:divider_r]
|
26
|
+
:left => opts[:divider_l] || '',
|
27
|
+
:right => opts[:divider_r] || '',
|
20
28
|
}
|
21
29
|
|
22
30
|
@content_width = @width - @dividers.values.map(&:length).inject(:+)
|
@@ -36,10 +44,10 @@ module SidekiqSpy
|
|
36
44
|
private
|
37
45
|
|
38
46
|
def content(data_l, data_r, width)
|
39
|
-
l = data_l.is_a?(Proc) ? data_l.call : data_l
|
40
|
-
r = data_r.is_a?(Proc) ? data_r.call : data_r
|
47
|
+
l = data_l.is_a?(Proc) ? data_l.call : data_l
|
48
|
+
r = data_r.is_a?(Proc) ? data_r.call : data_r
|
41
49
|
|
42
|
-
l
|
50
|
+
("#{l}%#{width - (l ? l.length : 0)}s" % r)[0...width]
|
43
51
|
end
|
44
52
|
|
45
53
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'sidekiq'
|
3
|
+
|
4
|
+
|
5
|
+
module SidekiqSpy
|
6
|
+
module Spy
|
7
|
+
class Workers
|
8
|
+
|
9
|
+
attr_reader :data
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@workers = Sidekiq::Workers.new
|
13
|
+
|
14
|
+
refresh
|
15
|
+
end
|
16
|
+
|
17
|
+
def refresh
|
18
|
+
h = {}
|
19
|
+
|
20
|
+
@workers.each do |worker, msg|
|
21
|
+
h[worker] = {
|
22
|
+
:name => worker,
|
23
|
+
:queue => msg['queue'],
|
24
|
+
:class => msg['payload']['class'],
|
25
|
+
:args => msg['payload']['args'],
|
26
|
+
:started_at => (msg['run_at'].is_a?(Numeric) ? Time.at(msg['run_at']) : Time.parse(msg['run_at'])),
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
@data = h
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -3,10 +3,6 @@ module SidekiqSpy
|
|
3
3
|
|
4
4
|
def t
|
5
5
|
{
|
6
|
-
divider: {
|
7
|
-
left: "",
|
8
|
-
right: "|",
|
9
|
-
},
|
10
6
|
program: "Sidekiq Spy #{VERSION}",
|
11
7
|
redis: {
|
12
8
|
connection: "redis:",
|
@@ -25,6 +21,13 @@ module SidekiqSpy
|
|
25
21
|
scheduled: "scheduled:",
|
26
22
|
failed: "failed:",
|
27
23
|
},
|
24
|
+
heading: {
|
25
|
+
worker: "WORKER",
|
26
|
+
queue: "QUEUE",
|
27
|
+
class: "CLASS",
|
28
|
+
args: "ARGUMENTS",
|
29
|
+
started_at: "STARTED",
|
30
|
+
}
|
28
31
|
}
|
29
32
|
end
|
30
33
|
|
data/lib/sidekiq-spy/version.rb
CHANGED
data/sidekiq-spy.gemspec
CHANGED
data/test/helper.rb
CHANGED
@@ -3,9 +3,24 @@ require File.expand_path('../../helper', __FILE__)
|
|
3
3
|
require File.expand_path('../../../lib/sidekiq-spy', __FILE__)
|
4
4
|
|
5
5
|
|
6
|
+
def start_and_stop_app(app)
|
7
|
+
app_thread = Thread.new { app.start }
|
8
|
+
|
9
|
+
sleep 1 # patience, patience; give app time to start
|
10
|
+
|
11
|
+
app.stop
|
12
|
+
|
13
|
+
app_thread.join(2)
|
14
|
+
|
15
|
+
Thread.kill(app_thread)
|
16
|
+
end
|
17
|
+
|
18
|
+
|
6
19
|
describe SidekiqSpy::App do
|
7
20
|
|
8
21
|
before do
|
22
|
+
SidekiqSpy::Display::Screen.stubs(:new)
|
23
|
+
|
9
24
|
@app = SidekiqSpy::App.new
|
10
25
|
end
|
11
26
|
|
@@ -13,6 +28,101 @@ describe SidekiqSpy::App do
|
|
13
28
|
@app.running.must_equal false
|
14
29
|
end
|
15
30
|
|
31
|
+
describe "#configure" do
|
32
|
+
it "configures Sidekiq" do
|
33
|
+
Sidekiq.expects(:configure_client)
|
34
|
+
|
35
|
+
@app.configure { }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "configure block main" do
|
40
|
+
before do
|
41
|
+
@app.configure do |c|
|
42
|
+
c.namespace = 'resque'
|
43
|
+
c.interval = 1
|
44
|
+
end
|
45
|
+
|
46
|
+
@config = @app.config
|
47
|
+
end
|
48
|
+
|
49
|
+
it "configures namespace" do
|
50
|
+
@config.namespace.must_equal 'resque'
|
51
|
+
end
|
52
|
+
|
53
|
+
it "configures interval" do
|
54
|
+
@config.interval.must_equal 1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "configure block url" do
|
59
|
+
before do
|
60
|
+
@app.configure do |c|
|
61
|
+
c.url = 'redis://da.example.com:237/42'
|
62
|
+
end
|
63
|
+
|
64
|
+
@config = @app.config
|
65
|
+
end
|
66
|
+
|
67
|
+
it "configures host" do
|
68
|
+
@config.host.must_equal 'da.example.com'
|
69
|
+
end
|
70
|
+
|
71
|
+
it "configures port" do
|
72
|
+
@config.port.must_equal 237
|
73
|
+
end
|
74
|
+
|
75
|
+
it "configures database" do
|
76
|
+
@config.database.must_equal 42
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "configure block url-brief" do
|
81
|
+
before do
|
82
|
+
@app.configure do |c|
|
83
|
+
c.url = 'redis://da.example.com'
|
84
|
+
end
|
85
|
+
|
86
|
+
@config = @app.config
|
87
|
+
end
|
88
|
+
|
89
|
+
it "configures host" do
|
90
|
+
@config.host.must_equal 'da.example.com'
|
91
|
+
end
|
92
|
+
|
93
|
+
it "configures port" do
|
94
|
+
@config.port.must_equal 6379
|
95
|
+
end
|
96
|
+
|
97
|
+
it "configures database" do
|
98
|
+
@config.database.must_equal 0
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "configure block non-url" do
|
103
|
+
before do
|
104
|
+
@app.configure do |c|
|
105
|
+
c.host = 'da.example.com'
|
106
|
+
c.port = 237
|
107
|
+
c.database = 42
|
108
|
+
end
|
109
|
+
|
110
|
+
@config = @app.config
|
111
|
+
end
|
112
|
+
|
113
|
+
it "configures host" do
|
114
|
+
@config.host.must_equal 'da.example.com'
|
115
|
+
end
|
116
|
+
|
117
|
+
it "configures port" do
|
118
|
+
@config.port.must_equal 237
|
119
|
+
end
|
120
|
+
|
121
|
+
it "configures database" do
|
122
|
+
@config.database.must_equal 42
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
16
126
|
describe "#start" do
|
17
127
|
before do
|
18
128
|
@app.configure do |c|
|
@@ -30,18 +140,42 @@ describe SidekiqSpy::App do
|
|
30
140
|
Thread.kill(thread_app)
|
31
141
|
end
|
32
142
|
|
33
|
-
it "stops running within
|
143
|
+
it "stops running within 1s" do
|
34
144
|
thread_app = Thread.new { @app.start }
|
35
145
|
|
36
146
|
sleep 1 # patience, patience; give app time to start
|
37
147
|
|
38
148
|
@app.stop; t0 = Time.now
|
39
149
|
|
40
|
-
thread_app.join(
|
150
|
+
thread_app.join(2)
|
41
151
|
|
42
152
|
Thread.kill(thread_app)
|
43
153
|
|
44
|
-
assert_operator (Time.now - t0), :<=,
|
154
|
+
assert_operator (Time.now - t0), :<=, 1
|
155
|
+
end
|
156
|
+
|
157
|
+
it "calls #setup hook" do
|
158
|
+
@app.expects(:setup)
|
159
|
+
|
160
|
+
start_and_stop_app(@app)
|
161
|
+
end
|
162
|
+
|
163
|
+
it "calls #refresh hook" do
|
164
|
+
@app.expects(:refresh)
|
165
|
+
|
166
|
+
start_and_stop_app(@app)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "calls #next_key hook" do
|
170
|
+
@app.expects(:next_key).at_least_once
|
171
|
+
|
172
|
+
start_and_stop_app(@app)
|
173
|
+
end
|
174
|
+
|
175
|
+
it "calls #cleanup hook" do
|
176
|
+
@app.expects(:cleanup)
|
177
|
+
|
178
|
+
start_and_stop_app(@app)
|
45
179
|
end
|
46
180
|
end
|
47
181
|
|
@@ -57,4 +191,16 @@ describe SidekiqSpy::App do
|
|
57
191
|
end
|
58
192
|
end
|
59
193
|
|
194
|
+
describe "#do_command" do
|
195
|
+
before do
|
196
|
+
@app.instance_variable_set(:@running, true)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "<q> sets status not-running" do
|
200
|
+
@app.do_command('q')
|
201
|
+
|
202
|
+
@app.running.must_equal false
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
60
206
|
end
|
@@ -1,15 +1,10 @@
|
|
1
1
|
require File.expand_path('../../helper', __FILE__)
|
2
2
|
|
3
3
|
require File.expand_path('../../../lib/sidekiq-spy/config', __FILE__)
|
4
|
-
require File.expand_path('../../../lib/sidekiq-spy/app', __FILE__)
|
5
4
|
|
6
5
|
|
7
6
|
describe SidekiqSpy::Config do
|
8
7
|
|
9
|
-
before do
|
10
|
-
@app = SidekiqSpy::App.new
|
11
|
-
end
|
12
|
-
|
13
8
|
describe "default" do
|
14
9
|
before do
|
15
10
|
@config = SidekiqSpy::Config.new
|
@@ -36,93 +31,6 @@ describe SidekiqSpy::Config do
|
|
36
31
|
end
|
37
32
|
end
|
38
33
|
|
39
|
-
describe "configure block main" do
|
40
|
-
before do
|
41
|
-
@app.configure do |c|
|
42
|
-
c.namespace = 'resque'
|
43
|
-
c.interval = 1
|
44
|
-
end
|
45
|
-
|
46
|
-
@config = @app.config
|
47
|
-
end
|
48
|
-
|
49
|
-
it "configures namespace" do
|
50
|
-
@config.namespace.must_equal 'resque'
|
51
|
-
end
|
52
|
-
|
53
|
-
it "configures interval" do
|
54
|
-
@config.interval.must_equal 1
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe "configure block url" do
|
59
|
-
before do
|
60
|
-
@app.configure do |c|
|
61
|
-
c.url = 'redis://da.example.com:237/42'
|
62
|
-
end
|
63
|
-
|
64
|
-
@config = @app.config
|
65
|
-
end
|
66
|
-
|
67
|
-
it "configures host" do
|
68
|
-
@config.host.must_equal 'da.example.com'
|
69
|
-
end
|
70
|
-
|
71
|
-
it "configures port" do
|
72
|
-
@config.port.must_equal 237
|
73
|
-
end
|
74
|
-
|
75
|
-
it "configures database" do
|
76
|
-
@config.database.must_equal 42
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
describe "configure block url-brief" do
|
81
|
-
before do
|
82
|
-
@app.configure do |c|
|
83
|
-
c.url = 'redis://da.example.com'
|
84
|
-
end
|
85
|
-
|
86
|
-
@config = @app.config
|
87
|
-
end
|
88
|
-
|
89
|
-
it "configures host" do
|
90
|
-
@config.host.must_equal 'da.example.com'
|
91
|
-
end
|
92
|
-
|
93
|
-
it "configures port" do
|
94
|
-
@config.port.must_equal 6379
|
95
|
-
end
|
96
|
-
|
97
|
-
it "configures database" do
|
98
|
-
@config.database.must_equal 0
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
describe "configure block non-url" do
|
103
|
-
before do
|
104
|
-
@app.configure do |c|
|
105
|
-
c.host = 'da.example.com'
|
106
|
-
c.port = 237
|
107
|
-
c.database = 42
|
108
|
-
end
|
109
|
-
|
110
|
-
@config = @app.config
|
111
|
-
end
|
112
|
-
|
113
|
-
it "configures host" do
|
114
|
-
@config.host.must_equal 'da.example.com'
|
115
|
-
end
|
116
|
-
|
117
|
-
it "configures port" do
|
118
|
-
@config.port.must_equal 237
|
119
|
-
end
|
120
|
-
|
121
|
-
it "configures database" do
|
122
|
-
@config.database.must_equal 42
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
34
|
describe "#url" do
|
127
35
|
before do
|
128
36
|
@config = SidekiqSpy::Config.new
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require File.expand_path('../../../helper', __FILE__)
|
2
|
+
|
3
|
+
require File.expand_path('../../../../lib/sidekiq-spy/display/panel', __FILE__)
|
4
|
+
|
5
|
+
|
6
|
+
describe SidekiqSpy::Display::Panel do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@window = stub
|
10
|
+
|
11
|
+
Curses::Window.stubs(:new).returns(@window)
|
12
|
+
|
13
|
+
@panel = SidekiqSpy::Display::Panel.new(24, 80, 1, 2)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#initialize" do
|
17
|
+
describe "required" do
|
18
|
+
it "sets height" do
|
19
|
+
@panel.height.must_equal 24
|
20
|
+
end
|
21
|
+
|
22
|
+
it "sets width" do
|
23
|
+
@panel.width.must_equal 80
|
24
|
+
end
|
25
|
+
|
26
|
+
it "sets top" do
|
27
|
+
@panel.top.must_equal 1
|
28
|
+
end
|
29
|
+
|
30
|
+
it "sets left" do
|
31
|
+
@panel.left.must_equal 2
|
32
|
+
end
|
33
|
+
|
34
|
+
it "defaults dividers" do
|
35
|
+
@panel.dividers.must_equal({
|
36
|
+
:left => '',
|
37
|
+
:right => '',
|
38
|
+
})
|
39
|
+
end
|
40
|
+
|
41
|
+
it "calculates divider_length" do
|
42
|
+
@panel.divider_length.must_equal 0
|
43
|
+
end
|
44
|
+
|
45
|
+
it "sets up window with dimensions" do
|
46
|
+
Curses::Window.expects(:new).with(24, 80, 1, 2)
|
47
|
+
|
48
|
+
SidekiqSpy::Display::Panel.new(24, 80, 1, 2)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "sets window" do
|
52
|
+
@panel.instance_variable_get(:@window).must_equal @window
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "optional" do
|
57
|
+
before do
|
58
|
+
@structure = [
|
59
|
+
[
|
60
|
+
[1, "busy:", -> { 1 + 3 }], # S(0,0)
|
61
|
+
[1, "retries:", 2], # S(0,1)
|
62
|
+
],
|
63
|
+
[
|
64
|
+
[2, -> { 2 * 7 }, "long"], # S(1,0)
|
65
|
+
[1, -> { "1" + "4" }, -> { "dark" }], # S(1,1)
|
66
|
+
],
|
67
|
+
]
|
68
|
+
|
69
|
+
@panel = SidekiqSpy::Display::Panel.new(24, 80, 1, 2, @structure,
|
70
|
+
:divider_l => '<',
|
71
|
+
:divider_r => '>'
|
72
|
+
)
|
73
|
+
|
74
|
+
@subpanels = @panel.instance_variable_get(:@subpanels)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "sets dividers" do
|
78
|
+
@panel.dividers.must_equal({
|
79
|
+
:left => '<',
|
80
|
+
:right => '>',
|
81
|
+
})
|
82
|
+
end
|
83
|
+
|
84
|
+
it "calculates divider_length" do
|
85
|
+
@panel.divider_length.must_equal 2
|
86
|
+
end
|
87
|
+
|
88
|
+
it "builds enough subpanels" do
|
89
|
+
@subpanels.length.must_equal 4
|
90
|
+
end
|
91
|
+
|
92
|
+
it "builds S(0,0)" do
|
93
|
+
@subpanels.count { |e|
|
94
|
+
e.height == 1 && e.width == 42 && e.top == 0 && e.left == 0 &&
|
95
|
+
e.data[:left] == "busy:" && e.data[:right].call == 4 &&
|
96
|
+
e.dividers[:left] == '' && e.dividers[:right] == '>' &&
|
97
|
+
e.content_width == 41
|
98
|
+
}.must_equal 1
|
99
|
+
end
|
100
|
+
|
101
|
+
it "builds S(0,1)" do
|
102
|
+
@subpanels.count { |e|
|
103
|
+
e.height == 1 && e.width == 38 && e.top == 0 && e.left == 42 &&
|
104
|
+
e.data[:left] == "retries:" && e.data[:right] == 2 &&
|
105
|
+
e.dividers[:left] == '<' && e.dividers[:right] == '' &&
|
106
|
+
e.content_width == 37
|
107
|
+
}.must_equal 1
|
108
|
+
end
|
109
|
+
|
110
|
+
it "builds S(1,0)" do
|
111
|
+
@subpanels.count { |e|
|
112
|
+
e.height == 1 && e.width == 56 && e.top == 1 && e.left == 0 &&
|
113
|
+
e.data[:left].call == 14 && e.data[:right] == "long" &&
|
114
|
+
e.dividers[:left] == '' && e.dividers[:right] == '>' &&
|
115
|
+
e.content_width == 55
|
116
|
+
}.must_equal 1
|
117
|
+
end
|
118
|
+
|
119
|
+
it "builds S(1,1)" do
|
120
|
+
@subpanels.count { |e|
|
121
|
+
e.height == 1 && e.width == 24 && e.top == 1 && e.left == 56 &&
|
122
|
+
e.data[:left].call == "14" && e.data[:right].call == "dark" &&
|
123
|
+
e.dividers[:left] == '<' && e.dividers[:right] == '' &&
|
124
|
+
e.content_width == 23
|
125
|
+
}.must_equal 1
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "#close" do
|
131
|
+
it "closes window" do
|
132
|
+
@window.expects(:close)
|
133
|
+
|
134
|
+
@panel.close
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#refresh" do
|
139
|
+
it "refreshes subpanels" do
|
140
|
+
@window.stubs(:refresh)
|
141
|
+
|
142
|
+
@subpanel2 = stub
|
143
|
+
@subpanel2.expects(:refresh)
|
144
|
+
|
145
|
+
@panel.instance_variable_set(:@subpanels, [@subpanel2])
|
146
|
+
|
147
|
+
@panel.refresh
|
148
|
+
end
|
149
|
+
|
150
|
+
it "refreshes window" do
|
151
|
+
@subpanel2 = stub(:refresh => nil)
|
152
|
+
|
153
|
+
@panel.instance_variable_set(:@subpanels, [@subpanel2])
|
154
|
+
|
155
|
+
@window.expects(:refresh)
|
156
|
+
|
157
|
+
@panel.refresh
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|