dbtop 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/.gitignore +1 -0
  2. data/bin/dbtop +170 -22
  3. data/dbtop-0.0.0.gem +0 -0
  4. data/dbtop.gemspec +35 -0
  5. data/version.txt +1 -1
  6. 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
- # purpose: Process monitor for MySQL Databases; ignores 'Sleep' processes.
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
- end
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
- %x[mysql -A -u #@user -p#@pass -h #@host #@db -e "show processlist"].lines.each do |line|
57
- next if line.include?('Sleep')
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
- line = line.split(' ')
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
- row = {
62
- id: line[0],
63
- user: line[1],
64
- host: line[2],
65
- db: line[3],
66
- cmd: line[4],
67
- time: line[5],
68
- state: line[6],
69
- info: line[7]
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
- tbl << [line[5], line[1], line[2], line[3], line[6], line[4]]
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
- write(0,0,tbl.to_s)
75
- tbl.rows = tbl.rows.clear
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
- Curses.addstr(text)
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.refresh
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.0.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.0.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-05-24 00:00:00.000000000Z
12
+ date: 2012-06-02 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bones
16
- requirement: &70169320893340 !ruby/object:Gem::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: *70169320893340
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