mmtop 0.9.4 → 0.9.5

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.
@@ -1,3 +1,6 @@
1
+ # I'd like to say that I no longer understand this code.
2
+ # Also, I'd like to say that it's unlikely to work for you, the general public. patches welcome!
3
+
1
4
  module MMTop
2
5
  class Topology
3
6
  def initialize(config)
@@ -10,9 +13,10 @@ module MMTop
10
13
 
11
14
  new_top = create_sort_array(topology)
12
15
 
13
- hosts = @config.hosts.sort_by { |h| new_top.find_index { |t| t[:hostname] == h.name } }
16
+ hosts = @config.hosts.sort_by { |h| new_top.find_index { |t| t[:hostname] == h.name } || 1_000_000 }
14
17
  hosts.each { |h|
15
18
  top = new_top.find { |t| t[:hostname] == h.name }
19
+ next unless top
16
20
  if top[:levels] > 0
17
21
  h.display_name = (" " * top[:levels]) + '\_' + h.name
18
22
  end
@@ -70,7 +74,11 @@ module MMTop
70
74
 
71
75
  def find_master_slave
72
76
  topology = @config.hosts.inject({}) { |accum, h|
73
- hostname = h.query("show global variables where Variable_name='hostname'")[0][:Value]
77
+ rows = h.query("show global variables where Variable_name='hostname'")
78
+ next accum if rows.empty?
79
+
80
+ hostname = rows.first[:Value]
81
+
74
82
  hostname = hostname.split('.')[0]
75
83
  status = h.slave_status
76
84
 
@@ -107,9 +115,18 @@ module MMTop
107
115
  end
108
116
 
109
117
  Filter.add_filter("discover_topology") do |queries, hostinfo, config|
110
- if !config.options['discovered']
111
- config.options['discovered'] = true
118
+ if config.options['discover_topology'] && !config.options['topology.discovered']
119
+ config.options['topology.discovered'] = true
112
120
  config.hosts = MMTop::Topology.new(config).new_hostlist
113
- end
121
+ end
122
+ end
123
+
124
+ MMTop::Command.register do |c|
125
+ c.regexp /map_topology/
126
+ c.usage "map_topology"
127
+ c.explain "Re-Map the slave-chain topology"
128
+ c.command do |cmd, config|
129
+ config.options['discovered'] = false
130
+ end
114
131
  end
115
132
  end
@@ -1,3 +1,5 @@
1
+ require 'mmtop/qps'
2
+
1
3
  module MMTop
2
4
  class Host
3
5
  def initialize(hostname, user, password, options)
@@ -8,20 +10,43 @@ module MMTop
8
10
  m2opts[:socket] = options['socket'] if options['socket']
9
11
  m2opts[:port] = options['port'] if options['port']
10
12
  m2opts[:reconnect] = true
11
- @mysql = Mysql2::Client.new(m2opts)
12
- # rescue connection errors or sumpin
13
13
  @options = options
14
14
  @name = hostname
15
15
  @display_name = @name
16
16
  @comment = options['comment']
17
17
  @last_queries = nil
18
+
19
+ begin
20
+ @mysql = Mysql2::Client.new(m2opts)
21
+ rescue Mysql2::Error => e
22
+ if e.error_number == 2003
23
+ mark_dead!
24
+ else
25
+ raise e
26
+ end
27
+ end
28
+
29
+ # rescue connection errors or sumpin
18
30
  end
19
31
 
20
32
  attr_accessor :display_name, :name, :comment, :options
21
33
 
22
34
  def query(q)
35
+ return [] if dead?
36
+
23
37
  res = []
24
- ret = @mysql.query(q)
38
+ begin
39
+ ret = @mysql.query(q)
40
+ rescue Mysql2::Error => e
41
+ if [2007, 2013, 2003].include?(e.error_number)
42
+ mark_dead!
43
+ return []
44
+ else
45
+ puts "Got error number " + e.error_number.to_s
46
+ raise e
47
+ end
48
+ end
49
+
25
50
  return nil unless ret
26
51
  ret.each(:symbolize_keys => true) do |r|
27
52
  res << r
@@ -29,6 +54,14 @@ module MMTop
29
54
  res
30
55
  end
31
56
 
57
+ def mark_dead!
58
+ @dead = true
59
+ end
60
+
61
+ def dead?
62
+ @dead
63
+ end
64
+
32
65
  def slave_status
33
66
  return nil if @options['expect_slave'] == false
34
67
  res = query("show slave status")[0]
@@ -42,20 +75,15 @@ module MMTop
42
75
 
43
76
  def stats
44
77
  stats = {}
45
- queries = query("show global status like 'Questions'")[0][:Value].to_i
46
-
47
- if @last_queries
48
- elapsed = Time.now.to_i - @last_queries[:time]
49
- if elapsed > 0
50
- qps = (queries - @last_queries[:count]) / elapsed
51
- else
52
- qps = queries - @last_queries[:count]
53
- end
54
- stats[:qps] = qps
55
- end
56
- @last_queries = {}
57
- @last_queries[:count] = queries
58
- @last_queries[:time] = Time.now.to_i
78
+ row = query("show global status like 'Questions'")
79
+ return {} if row.empty?
80
+
81
+ queries = row.first[:Value].to_i
82
+
83
+ @qps ||= MMTop::QPS.new
84
+ @qps.add_sample(queries, Time.now)
85
+ stats[:qps] = @qps.calc.to_i
86
+
59
87
  stats
60
88
  end
61
89
 
@@ -18,12 +18,7 @@ module MMTop
18
18
  h['password'] ||= (pass || config['password'])
19
19
  h['wedge_monitor'] ||= config['wedge_monitor']
20
20
 
21
- begin
22
- Host.new(h['host'], h['user'], h['password'], h)
23
- rescue Mysql2::Error => e
24
- puts e
25
- nil
26
- end
21
+ Host.new(h['host'], h['user'], h['password'], h)
27
22
  end.compact
28
23
 
29
24
  @filters = MMTop::Filter.default_filters
@@ -0,0 +1,46 @@
1
+ module MMTop
2
+ class QPS
3
+ DEFAULT_WINDOW = 20
4
+
5
+ QUERIES = 0
6
+ TIME = 1
7
+ def self.window
8
+ @window || DEFAULT_WINDOW
9
+ end
10
+
11
+ def self.window=(window)
12
+ @window = window
13
+ end
14
+
15
+ def window
16
+ self.class.window
17
+ end
18
+
19
+ def add_sample(queries, time)
20
+ samples.push [queries, time]
21
+ clean_samples
22
+ end
23
+
24
+ def calc
25
+ clean_samples
26
+ return '...' if samples.size == 1
27
+
28
+ queries = samples.last[QUERIES] - samples.first[QUERIES]
29
+ time = samples.last[TIME].to_i - samples.first[TIME].to_i
30
+
31
+ queries / time
32
+ end
33
+
34
+ private
35
+
36
+ def clean_samples
37
+ while samples.first[TIME].to_i < (Time.now.to_i - window)
38
+ samples.shift
39
+ end
40
+ end
41
+
42
+ def samples
43
+ @samples ||= []
44
+ end
45
+ end
46
+ end
@@ -133,14 +133,16 @@ module MMTop
133
133
  str = pipe + " " + column_value(0, p.client, ' ', :right)
134
134
  str += info_sep + column_value(1, p.id ? p.id.to_s : '')
135
135
  str += info_sep + column_value(2, format_time(p.time))
136
- str += info_sep
136
+ str += info_sep
137
137
  str += format_process(p, @x - str.size - 1)
138
138
  str += " " * (@x - str.size - 1) + pipe
139
139
  puts str
140
140
  end
141
141
 
142
142
  def print_host(info)
143
- str = pipe + " " + column_value(0, info.host.display_name + " " + (info.host.comment || ""), "-".dark_gray)
143
+ display_name = info.host.display_name
144
+ display_name = (display_name + "!").red if info.host.dead?
145
+ str = pipe + " " + column_value(0, display_name + " " + (info.host.comment || ""), "-".dark_gray)
144
146
  str += sep_fill + column_fill(1) + sep_fill + column_fill(2)
145
147
  str += info_sep + column_value(3, info.connections.size.to_s)
146
148
  str += info_sep + column_value(4, format_slave_status(info.slave_status))
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mmtop
3
3
  version: !ruby/object:Gem::Version
4
- hash: 51
4
+ hash: 49
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 4
10
- version: 0.9.4
9
+ - 5
10
+ version: 0.9.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ben Osheroff
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-18 00:00:00 +00:00
18
+ date: 2012-02-03 00:00:00 +00:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -80,6 +80,7 @@ files:
80
80
  - lib/mmtop/process.rb
81
81
  - lib/mmtop/host.rb
82
82
  - lib/mmtop/term_input.rb
83
+ - lib/mmtop/qps.rb
83
84
  - lib/mmtop/term_printer.rb
84
85
  - lib/mmtop/commands/filters.rb
85
86
  - lib/mmtop/commands/kill.rb