redis-stat 0.3.0-java
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +85 -0
- data/Rakefile +8 -0
- data/bin/redis-stat +16 -0
- data/lib/redis-stat/constants.rb +118 -0
- data/lib/redis-stat/option.rb +134 -0
- data/lib/redis-stat/server/public/bootstrap/css/bootstrap-responsive.min.css +9 -0
- data/lib/redis-stat/server/public/bootstrap/css/bootstrap.min.css +9 -0
- data/lib/redis-stat/server/public/bootstrap/img/glyphicons-halflings-white.png +0 -0
- data/lib/redis-stat/server/public/bootstrap/img/glyphicons-halflings.png +0 -0
- data/lib/redis-stat/server/public/bootstrap/js/bootstrap.min.js +6 -0
- data/lib/redis-stat/server/public/css/site.css +67 -0
- data/lib/redis-stat/server/public/favicon.ico +0 -0
- data/lib/redis-stat/server/public/favicon.png +0 -0
- data/lib/redis-stat/server/public/jqplot/jqplot.canvasAxisLabelRenderer.min.js +57 -0
- data/lib/redis-stat/server/public/jqplot/jqplot.canvasAxisTickRenderer.min.js +57 -0
- data/lib/redis-stat/server/public/jqplot/jqplot.canvasTextRenderer.min.js +57 -0
- data/lib/redis-stat/server/public/jqplot/jquery.jqplot.min.css +1 -0
- data/lib/redis-stat/server/public/jqplot/jquery.jqplot.min.js +57 -0
- data/lib/redis-stat/server/public/jquery-1.8.2.min.js +2 -0
- data/lib/redis-stat/server/public/js/site.js +192 -0
- data/lib/redis-stat/server/views/index.erb +145 -0
- data/lib/redis-stat/server.rb +57 -0
- data/lib/redis-stat/version.rb +3 -0
- data/lib/redis-stat.rb +314 -0
- data/redis-stat.gemspec +33 -0
- data/test/bin_helper.rb +9 -0
- data/test/test_redis-stat.rb +193 -0
- metadata +194 -0
data/lib/redis-stat.rb
ADDED
@@ -0,0 +1,314 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'redis-stat/version'
|
4
|
+
require 'redis-stat/constants'
|
5
|
+
require 'redis-stat/option'
|
6
|
+
require 'redis-stat/server' unless RUBY_PLATFORM == 'java'
|
7
|
+
require 'insensitive_hash'
|
8
|
+
require 'redis'
|
9
|
+
require 'tabularize'
|
10
|
+
require 'ansi'
|
11
|
+
require 'csv'
|
12
|
+
require 'parallelize'
|
13
|
+
require 'si'
|
14
|
+
|
15
|
+
class RedisStat
|
16
|
+
attr_reader :hosts, :measures
|
17
|
+
|
18
|
+
def initialize options = {}
|
19
|
+
options = RedisStat::Option::DEFAULT.merge options
|
20
|
+
@hosts = options[:hosts]
|
21
|
+
@redises = @hosts.map { |e|
|
22
|
+
host, port = e.split(':')
|
23
|
+
Redis.new(Hash[ {:host => host, :port => port, :timeout => DEFAULT_REDIS_TIMEOUT}.select { |k, v| v } ])
|
24
|
+
}
|
25
|
+
@interval = options[:interval]
|
26
|
+
@max_count = options[:count]
|
27
|
+
@mono = options[:mono]
|
28
|
+
@colors = options[:colors] || COLORS
|
29
|
+
@csv = options[:csv]
|
30
|
+
@auth = options[:auth]
|
31
|
+
@measures = MEASURES[ options[:verbose] ? :verbose : :default ]
|
32
|
+
@all_measures= MEASURES.values.inject(:+).uniq - [:at]
|
33
|
+
@count = 0
|
34
|
+
@style = options[:style]
|
35
|
+
@first_batch = true
|
36
|
+
@server_port = options[:server_port]
|
37
|
+
@daemonized = options[:daemon]
|
38
|
+
end
|
39
|
+
|
40
|
+
def info
|
41
|
+
collect
|
42
|
+
end
|
43
|
+
|
44
|
+
def start output_stream
|
45
|
+
@os = output_stream
|
46
|
+
trap('INT') { Thread.main.raise Interrupt }
|
47
|
+
|
48
|
+
begin
|
49
|
+
csv = File.open(@csv, 'w') if @csv
|
50
|
+
update_term_size!
|
51
|
+
|
52
|
+
# Warm-up / authenticate only when needed
|
53
|
+
@redises.each do |r|
|
54
|
+
begin
|
55
|
+
r.info
|
56
|
+
rescue Redis::CommandError
|
57
|
+
r.auth @auth if @auth
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
@started_at = Time.now
|
63
|
+
prev_info = nil
|
64
|
+
server = start_server if @server_port
|
65
|
+
|
66
|
+
loop do
|
67
|
+
info = collect
|
68
|
+
info_output = process info, prev_info
|
69
|
+
output info, info_output, csv unless @daemonized
|
70
|
+
server.push info, Hash[info_output] if server
|
71
|
+
prev_info = info
|
72
|
+
|
73
|
+
@count += 1
|
74
|
+
break if @max_count && @count >= @max_count
|
75
|
+
sleep @interval
|
76
|
+
end
|
77
|
+
@os.puts
|
78
|
+
rescue Interrupt
|
79
|
+
@os.puts
|
80
|
+
@os.puts ansi(:yellow, :bold) { "Interrupted." }
|
81
|
+
rescue Exception => e
|
82
|
+
@os.puts ansi(:red, :bold) { e.to_s }
|
83
|
+
raise
|
84
|
+
ensure
|
85
|
+
csv.close if csv
|
86
|
+
end
|
87
|
+
@os.puts ansi(:blue, :bold) {
|
88
|
+
"Elapsed: #{"%.2f" % (Time.now - @started_at)} sec."
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
def start_server
|
94
|
+
RedisStat::Server.set :port, @server_port
|
95
|
+
RedisStat::Server.set :redis_stat, self
|
96
|
+
Thread.new { RedisStat::Server.run! }
|
97
|
+
RedisStat::Server.wait_until_running
|
98
|
+
trap('INT') { Thread.main.raise Interrupt }
|
99
|
+
RedisStat::Server
|
100
|
+
end
|
101
|
+
|
102
|
+
def collect
|
103
|
+
{}.insensitive.tap do |info|
|
104
|
+
class << info
|
105
|
+
def sumf label
|
106
|
+
(self[label] || []).map(&:to_f).inject(:+)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
info[:at] = Time.now.to_f
|
111
|
+
@redises.pmap(@redises.length) { |redis|
|
112
|
+
redis.info.insensitive
|
113
|
+
}.each do |rinfo|
|
114
|
+
(@all_measures + rinfo.keys.select { |k| k =~ /^db[0-9]+$/ }).each do |k|
|
115
|
+
info[k] ||= []
|
116
|
+
info[k] << rinfo[k]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def update_term_size!
|
123
|
+
if RUBY_PLATFORM == 'java'
|
124
|
+
require 'java'
|
125
|
+
begin
|
126
|
+
case JRUBY_VERSION
|
127
|
+
when /^1\.7/
|
128
|
+
@term ||= Java::jline.console.ConsoleReader.new.getTerminal
|
129
|
+
@term_width = (@term.width rescue DEFAULT_TERM_WIDTH)
|
130
|
+
@term_height = (@term.height rescue DEFAULT_TERM_HEIGHT) - 4
|
131
|
+
return
|
132
|
+
when /^1\.6/
|
133
|
+
@term ||= Java::jline.ConsoleReader.new.getTerminal
|
134
|
+
@term_width = (@term.getTerminalWidth rescue DEFAULT_TERM_WIDTH)
|
135
|
+
@term_height = (@term.getTerminalHeight rescue DEFAULT_TERM_HEIGHT) - 4
|
136
|
+
return
|
137
|
+
end
|
138
|
+
rescue Exception
|
139
|
+
# Fallback to tput (which yields incorrect values as of now)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
@term_width = (`tput cols` rescue DEFAULT_TERM_WIDTH).to_i
|
144
|
+
@term_height = (`tput lines` rescue DEFAULT_TERM_HEIGHT).to_i - 4
|
145
|
+
end
|
146
|
+
|
147
|
+
def move! lines
|
148
|
+
return if lines == 0
|
149
|
+
|
150
|
+
@os.print(
|
151
|
+
if defined?(Win32::Console)
|
152
|
+
if lines < 0
|
153
|
+
"\e[#{- lines}F"
|
154
|
+
else
|
155
|
+
"\e[#{lines}E"
|
156
|
+
end
|
157
|
+
else
|
158
|
+
if lines < 0
|
159
|
+
"\e[#{- lines}A\e[0G"
|
160
|
+
else
|
161
|
+
"\e[#{lines}B\e[0G"
|
162
|
+
end
|
163
|
+
end)
|
164
|
+
end
|
165
|
+
|
166
|
+
def output info, info_output, file
|
167
|
+
@table ||= init_table info_output
|
168
|
+
|
169
|
+
movement = nil
|
170
|
+
if @count == 0
|
171
|
+
output_static_info info
|
172
|
+
|
173
|
+
movement = 0
|
174
|
+
if file
|
175
|
+
file.puts CSV.generate_line(info_output.map { |pair|
|
176
|
+
LABELS[pair.first] || pair.first
|
177
|
+
})
|
178
|
+
end
|
179
|
+
elsif @count % @term_height == 0
|
180
|
+
@first_batch = false
|
181
|
+
movement = -1
|
182
|
+
update_term_size!
|
183
|
+
@table = init_table info_output
|
184
|
+
end
|
185
|
+
|
186
|
+
# Build output table
|
187
|
+
@table << info_output.map { |pair|
|
188
|
+
ansi(*@colors[pair.first]) { [*pair.last].first }
|
189
|
+
}
|
190
|
+
lines = @table.to_s.lines.map(&:chomp)
|
191
|
+
lines.delete_at @first_batch ? 1 : 0
|
192
|
+
width = lines.first.length
|
193
|
+
height = lines.length
|
194
|
+
|
195
|
+
# Calculate the number of lines to go upward
|
196
|
+
if movement.nil?
|
197
|
+
if @prev_width && @prev_width == width
|
198
|
+
lines = lines[-2..-1]
|
199
|
+
movement = -1
|
200
|
+
else
|
201
|
+
movement = -(height - 1)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
@prev_width = width
|
205
|
+
|
206
|
+
move! movement
|
207
|
+
begin
|
208
|
+
@os.print $/ + lines.join($/)
|
209
|
+
|
210
|
+
if file
|
211
|
+
file.puts CSV.generate_line(info_output.map { |pair|
|
212
|
+
[*pair.last].last
|
213
|
+
})
|
214
|
+
end
|
215
|
+
rescue Interrupt
|
216
|
+
move! -movement
|
217
|
+
raise
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def output_static_info info
|
222
|
+
tab = Tabularize.new(
|
223
|
+
:unicode => false, :align => :right,
|
224
|
+
:border_style => @style
|
225
|
+
)
|
226
|
+
tab << [nil] + @hosts.map { |h| ansi(:bold, :green) { h } }
|
227
|
+
tab.separator!
|
228
|
+
MEASURES[:static].each do |key|
|
229
|
+
tab << [ansi(:bold) { key }] + info[key] unless info[key].compact.empty?
|
230
|
+
end
|
231
|
+
@os.puts tab
|
232
|
+
end
|
233
|
+
|
234
|
+
def init_table info_output
|
235
|
+
table = Tabularize.new :unicode => false,
|
236
|
+
:align => :right,
|
237
|
+
:border_style => @style,
|
238
|
+
:border_color => @mono ? nil : ANSI::Code.red,
|
239
|
+
:vborder => ' ',
|
240
|
+
:pad_left => 0,
|
241
|
+
:pad_right => 0,
|
242
|
+
:screen_width => @term_width
|
243
|
+
table.separator!
|
244
|
+
table << info_output.map { |pair|
|
245
|
+
ansi(*((@colors[pair.first] || []) + [:underline])) {
|
246
|
+
LABELS[pair.first] || pair.first
|
247
|
+
}
|
248
|
+
}
|
249
|
+
table.separator!
|
250
|
+
table
|
251
|
+
end
|
252
|
+
|
253
|
+
def process info, prev_info
|
254
|
+
@measures.map { |key|
|
255
|
+
[ key, process_how(info, prev_info, key) ]
|
256
|
+
}.select { |pair| pair.last }
|
257
|
+
end
|
258
|
+
|
259
|
+
def process_how info, prev_info, key
|
260
|
+
dur = prev_info && (info[:at] - prev_info[:at])
|
261
|
+
|
262
|
+
get_diff = lambda do |label|
|
263
|
+
if dur && dur > 0
|
264
|
+
(info.sumf(label) - prev_info.sumf(label)) / dur
|
265
|
+
else
|
266
|
+
nil
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
case key
|
271
|
+
when :at
|
272
|
+
val = Time.now.strftime('%H:%M:%S')
|
273
|
+
[val, val]
|
274
|
+
when :used_cpu_user, :used_cpu_sys
|
275
|
+
val = get_diff.call(key)
|
276
|
+
val &&= (val * 100).round
|
277
|
+
[humanize_number(val), val]
|
278
|
+
when :keys
|
279
|
+
val = Hash[ info.select { |k, v| k =~ /^db[0-9]+$/ } ].values.inject(0) { |sum, vs|
|
280
|
+
sum + vs.map { |v| Hash[ v.split(',').map { |e| e.split '=' } ]['keys'].to_i }.inject(:+)
|
281
|
+
}
|
282
|
+
[humanize_number(val), val]
|
283
|
+
when :evicted_keys_per_second, :expired_keys_per_second, :keyspace_hits_per_second,
|
284
|
+
:keyspace_misses_per_second, :total_commands_processed_per_second
|
285
|
+
val = get_diff.call(key.to_s.gsub(/_per_second$/, '').to_sym)
|
286
|
+
[humanize_number(val), val]
|
287
|
+
when :used_memory, :used_memory_rss, :aof_current_size, :aof_base_size
|
288
|
+
val = info.sumf(key)
|
289
|
+
[humanize_number(val.to_i, true), val]
|
290
|
+
else
|
291
|
+
val = info.sumf(key)
|
292
|
+
[humanize_number(val), val]
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def humanize_number num, byte = false
|
297
|
+
return '-' if num.nil?
|
298
|
+
|
299
|
+
num = num.to_i if num == num.to_i
|
300
|
+
if byte
|
301
|
+
num.si_byte
|
302
|
+
else
|
303
|
+
num.si(:min_exp => 0)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def ansi *args, &block
|
308
|
+
if @mono || args.empty?
|
309
|
+
block.call
|
310
|
+
else
|
311
|
+
ANSI::Code.ansi *args, &block
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
data/redis-stat.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/redis-stat/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Junegunn Choi"]
|
6
|
+
gem.email = ["junegunn.c@gmail.com"]
|
7
|
+
gem.description = %q{A Redis monitoring tool written in Ruby}
|
8
|
+
gem.summary = %q{A Redis monitoring tool written in Ruby}
|
9
|
+
gem.homepage = "https://github.com/junegunn/redis-stat"
|
10
|
+
|
11
|
+
gem.platform = 'java' if RUBY_PLATFORM == 'java'
|
12
|
+
gem.files = `git ls-files`.split("\n").reject { |f| f =~ /^screenshots/ }
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.name = "redis-stat"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
gem.version = RedisStat::VERSION
|
18
|
+
|
19
|
+
gem.add_runtime_dependency "ansi", '~> 1.4.3'
|
20
|
+
gem.add_runtime_dependency "redis", '~> 3.0.1'
|
21
|
+
gem.add_runtime_dependency "tabularize", '~> 0.2.8'
|
22
|
+
gem.add_runtime_dependency "insensitive_hash", '~> 0.3.0'
|
23
|
+
gem.add_runtime_dependency "parallelize", '~> 0.4.0'
|
24
|
+
gem.add_runtime_dependency "si", '~> 0.1.3'
|
25
|
+
unless RUBY_PLATFORM == 'java'
|
26
|
+
gem.add_runtime_dependency "sinatra", '~> 1.3.3'
|
27
|
+
gem.add_runtime_dependency "thin", '~> 1.5.0'
|
28
|
+
gem.add_runtime_dependency "json", '~> 1.7.5'
|
29
|
+
gem.add_runtime_dependency "daemons", '~> 1.1.9'
|
30
|
+
end
|
31
|
+
|
32
|
+
gem.add_development_dependency 'test-unit'
|
33
|
+
end
|
data/test/bin_helper.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# DISCLAIMER:
|
5
|
+
# Not a real test!
|
6
|
+
# Just a helper script for running scripts with local source
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '../lib')
|
9
|
+
load File.join(File.dirname(__FILE__), '../bin/', File.basename(ARGV.shift))
|
@@ -0,0 +1,193 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'test-unit'
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
require 'redis-stat'
|
8
|
+
require 'redis'
|
9
|
+
require 'stringio'
|
10
|
+
|
11
|
+
class TestRedisStat < Test::Unit::TestCase
|
12
|
+
def test_humanize_number
|
13
|
+
rs = RedisStat.new
|
14
|
+
assert_equal '0', rs.send(:humanize_number, 0.00)
|
15
|
+
assert_equal '7', rs.send(:humanize_number, 7)
|
16
|
+
assert_equal '0.01', rs.send(:humanize_number, 0.00751)
|
17
|
+
assert_equal '0.08', rs.send(:humanize_number, 0.0751)
|
18
|
+
assert_equal '0.75', rs.send(:humanize_number, 0.751)
|
19
|
+
assert_equal '7.51', rs.send(:humanize_number, 7.51)
|
20
|
+
assert_equal '75.1', rs.send(:humanize_number, 75.1)
|
21
|
+
assert_equal '7.51k', rs.send(:humanize_number, 7510)
|
22
|
+
assert_equal '75.1k', rs.send(:humanize_number, 75100)
|
23
|
+
assert_equal '751k', rs.send(:humanize_number, 751000)
|
24
|
+
assert_equal '7.51M', rs.send(:humanize_number, 7510000)
|
25
|
+
assert_equal '75.1M', rs.send(:humanize_number, 75100000)
|
26
|
+
assert_equal '751M', rs.send(:humanize_number, 751000000)
|
27
|
+
assert_equal '7.51G', rs.send(:humanize_number, 7510000000)
|
28
|
+
assert_equal '75.1G', rs.send(:humanize_number, 75100000000)
|
29
|
+
assert_equal '751G', rs.send(:humanize_number, 751000000000)
|
30
|
+
assert_equal '7.51T', rs.send(:humanize_number, 7510000000000)
|
31
|
+
assert_equal '75.1T', rs.send(:humanize_number, 75100000000000)
|
32
|
+
assert_equal '751T', rs.send(:humanize_number, 751000000000000)
|
33
|
+
assert_equal '7.51P', rs.send(:humanize_number, 7510000000000000)
|
34
|
+
assert_equal '75.1P', rs.send(:humanize_number, 75100000000000000)
|
35
|
+
assert_equal '751P', rs.send(:humanize_number, 751000000000000000)
|
36
|
+
assert_equal '7.51E', rs.send(:humanize_number, 7510000000000000000)
|
37
|
+
assert_equal '75.1E', rs.send(:humanize_number, 75100000000000000000)
|
38
|
+
assert_equal '751E', rs.send(:humanize_number, 751000000000000000000)
|
39
|
+
assert_equal '7.51Z', rs.send(:humanize_number, 7510000000000000000000)
|
40
|
+
|
41
|
+
assert_equal '7.51PB', rs.send(:humanize_number, 7.51 * (1024 ** 5), true)
|
42
|
+
assert_equal '-7.51PB', rs.send(:humanize_number, -7.51 * (1024 ** 5), true)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_option_parse
|
46
|
+
options = RedisStat::Option.parse([])
|
47
|
+
assert_equal RedisStat::Option::DEFAULT.sort, options.sort
|
48
|
+
|
49
|
+
options = RedisStat::Option.parse(%w[localhost:1000 20])
|
50
|
+
assert_equal({
|
51
|
+
:hosts => ['localhost:1000'],
|
52
|
+
:interval => 20,
|
53
|
+
:count => nil,
|
54
|
+
:csv => nil,
|
55
|
+
:style => :unicode
|
56
|
+
}.sort, options.sort)
|
57
|
+
|
58
|
+
options = RedisStat::Option.parse(%w[localhost:1000 20 30])
|
59
|
+
assert_equal({
|
60
|
+
:hosts => ['localhost:1000'],
|
61
|
+
:interval => 20,
|
62
|
+
:count => 30,
|
63
|
+
:csv => nil,
|
64
|
+
:style => :unicode
|
65
|
+
}.sort, options.sort)
|
66
|
+
|
67
|
+
options = RedisStat::Option.parse(%w[20])
|
68
|
+
assert_equal({
|
69
|
+
:hosts => ['127.0.0.1:6379'],
|
70
|
+
:interval => 20,
|
71
|
+
:count => nil,
|
72
|
+
:csv => nil,
|
73
|
+
:style => :unicode
|
74
|
+
}.sort, options.sort)
|
75
|
+
|
76
|
+
options = RedisStat::Option.parse(%w[20 30])
|
77
|
+
assert_equal({
|
78
|
+
:hosts => ['127.0.0.1:6379'],
|
79
|
+
:interval => 20,
|
80
|
+
:count => 30,
|
81
|
+
:csv => nil,
|
82
|
+
:style => :unicode
|
83
|
+
}.sort, options.sort)
|
84
|
+
|
85
|
+
options = RedisStat::Option.parse(%w[localhost:8888 10 --csv=/tmp/a.csv --style=ascii --auth password])
|
86
|
+
assert_equal({
|
87
|
+
:auth => 'password',
|
88
|
+
:hosts => ['localhost:8888'],
|
89
|
+
:interval => 10,
|
90
|
+
:count => nil,
|
91
|
+
:csv => '/tmp/a.csv',
|
92
|
+
:style => :ascii
|
93
|
+
}.sort, options.sort)
|
94
|
+
|
95
|
+
options = RedisStat::Option.parse(%w[-h localhost:8888 10 -a password --csv=/tmp/a.csv --style=ascii])
|
96
|
+
assert_equal({
|
97
|
+
:auth => 'password',
|
98
|
+
:hosts => ['localhost:8888'],
|
99
|
+
:interval => 10,
|
100
|
+
:count => nil,
|
101
|
+
:csv => '/tmp/a.csv',
|
102
|
+
:style => :ascii
|
103
|
+
}.sort, options.sort)
|
104
|
+
|
105
|
+
# Server
|
106
|
+
if RUBY_PLATFORM == 'java'
|
107
|
+
assert_raise(SystemExit) {
|
108
|
+
RedisStat::Option.parse(%w[-h localhost:8888 10 -a password --csv=/tmp/a.csv --style=ascii --server=5555])
|
109
|
+
}
|
110
|
+
assert_raise(SystemExit) {
|
111
|
+
RedisStat::Option.parse(%w[-h localhost:8888 10 -a password --csv=/tmp/a.csv --style=ascii --server=5555 --daemon])
|
112
|
+
}
|
113
|
+
else
|
114
|
+
options = RedisStat::Option.parse(%w[-h localhost:8888 10 -a password --csv=/tmp/a.csv --style=ascii --server=5555 --daemon])
|
115
|
+
assert_equal({
|
116
|
+
:auth => 'password',
|
117
|
+
:hosts => ['localhost:8888'],
|
118
|
+
:interval => 10,
|
119
|
+
:count => nil,
|
120
|
+
:csv => '/tmp/a.csv',
|
121
|
+
:server_port => "5555",
|
122
|
+
:style => :ascii,
|
123
|
+
:daemon => true
|
124
|
+
}.sort, options.sort)
|
125
|
+
end
|
126
|
+
|
127
|
+
options = RedisStat::Option.parse(%w[--no-color])
|
128
|
+
assert_equal true, options[:mono]
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_option_parse_invalid
|
132
|
+
[
|
133
|
+
%w[localhost 0],
|
134
|
+
%w[localhost 5 0]
|
135
|
+
].each do |argv|
|
136
|
+
assert_raise(SystemExit) {
|
137
|
+
options = RedisStat::Option.parse(argv)
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
assert_raise(SystemExit) {
|
142
|
+
RedisStat::Option.parse(%w[--style=html])
|
143
|
+
}
|
144
|
+
|
145
|
+
assert_raise(SystemExit) {
|
146
|
+
RedisStat::Option.parse(%w[--daemon])
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_start
|
151
|
+
csv = '/tmp/redis-stat.csv'
|
152
|
+
cnt = 100
|
153
|
+
rs = RedisStat.new :hosts => %w[localhost] * 5, :interval => 0.01, :count => cnt,
|
154
|
+
:verbose => true, :csv => csv, :auth => 'pw'
|
155
|
+
rs.start $stdout
|
156
|
+
|
157
|
+
assert_equal cnt + 1, File.read(csv).lines.to_a.length
|
158
|
+
ensure
|
159
|
+
File.unlink csv
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_mono
|
163
|
+
[true, false].each do |mono|
|
164
|
+
rs = RedisStat.new :hosts => %w[localhost] * 5, :interval => 0.02, :count => 20,
|
165
|
+
:verbose => true, :auth => 'pw', :mono => mono
|
166
|
+
output = StringIO.new
|
167
|
+
rs.start output
|
168
|
+
puts output.string
|
169
|
+
assert_equal mono, output.string !~ /\e\[\d*(;\d+)*m/
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_static_info_of_mixed_versions
|
174
|
+
# prerequisite
|
175
|
+
r1 = Redis.new(:host => 'localhost')
|
176
|
+
r2 = Redis.new(:host => 'localhost', :port => 6380)
|
177
|
+
|
178
|
+
if r1.info['redis_version'] =~ /^2\.4/ && r2.info['redis_version'] =~ /^2\.2/
|
179
|
+
rs = RedisStat.new :hosts => %w[localhost:6380 localhost], :interval => 1, :count => 1,
|
180
|
+
:auth => 'pw', :style => :ascii
|
181
|
+
output = StringIO.new
|
182
|
+
rs.start output
|
183
|
+
vline = output.string.lines.select { |line| line =~ /gcc_version/ }.first
|
184
|
+
puts vline.gsub(/ +/, ' ')
|
185
|
+
assert vline.gsub(/ +/, ' ').include?('| | 4.2.1 |')
|
186
|
+
else
|
187
|
+
raise NotImplementedError.new # FIXME
|
188
|
+
end
|
189
|
+
rescue Redis::CannotConnectError, NotImplementedError
|
190
|
+
pend "redises not ready"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|