dbtop 0.0.0 → 0.1.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.
- data/.gitignore +1 -0
- data/bin/dbtop +170 -22
- data/dbtop-0.0.0.gem +0 -0
- data/dbtop.gemspec +35 -0
- data/version.txt +1 -1
- metadata +7 -4
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg/*
|
data/bin/dbtop
CHANGED
@@ -11,7 +11,11 @@
|
|
11
11
|
# ------------------------------------------------------------------------------
|
12
12
|
# filename: dbtop.rb
|
13
13
|
# author: alfred.moreno@zumba.com
|
14
|
-
#
|
14
|
+
#
|
15
|
+
# TODO: Add scrolling to the process window.
|
16
|
+
#
|
17
|
+
# TODO: VIM style navigation for the processlist. (5j, 5k) 5up, 5down
|
18
|
+
#
|
15
19
|
# ------------------------------------------------------------------------------
|
16
20
|
require 'curses'
|
17
21
|
require 'terminal-table'
|
@@ -27,15 +31,40 @@ class MysqlTop
|
|
27
31
|
#############################################################################
|
28
32
|
def initialize(options)
|
29
33
|
|
34
|
+
Curses.noecho # Don't echo characters to the screen.
|
35
|
+
|
30
36
|
@user = options[:user] || ENV['MYSQL_USER']
|
31
37
|
@pass = options[:pass] || ENV['MYSQL_PASSWORD']
|
32
38
|
@host = options[:host] || ENV['MYSQL_HOST']
|
33
39
|
@db = options[:db] || ENV['MYSQL_DATABASE']
|
34
40
|
@port = 3306 || ENV['MYSQL_PORT']
|
35
41
|
@interval = options[:interval] || 5
|
42
|
+
|
43
|
+
@page_tracker = {
|
44
|
+
top_row: 4,
|
45
|
+
bottom_row: Curses.lines - 1,
|
46
|
+
current_page: 1,
|
47
|
+
total_pages: 0
|
48
|
+
}
|
49
|
+
|
50
|
+
@process_list = {
|
51
|
+
x: 3,
|
52
|
+
y: 0
|
53
|
+
}
|
54
|
+
|
55
|
+
@current_pos = {
|
56
|
+
x: 0,
|
57
|
+
y: 0
|
58
|
+
}
|
59
|
+
|
60
|
+
@state = 'FREE'
|
61
|
+
@show_sleep = false
|
62
|
+
@freeze_screen = nil
|
63
|
+
|
36
64
|
validate
|
37
65
|
|
38
|
-
tbl = Terminal::Table.new headings: [
|
66
|
+
@tbl = Terminal::Table.new headings: [
|
67
|
+
'PID',
|
39
68
|
'Time',
|
40
69
|
'User',
|
41
70
|
'Host',
|
@@ -48,32 +77,137 @@ class MysqlTop
|
|
48
77
|
Curses.timeout=0
|
49
78
|
loop do
|
50
79
|
|
80
|
+
# Listen for key input..
|
51
81
|
case getch
|
52
82
|
when 'q'
|
53
83
|
exit
|
54
|
-
|
84
|
+
# Line Feed (Code 10)
|
85
|
+
when 10
|
86
|
+
exit
|
87
|
+
when 'S'
|
88
|
+
@show_sleep = !@show_sleep
|
89
|
+
when 'K'
|
90
|
+
@state = "KILL_MODE"
|
91
|
+
@freeze_screen = @tbl.clone unless (@freeze_screen == @tbl) || @tbl.rows.count == 0
|
92
|
+
Curses.setpos(@process_list[:x],0)
|
93
|
+
nav_key = 0
|
94
|
+
while nav_key != 10
|
95
|
+
break if nav_key == 27
|
96
|
+
# Position tracker for navigating the list
|
97
|
+
process_list_nav = {x: 0, y: 0}
|
98
|
+
|
99
|
+
# Draw the frozen process table
|
100
|
+
@freeze_screen.to_s.each_line do |line|
|
101
|
+
|
102
|
+
break if process_list_nav[:x] == Curses.lines - 1
|
103
|
+
Curses.setpos(process_list_nav[:x],process_list_nav[:y])
|
104
|
+
|
105
|
+
# While drawing the frozen table, we check our process_list_nav
|
106
|
+
# position against the position we're controlling via @process_list.
|
107
|
+
#
|
108
|
+
# If the current row we're drawing is the row we've incremented or
|
109
|
+
# decremented to, it's the current selected row -- hilight it!
|
110
|
+
#
|
111
|
+
if process_list_nav[:x] == @process_list[:x]
|
112
|
+
Curses.start_color
|
113
|
+
Curses.init_pair(COLOR_RED,COLOR_RED,COLOR_WHITE)
|
114
|
+
Curses.attron(color_pair(COLOR_RED)|A_UNDERLINE) {
|
115
|
+
Curses.addstr(line)
|
116
|
+
}
|
117
|
+
Curses.attrset(A_NORMAL)
|
118
|
+
else
|
119
|
+
Curses.addstr(line)
|
120
|
+
end
|
121
|
+
|
122
|
+
process_list_nav[:x] += 1
|
123
|
+
end
|
55
124
|
|
56
|
-
|
57
|
-
|
125
|
+
# Poll for key input (j,k) that we'll use to navigate the
|
126
|
+
# list of processes in the DB process table.
|
127
|
+
#
|
128
|
+
nav_key = getch
|
58
129
|
|
59
|
-
|
130
|
+
# Logic should follow the drawn table (i.e. dimensions of
|
131
|
+
# navigable content are: (4 => lines.count-2)
|
132
|
+
#
|
133
|
+
if @process_list[:x] > 3 && nav_key.eql?('k')
|
60
134
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
135
|
+
# Going up!
|
136
|
+
@process_list[:x] -= 1
|
137
|
+
elsif nav_key.eql?('j') && @process_list[:x] < (@freeze_screen.to_s.lines.count-2)
|
138
|
+
|
139
|
+
# Going down!
|
140
|
+
@process_list[:x] += 1
|
141
|
+
end
|
142
|
+
|
143
|
+
Curses.setpos(@process_list[:x],0)
|
144
|
+
end
|
145
|
+
kill_pid = @freeze_screen.rows[@process_list[:x]-3][0]
|
146
|
+
Thread.new {
|
147
|
+
%x[mysql -A -u #@user -p#@pass -h #@host #@db -e "KILL #{kill_pid}"]
|
70
148
|
}
|
71
|
-
|
149
|
+
write(0,0,@freeze_screen.to_s)
|
150
|
+
@state = "FREE"
|
151
|
+
when '?'
|
152
|
+
@state = "HELP"
|
153
|
+
@freeze_screen = @tbl.clone unless (@freeze_screen == @tbl) || @tbl.rows.count == 0
|
154
|
+
|
155
|
+
Curses.clear
|
156
|
+
help_xy = {x: 0, y: 0}
|
157
|
+
Curses.setpos(0,0)
|
158
|
+
Curses.attrset(A_UNDERLINE)
|
159
|
+
Curses.start_color
|
160
|
+
Curses.init_pair(COLOR_GREEN,COLOR_RED,COLOR_BLACK)
|
161
|
+
Curses.attron(color_pair(COLOR_GREEN)|A_UNDERLINE) {
|
162
|
+
Curses.addstr("State\tCommand\t\tDescription\n")
|
163
|
+
}
|
164
|
+
Curses.attrset(A_NORMAL)
|
165
|
+
|
166
|
+
help_cmds = [
|
167
|
+
"\tS\t\tInclude 'Sleep' processes\n",
|
168
|
+
"\tp\t\tPause the process monitor\n",
|
169
|
+
"\tk\t\tEnter kill mode -- navigate to kill a process\n"
|
170
|
+
]
|
171
|
+
help_cmds.each do |help_cmd|
|
172
|
+
help_xy[:x] += 1
|
173
|
+
Curses.addstr(help_cmd)
|
174
|
+
end
|
175
|
+
|
176
|
+
Curses.setpos(Curses.lines-1,0)
|
177
|
+
Curses.addstr("Press any key to continue...")
|
178
|
+
|
179
|
+
while !getch
|
180
|
+
|
181
|
+
end
|
182
|
+
write(0,0,@freeze_screen.to_s)
|
183
|
+
@state = 'FREE'
|
72
184
|
end
|
73
185
|
|
74
|
-
|
75
|
-
|
186
|
+
# Connect to the MySQL DB and retrieve the process list
|
187
|
+
# This will change soon as I add support for other DB's
|
188
|
+
#
|
189
|
+
Thread.new {
|
190
|
+
%x[mysql -A -u #@user -p#@pass -h #@host #@db -e "show processlist"].lines.each_with_index do |line,index|
|
191
|
+
next if line.include?('Sleep') && !@show_sleep || !@state.eql?('FREE') || index == 0
|
192
|
+
|
193
|
+
line = line.split(' ')
|
194
|
+
|
195
|
+
row = {
|
196
|
+
id: line[0],
|
197
|
+
user: line[1],
|
198
|
+
host: line[2],
|
199
|
+
db: line[3],
|
200
|
+
cmd: line[4],
|
201
|
+
time: line[5],
|
202
|
+
state: line[6],
|
203
|
+
info: line[7]
|
204
|
+
}
|
205
|
+
@tbl << [line[0], line[5], line[1], line[2], line[3], line[6], line[4]]
|
206
|
+
end
|
207
|
+
write(0,0,@tbl.to_s) if @tbl.rows.count > 0
|
76
208
|
sleep @interval
|
209
|
+
@tbl.rows = @tbl.rows.clear
|
210
|
+
} unless Thread.list.size > 1 || !@state.eql?('FREE')
|
77
211
|
|
78
212
|
end
|
79
213
|
ensure
|
@@ -95,7 +229,7 @@ class MysqlTop
|
|
95
229
|
|
96
230
|
#############################################################################
|
97
231
|
# Public: Initializes the screen buffer with specified options.
|
98
|
-
#
|
232
|
+
#
|
99
233
|
# Returns: nothing
|
100
234
|
#############################################################################
|
101
235
|
def init_screen
|
@@ -122,13 +256,27 @@ class MysqlTop
|
|
122
256
|
#############################################################################
|
123
257
|
def write(x,y,text)
|
124
258
|
Curses.setpos(x,y)
|
125
|
-
|
259
|
+
text.each_line do |line|
|
260
|
+
break if x == Curses.lines-1
|
261
|
+
Curses.addstr(line)
|
262
|
+
x += 1
|
263
|
+
end
|
126
264
|
for x in 1..Curses.lines
|
127
265
|
Curses.deleteln
|
128
266
|
end
|
129
267
|
Curses.setpos(text.lines.count-1,0)
|
130
|
-
Curses.addstr(text.lines.take(3)[2])
|
131
|
-
Curses.
|
268
|
+
Curses.addstr(text.lines.take(3)[2]) unless text.lines.take(3)[2].nil?
|
269
|
+
Curses.setpos(text.lines.count-1,0)
|
270
|
+
end
|
271
|
+
|
272
|
+
def page(nav,text)
|
273
|
+
if @tbl.rows.count > Curses.lines
|
274
|
+
|
275
|
+
end
|
276
|
+
Curses.setpos(0,0)
|
277
|
+
for x in 0..3
|
278
|
+
Curses.addstr
|
279
|
+
end
|
132
280
|
end
|
133
281
|
|
134
282
|
end
|
data/dbtop-0.0.0.gem
ADDED
Binary file
|
data/dbtop.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{dbtop}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = [%q{Alfred Moreno}]
|
9
|
+
s.date = %q{2012-06-02}
|
10
|
+
s.description = %q{Similar to the Unix 'top' tool, this Ruby gem will provide process
|
11
|
+
monitoring for your MySQL database instance.}
|
12
|
+
s.email = %q{kryptek@kryptek.org}
|
13
|
+
s.executables = [%q{dbtop}]
|
14
|
+
s.extra_rdoc_files = [%q{History.txt}, %q{bin/dbtop}]
|
15
|
+
s.files = [%q{.bnsignore}, %q{.gitignore}, %q{Gemfile}, %q{Gemfile.lock}, %q{History.txt}, %q{README.md}, %q{Rakefile}, %q{bin/dbtop}, %q{dbtop-0.0.0.gem}, %q{dbtop.gemspec}, %q{lib/dbtop.rb}, %q{spec/dbtop_spec.rb}, %q{spec/spec_helper.rb}, %q{test/test_dbtop.rb}, %q{version.txt}]
|
16
|
+
s.homepage = %q{http://github.com/kryptek}
|
17
|
+
s.rdoc_options = [%q{--main}, %q{README.md}]
|
18
|
+
s.require_paths = [%q{lib}]
|
19
|
+
s.rubyforge_project = %q{dbtop}
|
20
|
+
s.rubygems_version = %q{1.8.6}
|
21
|
+
s.summary = %q{Similar to the Unix 'top' tool, this Ruby gem will provide process monitoring for your MySQL database instance.}
|
22
|
+
s.test_files = [%q{test/test_dbtop.rb}]
|
23
|
+
|
24
|
+
if s.respond_to? :specification_version then
|
25
|
+
s.specification_version = 3
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
28
|
+
s.add_development_dependency(%q<bones>, [">= 3.8.0"])
|
29
|
+
else
|
30
|
+
s.add_dependency(%q<bones>, [">= 3.8.0"])
|
31
|
+
end
|
32
|
+
else
|
33
|
+
s.add_dependency(%q<bones>, [">= 3.8.0"])
|
34
|
+
end
|
35
|
+
end
|
data/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.0
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbtop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-02 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bones
|
16
|
-
requirement: &
|
16
|
+
requirement: &70339907623660 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: 3.8.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70339907623660
|
25
25
|
description: ! 'Similar to the Unix ''top'' tool, this Ruby gem will provide process
|
26
26
|
|
27
27
|
monitoring for your MySQL database instance.'
|
@@ -34,12 +34,15 @@ extra_rdoc_files:
|
|
34
34
|
- bin/dbtop
|
35
35
|
files:
|
36
36
|
- .bnsignore
|
37
|
+
- .gitignore
|
37
38
|
- Gemfile
|
38
39
|
- Gemfile.lock
|
39
40
|
- History.txt
|
40
41
|
- README.md
|
41
42
|
- Rakefile
|
42
43
|
- bin/dbtop
|
44
|
+
- dbtop-0.0.0.gem
|
45
|
+
- dbtop.gemspec
|
43
46
|
- lib/dbtop.rb
|
44
47
|
- spec/dbtop_spec.rb
|
45
48
|
- spec/spec_helper.rb
|