mysql_health 0.5.6 → 0.5.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -65,11 +65,21 @@ module MysqlHealth
65
65
  @options[:check][:slave] = true
66
66
  end
67
67
 
68
+ @options[:check][:database] = nil
69
+ opts.on( '--check:database NAME', 'Ensure that database exists') do |name|
70
+ @options[:check][:database] = name
71
+ end
72
+
68
73
  @options[:check][:allow_overlapping] = false
69
74
  opts.on( '--check:allow-overlapping', "Allow overlapping health checks (default: #{@options[:check][:allow_overlapping]})") do
70
75
  @options[:check][:allow_overlapping] = true
71
76
  end
72
77
 
78
+ @options[:check][:allow_master] = false
79
+ opts.on( '--check:allow-master', "Allow master to act as slave when --check:slave is used (default: #{@options[:check][:allow_master]})") do
80
+ @options[:check][:allow_master] = true
81
+ end
82
+
73
83
  @options[:check][:interval] = '10s'
74
84
  opts.on( '--check:interval INTERVAL', "Check health every INTERVAL (default: #{@options[:check][:interval]})") do |interval|
75
85
  @options[:check][:interval] = interval.to_s
@@ -77,7 +87,7 @@ module MysqlHealth
77
87
 
78
88
  @options[:check][:delay] = '0s'
79
89
  opts.on( '--check:delay DELAY', "Delay health checks for INTERVAL (default: #{@options[:check][:delay]})") do |delay|
80
- @options[:check][:delay] = interval.to_s
90
+ @options[:check][:delay] = delay.to_s
81
91
  end
82
92
 
83
93
  @options[:check][:dsn] ||= "DBI:Mysql:mysql:localhost"
@@ -92,13 +102,13 @@ module MysqlHealth
92
102
 
93
103
  @options[:check][:password] ||= ""
94
104
  opts.on( '--check:password PASSWORD', "MySQL Password (default: #{@options[:check][:password]})") do |password|
95
- @options[:check][:password] = interval.to_s
105
+ @options[:check][:password] = password.to_s
96
106
  end
97
107
 
98
108
  # Server
99
109
  @options[:server][:listen] = '0.0.0.0'
100
110
  opts.on( '-l', '--server:listen ADDR', "Server listen address (default: #{@options[:server][:listen]})") do |addr|
101
- @options[:server][:addr] = host.to_s
111
+ @options[:server][:addr] = addr.to_s
102
112
  end
103
113
 
104
114
  @options[:server][:port] = 3305
@@ -71,7 +71,7 @@ module MysqlHealth
71
71
 
72
72
  def master_status=(response)
73
73
  @mutex.synchronize do
74
- MysqlHealth.log.info("master status: #{response[:status]}")
74
+ MysqlHealth.log.info("master status: #{response[:status]} (#{response[:content].split(/\n/)[0]})")
75
75
  @master_status = response
76
76
  end
77
77
  end
@@ -86,7 +86,7 @@ module MysqlHealth
86
86
 
87
87
  def slave_status=(response)
88
88
  @mutex.synchronize do
89
- MysqlHealth.log.info("slave status: #{response[:status]}")
89
+ MysqlHealth.log.info("slave status: #{response[:status]} (#{response[:content].split(/\n/)[0]})")
90
90
  @slave_status = response
91
91
  end
92
92
  end
@@ -104,6 +104,10 @@ module MysqlHealth
104
104
  return (variables.length == 1)
105
105
  end
106
106
 
107
+ def master?(dbh)
108
+ read_only?(dbh) == false
109
+ end
110
+
107
111
  def check_master
108
112
  MysqlHealth.log.debug("check_master")
109
113
  response = {}
@@ -113,23 +117,25 @@ module MysqlHealth
113
117
  # connect to the MySQL server
114
118
  dbh = DBI.connect(@options[:dsn], @options[:username], @options[:password])
115
119
 
116
- status = {}
117
- dbh.select_all('SHOW STATUS') do |row|
118
- status[row[0].downcase.to_sym] = row[1]
120
+ # Validate that database exists
121
+ unless @options[:database].nil?
122
+ unless database?(dbh, @options[:database])
123
+ raise Exception.new("Database schema named #{@options[:database]} does not exist")
124
+ end
119
125
  end
120
- mysqladmin_status = "Uptime: %s Threads: %s Questions: %s Slow queries: %s Opens: %s Flush tables: %s Open tables: %s Queries per second avg: %.3f\n" %
121
- [ status[:uptime], status[:threads_running], status[:questions], status[:slow_queries], status[:opened_tables], status[:flush_commands], status[:open_tables], status[:queries].to_i/status[:uptime].to_i]
126
+
127
+ status = show_status(dbh)
122
128
  if status.length > 0
123
129
  if read_only?(dbh)
124
130
  response[:status] = '503 Service Read Only'
125
- response[:content] = mysqladmin_status
131
+ response[:content] = describe_status(status)
126
132
  else
127
133
  response[:status] = '200 OK'
128
- response[:content] = mysqladmin_status
134
+ response[:content] = describe_status(status)
129
135
  end
130
136
  else
131
137
  response[:status] = '503 Service Unavailable'
132
- response[:content] = mysqladmin_status
138
+ response[:content] = describe_status(status)
133
139
  end
134
140
  rescue Exception => e
135
141
  response[:status] = '500 Server Error'
@@ -138,6 +144,46 @@ module MysqlHealth
138
144
  self.master_status=(response)
139
145
  end
140
146
 
