mysql_health 0.5.6 → 0.5.7
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/lib/mysql_health/command_line.rb +13 -3
- data/lib/mysql_health/health.rb +72 -25
- data/lib/mysql_health/version.rb +1 -1
- data/redhat/rubygem-mysql_health.spec +1 -1
- metadata +3 -3
@@ -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] =
|
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] =
|
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] =
|
111
|
+
@options[:server][:addr] = addr.to_s
|
102
112
|
end
|
103
113
|
|
104
114
|
@options[:server][:port] = 3305
|
data/lib/mysql_health/health.rb
CHANGED
@@ -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
|
-
|
117
|
-
|
118
|
-
|
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
|
-
|
121
|
-
|
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] =
|
131
|
+
response[:content] = describe_status(status)
|
126
132
|
else
|
127
133
|
response[:status] = '200 OK'
|
128
|
-
response[:content] =
|
134
|
+
response[:content] = describe_status(status)
|
129
135
|
end
|
130
136
|
else
|
131
137
|
response[:status] = '503 Service Unavailable'
|
132
|
-
response[:content] =
|
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
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
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
|
-
|
162
|
-
|
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] =
|
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] =
|
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] =
|
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] =
|
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.
|
231
|
+
response[:content] = show_slave_status.to_json
|
185
232
|
end
|
186
233
|
rescue Exception => e
|
187
234
|
response[:status] = '500 Server Error'
|
data/lib/mysql_health/version.rb
CHANGED
@@ -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.
|
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
|
-
-
|
9
|
-
version: 0.5.
|
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-
|
17
|
+
date: 2012-12-06 00:00:00 -08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|