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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91574e1eabbcadaf02cc6fe5e70e3031e7022b33
|
4
|
+
data.tar.gz: da4ab6eb49ee18c42665a627abc08df7529e4972
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49c09665f4349ada057861bb8d9f02dbd2a473ea33ad4fc0843613d03429228fc707b1dae3fb5a5c092d7a9725c5b9e6d4a55a17698a99cf98dc9573c7e2c36a
|
7
|
+
data.tar.gz: 0b80737bf8f199ff2be3daa6e41746438ee55033d23926c106f9228fdad43a58476bcf4020c4eb41206a564a84197c9a6660e38a2639f2821b94a35aa0565736
|
data/.travis.yml
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
+
- 2.0.0
|
3
4
|
- 1.9.3
|
4
5
|
- jruby-19mode
|
5
6
|
- rbx-19mode
|
6
|
-
- 2.0.0
|
7
7
|
notifications:
|
8
8
|
email:
|
9
9
|
recipients:
|
10
10
|
- tp@tiredpixel.com
|
11
|
-
- sidekiq.spy@librelist.com
|
12
11
|
matrix:
|
13
12
|
allow_failures:
|
14
|
-
- rvm: 1.9.3
|
15
13
|
- rvm: jruby-19mode
|
16
14
|
- rvm: rbx-19mode
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Sidekiq Spy Changelog
|
2
|
+
|
3
|
+
This changelog documents the main changes between released versions.
|
4
|
+
For a full list of changes, consult the commit history.
|
5
|
+
For many of commits by [tiredpixel](http://www.tiredpixel.com), the commit
|
6
|
+
message provides information and examples.
|
7
|
+
|
8
|
+
|
9
|
+
## 0.1.0
|
10
|
+
|
11
|
+
- first release
|
12
|
+
- `sidekiq-spy` executable providing: `--url`, `--host`, `--port`, `--database`,
|
13
|
+
`--namespace`, `--interval`, `--help`, `--version`
|
14
|
+
- core Redis statistics: redis, namespace, redis version, uptime (d),
|
15
|
+
connections, memory, memory peak
|
16
|
+
- core Sidekiq statistics: busy, retries, processed, enqueued, scheduled, failed
|
17
|
+
|
18
|
+
|
19
|
+
## 0.2.0
|
20
|
+
|
21
|
+
- test fixes for Ruby 1.9.3, which is supported along with Ruby 2.0.0
|
22
|
+
- a plethora of tests; most of the core is now covered
|
23
|
+
- command-loop to handle key presses
|
24
|
+
- `<q>` for quit (in addition to existing `<ctrl>+<c>`)
|
25
|
+
- smaller sleep increments for faster exit
|
26
|
+
- content overrun fix
|
27
|
+
- workers panel (like `Sidekiq::Web` Workers tab), reporting who is up to what
|
data/README.md
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# Sidekiq Spy
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/sidekiq-spy.png)](http://badge.fury.io/rb/sidekiq-spy)
|
4
|
-
[![Build Status](https://travis-ci.org/tiredpixel/sidekiq-spy.png?branch=master,
|
4
|
+
[![Build Status](https://travis-ci.org/tiredpixel/sidekiq-spy.png?branch=master,stable)](https://travis-ci.org/tiredpixel/sidekiq-spy)
|
5
5
|
[![Code Climate](https://codeclimate.com/github/tiredpixel/sidekiq-spy.png)](https://codeclimate.com/github/tiredpixel/sidekiq-spy)
|
6
|
-
[![Coverage Status](https://coveralls.io/repos/tiredpixel/sidekiq-spy/badge.png?branch=master,develop)](https://coveralls.io/r/tiredpixel/sidekiq-spy)
|
7
6
|
|
8
7
|
[Sidekiq](https://github.com/mperham/sidekiq) monitoring in the console.
|
9
8
|
A bit like Sidekiq::Web. But without the web.
|
@@ -13,8 +12,9 @@ see how your workers are doing at-a-glance when SSHed into a remote box with
|
|
13
12
|
no web server, this one's for you. <3
|
14
13
|
|
15
14
|
This project is so hot out of the oven you might need mitts. But it's already
|
16
|
-
functional, with the main statistics from the Sidekiq::Web homepage
|
17
|
-
it would be nice to add the
|
15
|
+
functional, with the main statistics from the Sidekiq::Web homepage and the
|
16
|
+
Workers tab. In time, it would be nice to add the Queues, Retries, and
|
17
|
+
Scheduled tabs, too.
|
18
18
|
|
19
19
|
More sleep lost by [tiredpixel](http://www.tiredpixel.com).
|
20
20
|
|
@@ -50,18 +50,25 @@ We won't tell anyone! ;) (Resque is awesome, too!)
|
|
50
50
|
|
51
51
|
$ sidekiq-spy -n resque
|
52
52
|
|
53
|
-
That's about it.
|
53
|
+
To quit, press `<q>` or `<ctrl>+<c>`. That's about it.
|
54
54
|
|
55
55
|
|
56
56
|
## ASCII Art (a.k.a. Screenshot)
|
57
57
|
|
58
|
-
Sidekiq Spy 0.0
|
58
|
+
Sidekiq Spy 0.2.0 16:17:23 +0000
|
59
59
|
redis: 127.0.0.1:6379/0|namespace:
|
60
|
-
redis version: 2.6.11|uptime (d):
|
61
|
-
memory: 4.
|
60
|
+
redis version: 2.6.11|uptime (d): 2|connections: 5
|
61
|
+
memory: 4.89M|memory peak: 5.03M|
|
62
62
|
|
63
|
-
busy:
|
64
|
-
enqueued: 0|scheduled: 0|failed:
|
63
|
+
busy: 5|retries: 15|processed: 1623
|
64
|
+
enqueued: 0|scheduled: 0|failed: 1535
|
65
|
+
|
66
|
+
WORKER QUEUE CLASS ARGUMENTS STARTED
|
67
|
+
sep.da.local:17045-70130396 default MakeSEPFields [2670] 2013-11-03
|
68
|
+
sep.da.local:17045-70130397 default MakeSEPFields [2668] 2013-11-03
|
69
|
+
sep.da.local:17045-70130396 default MakeSEPFields [2669] 2013-11-03
|
70
|
+
sep.da.local:17045-70130397 default MakeSEPFields [2667] 2013-11-03
|
71
|
+
sep.da.local:17045-70130396 default MakeSEPFields [2671] 2013-11-03
|
65
72
|
|
66
73
|
|
67
74
|
## Stay Tuned
|
@@ -77,8 +84,6 @@ That was easy.
|
|
77
84
|
|
78
85
|
Dear Me, Here is a vague wishlist:
|
79
86
|
|
80
|
-
- more tests for the display parts
|
81
|
-
- Workers table on main page
|
82
87
|
- Queues page
|
83
88
|
- Retries page
|
84
89
|
- Scheduled page
|
data/lib/sidekiq-spy.rb
CHANGED
@@ -5,7 +5,13 @@ require File.expand_path('../sidekiq-spy/translatable', __FILE__)
|
|
5
5
|
require File.expand_path('../sidekiq-spy/app', __FILE__)
|
6
6
|
|
7
7
|
require File.expand_path('../sidekiq-spy/spy/stats', __FILE__)
|
8
|
+
require File.expand_path('../sidekiq-spy/spy/workers', __FILE__)
|
8
9
|
|
9
10
|
require File.expand_path('../sidekiq-spy/display/screen', __FILE__)
|
10
11
|
require File.expand_path('../sidekiq-spy/display/panel', __FILE__)
|
11
12
|
require File.expand_path('../sidekiq-spy/display/subpanel', __FILE__)
|
13
|
+
|
14
|
+
require File.expand_path('../sidekiq-spy/display/panels/header', __FILE__)
|
15
|
+
require File.expand_path('../sidekiq-spy/display/panels/redis_stats', __FILE__)
|
16
|
+
require File.expand_path('../sidekiq-spy/display/panels/sidekiq_stats', __FILE__)
|
17
|
+
require File.expand_path('../sidekiq-spy/display/panels/workers', __FILE__)
|
data/lib/sidekiq-spy/app.rb
CHANGED
@@ -1,13 +1,17 @@
|
|
1
|
+
require 'thread'
|
1
2
|
require 'sidekiq'
|
2
3
|
|
3
4
|
|
4
5
|
module SidekiqSpy
|
5
6
|
class App
|
6
7
|
|
8
|
+
REFRESH_SUBINTERVAL = 0.1
|
9
|
+
|
7
10
|
attr_reader :running
|
8
11
|
|
9
12
|
def initialize
|
10
|
-
@running
|
13
|
+
@running = false
|
14
|
+
@threads = {}
|
11
15
|
end
|
12
16
|
|
13
17
|
def config
|
@@ -26,17 +30,15 @@ module SidekiqSpy
|
|
26
30
|
|
27
31
|
setup
|
28
32
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
sleep 1
|
36
|
-
|
37
|
-
@sleep_timer -= 1
|
38
|
-
end
|
33
|
+
@threads[:command] ||= Thread.new do
|
34
|
+
command_loop # listen for commands
|
35
|
+
end
|
36
|
+
|
37
|
+
@threads[:refresh] ||= Thread.new do
|
38
|
+
refresh_loop # refresh frequently
|
39
39
|
end
|
40
|
+
|
41
|
+
@threads.each { |tname, t| t.join }
|
40
42
|
ensure
|
41
43
|
cleanup
|
42
44
|
end
|
@@ -46,6 +48,13 @@ module SidekiqSpy
|
|
46
48
|
@running = false
|
47
49
|
end
|
48
50
|
|
51
|
+
def do_command(key)
|
52
|
+
case key
|
53
|
+
when 'q' # quit
|
54
|
+
@running = false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
49
58
|
private
|
50
59
|
|
51
60
|
def configure_sidekiq
|
@@ -58,12 +67,40 @@ module SidekiqSpy
|
|
58
67
|
end
|
59
68
|
end
|
60
69
|
|
70
|
+
def command_loop
|
71
|
+
while @running do
|
72
|
+
key = next_key
|
73
|
+
|
74
|
+
next unless key # keep listening if timeout
|
75
|
+
|
76
|
+
do_command(key)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def refresh_loop
|
81
|
+
while @running do
|
82
|
+
refresh
|
83
|
+
|
84
|
+
@sleep_timer = config.interval
|
85
|
+
|
86
|
+
while @running && @sleep_timer > 0
|
87
|
+
sleep REFRESH_SUBINTERVAL
|
88
|
+
|
89
|
+
@sleep_timer -= REFRESH_SUBINTERVAL
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
61
94
|
def setup
|
62
95
|
@screen = Display::Screen.new
|
63
96
|
end
|
64
97
|
|
65
98
|
def refresh
|
66
|
-
@screen.refresh
|
99
|
+
@screen.refresh if @screen
|
100
|
+
end
|
101
|
+
|
102
|
+
def next_key
|
103
|
+
@screen.next_key if @screen
|
67
104
|
end
|
68
105
|
|
69
106
|
def cleanup
|
@@ -5,7 +5,16 @@ module SidekiqSpy
|
|
5
5
|
module Display
|
6
6
|
class Panel
|
7
7
|
|
8
|
-
|
8
|
+
include Translatable
|
9
|
+
|
10
|
+
attr_reader :height
|
11
|
+
attr_reader :width
|
12
|
+
attr_reader :top
|
13
|
+
attr_reader :left
|
14
|
+
attr_reader :dividers
|
15
|
+
attr_reader :divider_length
|
16
|
+
|
17
|
+
def initialize(height, width, top, left, structure = [], opts = {})
|
9
18
|
@height = height
|
10
19
|
@width = width
|
11
20
|
@top = top
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module SidekiqSpy
|
2
|
+
module Display
|
3
|
+
module Panels
|
4
|
+
class Header < Display::Panel
|
5
|
+
|
6
|
+
def initialize(height, width, top, left)
|
7
|
+
super(height, width, top, left, structure)
|
8
|
+
end
|
9
|
+
|
10
|
+
def structure
|
11
|
+
# [
|
12
|
+
# [relative_column_width, data_left, data_right]
|
13
|
+
# ]
|
14
|
+
[
|
15
|
+
[
|
16
|
+
[1, t[:program], nil],
|
17
|
+
[1, nil, -> { Time.now.strftime("%T %z") }],
|
18
|
+
],
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module SidekiqSpy
|
2
|
+
module Display
|
3
|
+
module Panels
|
4
|
+
class RedisStats < Display::Panel
|
5
|
+
|
6
|
+
def initialize(height, width, top, left)
|
7
|
+
super(height, width, top, left, structure, :divider_r => "|")
|
8
|
+
end
|
9
|
+
|
10
|
+
def structure
|
11
|
+
stats = Spy::Stats.new
|
12
|
+
|
13
|
+
# [
|
14
|
+
# [relative_column_width, data_left, data_right]
|
15
|
+
# ]
|
16
|
+
[
|
17
|
+
[
|
18
|
+
[2, t[:redis][:connection], -> { stats.connection }],
|
19
|
+
[1, t[:redis][:namespace], -> { stats.namespace }],
|
20
|
+
],
|
21
|
+
[
|
22
|
+
[1, t[:redis][:version], -> { stats.redis_version }],
|
23
|
+
[1, t[:redis][:uptime], -> { stats.uptime }],
|
24
|
+
[1, t[:redis][:connections], -> { stats.connections }],
|
25
|
+
],
|
26
|
+
[
|
27
|
+
[1, t[:redis][:memory], -> { stats.memory }],
|
28
|
+
[1, t[:redis][:memory_peak], -> { stats.memory_peak }],
|
29
|
+
[1, nil, nil],
|
30
|
+
],
|
31
|
+
]
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module SidekiqSpy
|
2
|
+
module Display
|
3
|
+
module Panels
|
4
|
+
class SidekiqStats < Display::Panel
|
5
|
+
|
6
|
+
def initialize(height, width, top, left)
|
7
|
+
super(height, width, top, left, structure, :divider_r => "|")
|
8
|
+
end
|
9
|
+
|
10
|
+
def structure
|
11
|
+
stats = Spy::Stats.new
|
12
|
+
|
13
|
+
# [
|
14
|
+
# [relative_column_width, data_left, data_right]
|
15
|
+
# ]
|
16
|
+
[
|
17
|
+
[
|
18
|
+
[1, t[:sidekiq][:busy], -> { stats.busy }],
|
19
|
+
[1, t[:sidekiq][:retries], -> { stats.retries }],
|
20
|
+
[1, t[:sidekiq][:processed], -> { stats.processed }],
|
21
|
+
],
|
22
|
+
[
|
23
|
+
[1, t[:sidekiq][:enqueued], -> { stats.enqueued }],
|
24
|
+
[1, t[:sidekiq][:scheduled], -> { stats.scheduled }],
|
25
|
+
[1, t[:sidekiq][:failed], -> { stats.failed }],
|
26
|
+
],
|
27
|
+
]
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module SidekiqSpy
|
2
|
+
module Display
|
3
|
+
module Panels
|
4
|
+
class Workers < Display::Panel
|
5
|
+
|
6
|
+
def initialize(height, width, top, left)
|
7
|
+
@height = height # #structure needs this before #initialize ends
|
8
|
+
|
9
|
+
super(height, width, top, left, structure, :divider_r => " ")
|
10
|
+
end
|
11
|
+
|
12
|
+
def refresh
|
13
|
+
@workers.refresh # refresh data feed
|
14
|
+
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def structure
|
19
|
+
@workers = Spy::Workers.new
|
20
|
+
|
21
|
+
# [
|
22
|
+
# [relative_column_width, data_left, data_right]
|
23
|
+
# ]
|
24
|
+
s = [
|
25
|
+
[ # table header slots
|
26
|
+
[2, t[:heading][:worker], nil],
|
27
|
+
[1, t[:heading][:queue], nil],
|
28
|
+
[1, t[:heading][:class], nil],
|
29
|
+
[1, t[:heading][:args], nil],
|
30
|
+
[1, nil, t[:heading][:started_at]],
|
31
|
+
],
|
32
|
+
]
|
33
|
+
|
34
|
+
(0...(@height - 1)).each do |i|
|
35
|
+
s << [ # table row slots
|
36
|
+
[2, -> { @workers.data.values[i][:name] rescue nil }, nil],
|
37
|
+
[1, -> { @workers.data.values[i][:queue] rescue nil }, nil],
|
38
|
+
[1, -> { @workers.data.values[i][:class] rescue nil }, nil],
|
39
|
+
[1, -> { @workers.data.values[i][:args] rescue nil }, nil],
|
40
|
+
[1, nil, -> { @workers.data.values[i][:started_at] rescue nil }],
|
41
|
+
]
|
42
|
+
end
|
43
|
+
|
44
|
+
s
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -5,19 +5,26 @@ module SidekiqSpy
|
|
5
5
|
module Display
|
6
6
|
class Screen
|
7
7
|
|
8
|
-
|
8
|
+
CURSES_GETCH_TIMEOUT = 100
|
9
|
+
|
10
|
+
attr_reader :height
|
11
|
+
attr_reader :width
|
9
12
|
|
10
13
|
def initialize
|
11
14
|
Curses.init_screen
|
12
15
|
Curses.nl
|
13
16
|
Curses.noecho
|
14
17
|
Curses.curs_set(0)
|
18
|
+
Curses.timeout = CURSES_GETCH_TIMEOUT
|
15
19
|
|
16
20
|
@height = Curses.lines
|
17
21
|
@width = Curses.cols
|
18
22
|
|
19
|
-
@panels = {
|
20
|
-
:header
|
23
|
+
@panels = { # attach panels, defining height, width, top, left
|
24
|
+
:header => Display::Panels::Header.new( 1, @width, 0, 0),
|
25
|
+
:redis_stats => Display::Panels::RedisStats.new( 3, @width, 1, 0),
|
26
|
+
:sidekiq_stats => Display::Panels::SidekiqStats.new(2, @width, 5, 0),
|
27
|
+
:workers => Display::Panels::Workers.new( (@height - 8), @width, 8, 0),
|
21
28
|
}
|
22
29
|
end
|
23
30
|
|
@@ -31,50 +38,8 @@ module SidekiqSpy
|
|
31
38
|
@panels.each { |pname, panel| panel.refresh }
|
32
39
|
end
|
33
40
|
|
34
|
-
|
35
|
-
|
36
|
-
def panel_header
|
37
|
-
stats = Spy::Stats.new
|
38
|
-
|
39
|
-
structure = [
|
40
|
-
[
|
41
|
-
[1, t[:program], nil],
|
42
|
-
[1, nil, -> { Time.now.strftime("%T %z") }],
|
43
|
-
],
|
44
|
-
[
|
45
|
-
[2, t[:redis][:connection], -> { stats.connection }],
|
46
|
-
[1, t[:redis][:namespace], -> { stats.namespace }],
|
47
|
-
],
|
48
|
-
[
|
49
|
-
[1, t[:redis][:version], -> { stats.redis_version }],
|
50
|
-
[1, t[:redis][:uptime], -> { stats.uptime }],
|
51
|
-
[1, t[:redis][:connections], -> { stats.connections }],
|
52
|
-
],
|
53
|
-
[
|
54
|
-
[1, t[:redis][:memory], -> { stats.memory }],
|
55
|
-
[1, t[:redis][:memory_peak], -> { stats.memory_peak }],
|
56
|
-
[1, nil, nil],
|
57
|
-
],
|
58
|
-
nil,
|
59
|
-
[
|
60
|
-
[1, t[:sidekiq][:busy], -> { stats.busy }],
|
61
|
-
[1, t[:sidekiq][:retries], -> { stats.retries }],
|
62
|
-
[1, t[:sidekiq][:processed], -> { stats.processed }],
|
63
|
-
],
|
64
|
-
[
|
65
|
-
[1, t[:sidekiq][:enqueued], -> { stats.enqueued }],
|
66
|
-
[1, t[:sidekiq][:scheduled], -> { stats.scheduled }],
|
67
|
-
[1, t[:sidekiq][:failed], -> { stats.failed }],
|
68
|
-
],
|
69
|
-
nil,
|
70
|
-
]
|
71
|
-
|
72
|
-
opts = {
|
73
|
-
:divider_l => t[:divider][:left],
|
74
|
-
:divider_r => t[:divider][:right],
|
75
|
-
}
|
76
|
-
|
77
|
-
Display::Panel.new(structure.length, @width, 0, 0, structure, opts)
|
41
|
+
def next_key
|
42
|
+
Curses.getch
|
78
43
|
end
|
79
44
|
|
80
45
|
end
|