147
+ def describe_status(status)
148
+ # Mimick "mysqladmin status"
149
+ "Uptime: %s Threads: %s Questions: %s Slow queries: %s Opens: %s Flush tables: %s Open tables: %s Queries per second avg: %.3f\n" %
150
+ [ status[:uptime], status[:threads_running], status[:questions], status[:slow_queries], status[:opened_tables], status[:flush_commands], status[:open_tables], status[:queries].to_i/status[:uptime].to_i]
151
+ end
152
+
153
+ # Return a hash of status information
154
+ def show_status(dbh, type = nil)
155
+ status = {}
156
+ if type.nil?
157
+ # Format of "SHOW STATUS" differs from "SHOW [MASTER|SLAVE] STATUS"
158
+ dbh.select_all('SHOW STATUS') do |row|
159
+ status[row[0].downcase.to_sym] = row[1]
160
+ end
161
+ else
162
+ dbh.execute('SHOW %s STATUS' % type.to_s.upcase) do |sth|
163
+ sth.fetch_hash() do |row|
164
+ row.each_pair do |k,v|
165
+ status[k.downcase.to_sym] = v
166
+ end
167
+ end
168
+ end
169
+ end
170
+ status
171
+ end
172
+
173
+ def show_create_database(dbh, name)
174
+ schema = nil
175
+ dbh.execute('SHOW CREATE DATABASE %s' % name) do |sth|
176
+ sth.fetch() do |row|
177
+ schema = row[1]
178
+ end
179
+ end
180
+ return schema
181
+ end
182
+
183
+ def database?(dbh, name)
184
+ show_create_database(dbh, name).nil? == false
185
+ end
186
+
141
187
  def check_slave
142
188
  MysqlHealth.log.debug("check_slave")
143
189
  response = {}
@@ -147,41 +193,42 @@ module MysqlHealth
147
193
  # connect to the MySQL server
148
194
  dbh = DBI.connect(@options[:dsn], @options[:username], @options[:password])
149
195
 
150
- show_slave_status = []
151
- status = {}
152
- dbh.execute('SHOW SLAVE STATUS') do |sth|
153
- sth.fetch_hash() do |row|
154
- row.each_pair do |k,v|
155
- status[k.downcase.to_sym] = v
156
- show_slave_status << "#{k}: #{v}"
157
- end
196
+ # Validate that database exists
197
+ unless @options[:database].nil?
198
+ unless database?(dbh, @options[:database])
199
+ raise Exception.new("Database schema named #{@options[:database]} does not exist")
158
200
  end
159
201
  end
160
202
 
161
- if status.length > 0
162
- seconds_behind_master = status[:seconds_behind_master]
203
+ show_slave_status = show_status(dbh, :slave)
204
+ if show_slave_status.length > 0
205
+ seconds_behind_master = show_slave_status[:seconds_behind_master]
163
206
 
164
207
  # We return a "203 Non-Authoritative Information" when replication is shot. We don't want to reduce site performance, but still want to track that something is awry.
165
208
  if seconds_behind_master.eql?('NULL')
166
209
  response[:status] = '203 Slave Stopped'
167
- response[:content] = status.to_json
210
+ response[:content] = show_slave_status.to_json
168
211
  response[:content_type] = 'application/json'
169
212
  elsif seconds_behind_master.to_i > 60*30
170
213
  response[:status] = '203 Slave Behind'
171
- response[:content] = status.to_json
214
+ response[:content] = show_slave_status.to_json
172
215
  response[:content_type] = 'application/json'
173
216
  elsif read_only?(dbh)
174
217
  response[:status] = '200 OK ' + seconds_behind_master + ' Seconds Behind Master'
175
- response[:content] = status.to_json
218
+ response[:content] = show_slave_status.to_json
176
219
  response[:content_type] = 'application/json'
177
220
  else
178
221
  response[:status] = '503 Service Unavailable'
179
- response[:content] = status.to_json
222
+ response[:content] = show_slave_status.to_json
180
223
  response[:content_type] = 'application/json'
181
224
  end
225
+ elsif @options[:allow_master] && master?(dbh)
226
+ response[:status] = '200 OK Master Running'
227
+ response[:content] = describe_status show_status(dbh)
228
+ response[:content_type] = 'application/json'
182
229
  else
183
230
  response[:status] = '503 Slave Not Configured'
184
- response[:content] = show_slave_status.join("\n")
231
+ response[:content] = show_slave_status.to_json
185
232
  end
186
233
  rescue Exception => e
187
234
  response[:status] = '500 Server Error'
@@ -18,5 +18,5 @@
18
18
  # along with mysql_health. If not, see <http://www.gnu.org/licenses/>.
19
19
  #
20
20
  module MysqlHealth
21
- VERSION = "0.5.6"
21
+ VERSION = "0.5.7"
22
22
  end
@@ -1,7 +1,7 @@
1
1
  %define ruby_sitelib %(ruby -rrbconfig -e "puts Config::CONFIG['sitelibdir']")
2
2
  %define gemdir %(ruby -rubygems -e 'puts Gem::dir' 2>/dev/null)
3
3
  %define gemname mysql_health
4
- %define gemversion 0.5.6
4
+ %define gemversion 0.5.7
5
5
  %define geminstdir %{gemdir}/gems/%{gemname}-%{gemversion}
6
6
  %define gemfile %{gemname}-%{gemversion}.gem
7
7
  %define gemsummary %(ruby -rrubygems -e 'puts YAML.load(`gem specification %{gemfile}`).summary')
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 5
8
- - 6
9
- version: 0.5.6
8
+ - 7
9
+ version: 0.5.7
10
10
  platform: ruby
11
11
  authors:
12
12
  - Erik Osterman
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2012-12-05 00:00:00 -08:00
17
+ date: 2012-12-06 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency