redis-stat 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in redis-stat.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Junegunn Choi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # redis-stat
2
+
3
+ A command-line Redis monitoring tool written in Ruby.
4
+
5
+ ## Installation
6
+
7
+ ```
8
+ gem install redis-stat
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```
14
+ usage: redis-stat [HOST[:PORT]] [INTERVAL [COUNT]]
15
+
16
+ --csv=OUTPUT_CSV_FILE_PATH Saves the result in CSV format
17
+ -v, --verbose Show more info
18
+ --version Show version
19
+ --help Show this message
20
+ ```
21
+
22
+ ## Examples
23
+
24
+ ```
25
+ redis-stat
26
+
27
+ redis-stat 1
28
+
29
+ redis-stat localhost:6380
30
+
31
+ redis-stat localhost:6380 1 10
32
+
33
+ redis-stat localhost:6380 1 10 --csv=/tmp/output.csv --verbose
34
+ ```
35
+
36
+ ## Screenshot
37
+
38
+ ![](https://github.com/junegunn/redis-stat/raw/master/screenshots/redis-stat-0.1.0.png)
39
+
40
+
41
+ ## Contributing
42
+
43
+ 1. Fork it
44
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
45
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
46
+ 4. Push to the branch (`git push origin my-new-feature`)
47
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+ Rake::TestTask.new(:test) do |test|
5
+ test.libs << 'lib' << 'test'
6
+ test.pattern = 'test/**/test_*.rb'
7
+ test.verbose = true
8
+ end
data/bin/redis-stat ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'redis-stat'
5
+
6
+ options = RedisStat::Option.parse ARGV
7
+ rs = RedisStat.new options
8
+ rs.start $stdout
data/lib/redis-stat.rb ADDED
@@ -0,0 +1,351 @@
1
+ require "redis-stat/version"
2
+ require "redis-stat/option"
3
+ require 'insensitive_hash'
4
+ require 'redis'
5
+ require 'tabularize'
6
+ require 'ansi'
7
+ require 'csv'
8
+
9
+ class RedisStat
10
+ DEFAULT_TERM_WIDTH = 180
11
+ DEFAULT_TERM_HEIGHT = 25
12
+
13
+ def initialize options = {}
14
+ @options = RedisStat::Option::DEFAULT.merge options
15
+ @redis = Redis.new(Hash[ @options.select { |k, _| [:host, :port].include? k } ])
16
+ @max_count = @options[:count]
17
+ @count = 0
18
+ @colors = @options[:colors] || COLORS
19
+ end
20
+
21
+ def start output_stream
22
+ @os = output_stream
23
+ trap('INT') { Thread.main.raise Interrupt }
24
+
25
+ @csv = File.open(@options[:csv], 'w') if @options[:csv]
26
+ update_term_size!
27
+
28
+ begin
29
+ @started_at = Time.now
30
+ loop do
31
+ @info = @redis.info.insensitive
32
+ @info[:at] = Time.now.to_f
33
+
34
+ output @info, @prev_info, @csv
35
+
36
+ @prev_info = @info
37
+ @count += 1
38
+ break if @max_count && @count >= @max_count
39
+ sleep @options[:interval]
40
+ end
41
+ @os.puts
42
+ rescue Interrupt
43
+ @os.puts
44
+ @os.puts ansi(:yellow, :bold) { "Interrupted." }
45
+ rescue Exception => e
46
+ @os.puts ansi(:red, :bold) { e.to_s }
47
+ exit 1
48
+ ensure
49
+ @csv.close if @csv
50
+ end
51
+ @os.puts ansi(:blue, :bold) {
52
+ "Elapsed: #{"%.2f" % (Time.now - @started_at)} sec."
53
+ }
54
+ end
55
+
56
+ private
57
+ def update_term_size!
58
+ @term_width = (`tput cols` rescue DEFAULT_TERM_WIDTH).to_i
59
+ @term_height = (`tput lines` rescue DEFAULT_TERM_HEIGHT).to_i - 4
60
+ end
61
+
62
+ def move! lines
63
+ return if lines == 0
64
+
65
+ @os.print(
66
+ if defined?(Win32::Console)
67
+ if lines < 0
68
+ "\e[#{- lines}F"
69
+ else
70
+ "\e[#{lines}E"
71
+ end
72
+ else
73
+ if lines < 0
74
+ "\e[#{- lines}A\e[0G"
75
+ else
76
+ "\e[#{lines}B\e[0G"
77
+ end
78
+ end)
79
+ end
80
+
81
+ def output info, prev_info, file
82
+ info_output = process info, prev_info
83
+
84
+ init_table info_output unless @table
85
+
86
+ movement = nil
87
+ if @count == 0
88
+ movement = 0
89
+ output_static_info info
90
+
91
+ if file
92
+ file.puts CSV.generate_line(info_output.map { |pair|
93
+ LABELS[pair.first] || pair.first
94
+ })
95
+ end
96
+ elsif @count % @term_height == 0
97
+ movement = -1
98
+ update_term_size!
99
+ init_table info_output
100
+ end
101
+
102
+ # Build output table
103
+ @table << info_output.map { |pair|
104
+ ansi(*@colors[pair.first]) { [*pair.last].first }
105
+ }
106
+ lines = @table.to_s.lines.map(&:chomp)
107
+ width = lines.first.length
108
+ height = lines.length
109
+
110
+ # Calculate the number of lines to go upward
111
+ if movement.nil?
112
+ if @prev_width && @prev_width == width
113
+ lines = lines[-2..-1]
114
+ movement = -1
115
+ else
116
+ movement = -(height - 1)
117
+ end
118
+ end
119
+ @prev_width = width
120
+
121
+ move! movement
122
+ begin
123
+ @os.print $/ + lines.join($/)
124
+
125
+ if file
126
+ file.puts CSV.generate_line(info_output.map { |pair|
127
+ [*pair.last].last
128
+ })
129
+ end
130
+ rescue Interrupt
131
+ move! -movement
132
+ raise
133
+ end
134
+ end
135
+
136
+ def output_static_info info
137
+ data =
138
+ {
139
+ :redis_stat_version => RedisStat::VERSION,
140
+ :redis_host => @options[:host],
141
+ :redis_port => @options[:port],
142
+ :csv => @options[:csv],
143
+ }.merge(
144
+ Hash[
145
+ [
146
+ :redis_version,
147
+ :process_id,
148
+ :uptime_in_seconds,
149
+ :uptime_in_days,
150
+ :gcc_version,
151
+ :role,
152
+ :connected_slaves, # FIXME: not so static
153
+ :aof_enabled,
154
+ :vm_enabled
155
+ ].map { |k| [k, info[k]] }
156
+ ]
157
+ ).reject { |k, v| v.nil? }.to_a
158
+ @os.puts Tabularize.it(data, :align => :left).map { |pair|
159
+ ansi(:bold) { pair.first } + ' : ' + pair.last
160
+ }
161
+ end
162
+
163
+ def init_table info_output
164
+ @table = Tabularize.new :unicode => false,
165
+ :align => :right,
166
+ :hborder => ansi(:black, :bold) { '-' },
167
+ :iborder => ansi(:black, :bold) { '+' },
168
+ :vborder => ' ',
169
+ :pad_left => 0,
170
+ :pad_right => 0,
171
+ :screen_width => @term_width
172
+ @table << info_output.map { |pair|
173
+ ansi(*((@colors[pair.first] || []) + [:underline])) {
174
+ LABELS[pair.first] || pair.first
175
+ }
176
+ }
177
+ @table.separator!
178
+ end
179
+
180
+ def process info, prev_info
181
+ MEASURES[@options[:verbose] ? :verbose : :default].map { |key|
182
+ [ key, process_how(info, prev_info, key) ]
183
+ }.select { |pair| pair.last }
184
+ end
185
+
186
+ def process_how info, prev_info, key
187
+ dur = prev_info && (info[:at] - prev_info[:at])
188
+
189
+ get_diff = lambda do |label|
190
+ if dur
191
+ (info[label].to_f - prev_info[label].to_f) / dur
192
+ else
193
+ nil
194
+ end
195
+ end
196
+
197
+ case key
198
+ when :at
199
+ Time.now.strftime('%H:%M:%S')
200
+ when :used_cpu_user, :used_cpu_sys
201
+ val = get_diff.call(key)
202
+ [humanize_number(val), val]
203
+ when :keys
204
+ val = Hash[ info.select { |k, v| k =~ /^db[0-9]+$/ } ].values.inject(0) { |sum, v|
205
+ sum + Hash[ v.split(',').map { |e| e.split '=' } ]['keys'].to_i
206
+ }
207
+ [humanize_number(val), val]
208
+ when :evicted_keys_per_second, :expired_keys_per_second, :keyspace_hits_per_second,
209
+ :keyspace_misses_per_second, :total_commands_processed_per_second
210
+ val = get_diff.call(key.to_s.gsub(/_per_second$/, '').to_sym)
211
+ [humanize_number(val), val]
212
+ when :total_commands_processed, :evicted_keys, :expired_keys, :keyspace_hits, :keyspace_misses
213
+ [humanize_number(info[key].to_i), info[key]]
214
+ when :used_memory, :used_memory_rss, :aof_current_size, :aof_base_size
215
+ [humanize_number(info[key].to_i, 1024, 'B'), info[key]]
216
+ else
217
+ info[key]
218
+ end
219
+ end
220
+
221
+ def format_number num
222
+ if num.to_i == num
223
+ num.to_i
224
+ elsif num < 10
225
+ "%.2f" % num
226
+ elsif num < 100
227
+ "%.1f" % num
228
+ else
229
+ num.to_i
230
+ end.to_s
231
+ end
232
+
233
+ def humanize_number bytes, k = 1000, suffix = ''
234
+ return '-' if bytes.nil?
235
+
236
+ bytes = bytes.to_f
237
+ if bytes < k
238
+ format_number(bytes)
239
+ elsif bytes < k ** 2
240
+ format_number(bytes / k) + 'K' + suffix
241
+ elsif bytes < k ** 3
242
+ format_number(bytes / k ** 2) + 'M' + suffix
243
+ else
244
+ format_number(bytes / k ** 3) + 'G' + suffix
245
+ end
246
+ end
247
+
248
+ def ansi *args, &block
249
+ if args.empty?
250
+ block.call
251
+ else
252
+ ANSI::Code.ansi *args, &block
253
+ end
254
+ end
255
+
256
+ MEASURES = {
257
+ :default => [
258
+ :at,
259
+ :used_cpu_user,
260
+ :used_cpu_sys,
261
+ :connected_clients,
262
+ :blocked_clients,
263
+ :used_memory,
264
+ :used_memory_rss,
265
+ :keys,
266
+ :total_commands_processed_per_second,
267
+ :expired_keys_per_second,
268
+ :evicted_keys_per_second,
269
+ :keyspace_hits_per_second,
270
+ :keyspace_misses_per_second,
271
+ :aof_current_size,
272
+ :pubsub_channels,
273
+ ],
274
+ :verbose => [
275
+ :at,
276
+ :used_cpu_user,
277
+ :used_cpu_sys,
278
+ :connected_clients,
279
+ :blocked_clients,
280
+ :used_memory,
281
+ :used_memory_rss,
282
+ :mem_fragmentation_ratio,
283
+ :keys,
284
+ :total_commands_processed_per_second,
285
+ :total_commands_processed,
286
+ :expired_keys_per_second,
287
+ :expired_keys,
288
+ :evicted_keys_per_second,
289
+ :evicted_keys,
290
+ :keyspace_hits_per_second,
291
+ :keyspace_hits,
292
+ :keyspace_misses_per_second,
293
+ :keyspace_misses,
294
+ :aof_current_size,
295
+ :aof_base_size,
296
+ :pubsub_channels,
297
+ :pubsub_patterns,
298
+ ]
299
+ }
300
+
301
+ COLORS = {
302
+ :at => [:bold],
303
+ :used_cpu_user => [:yellow, :bold],
304
+ :used_cpu_sys => [:yellow],
305
+ :connected_clients => [:cyan, :bold],
306
+ :blocked_clients => [:cyan, :bold],
307
+ :used_memory => [:green],
308
+ :used_memory_rss => [:green],
309
+ :mem_fragmentation_ratio => [:green],
310
+ :keys => [:bold],
311
+ :total_commands_processed => [:blue, :bold],
312
+ :total_commands_processed_per_second => [:blue, :bold],
313
+ :expired_keys => [:red],
314
+ :expired_keys_per_second => [:red],
315
+ :evicted_keys => [:red, :bold],
316
+ :evicted_keys_per_second => [:red, :bold],
317
+ :keyspace_hits => [:magenta, :bold],
318
+ :keyspace_hits_per_second => [:magenta, :bold],
319
+ :keyspace_misses => [:magenta],
320
+ :keyspace_misses_per_second => [:magenta],
321
+ :aof_current_size => [:cyan],
322
+ :aof_base_size => [:cyan],
323
+ :pubsub_channels => [:cyan, :bold],
324
+ :pubsub_patterns => [:cyan, :bold],
325
+ }
326
+
327
+ LABELS = {
328
+ :at => 'time',
329
+ :used_cpu_user => 'us',
330
+ :used_cpu_sys => 'sy',
331
+ :connected_clients => 'cl',
332
+ :blocked_clients => 'bcl',
333
+ :used_memory => 'mem',
334
+ :used_memory_rss => 'rss',
335
+ :mem_fragmentation_ratio => 'frag',
336
+ :total_commands_processed => 'cmd',
337
+ :total_commands_processed_per_second => 'cmd/s',
338
+ :expired_keys => 'exp',
339
+ :expired_keys_per_second => 'exp/s',
340
+ :evicted_keys => 'evt',
341
+ :evicted_keys_per_second => 'evt/s',
342
+ :keyspace_hits => 'hit',
343
+ :keyspace_hits_per_second => 'hit/s',
344
+ :keyspace_misses => 'mis',
345
+ :keyspace_misses_per_second => 'mis/s',
346
+ :aof_current_size => 'aofcs',
347
+ :aof_base_size => 'aofbs',
348
+ :pubsub_channels => 'psch',
349
+ :pubsub_patterns => 'psp',
350
+ }
351
+ end
@@ -0,0 +1,101 @@
1
+ require 'optparse'
2
+
3
+ class RedisStat
4
+ module Option
5
+ DEFAULT = {
6
+ :host => '127.0.0.1',
7
+ :port => 6379,
8
+ :interval => 2,
9
+ :count => nil,
10
+ :csv => nil
11
+ }
12
+
13
+ def self.parse argv
14
+ argv = argv.dup
15
+
16
+ options = DEFAULT.dup
17
+ opts = ::OptionParser.new { |opts|
18
+ opts.banner = "usage: redis-stat [HOST[:PORT]] [INTERVAL [COUNT]]"
19
+ opts.separator ''
20
+
21
+ opts.on('--csv=OUTPUT_CSV_FILE_PATH', 'Save the result in CSV format') do |v|
22
+ options[:csv] = v
23
+ end
24
+
25
+ opts.on('-v', '--verbose', 'Show more info') do |v|
26
+ options[:verbose] = v
27
+ end
28
+
29
+ opts.on('--version', 'Show version') do
30
+ puts RedisStat::VERSION
31
+ exit 0
32
+ end
33
+
34
+ opts.on_tail('--help', 'Show this message') do
35
+ puts opts
36
+ exit 0
37
+ end
38
+ }
39
+
40
+ begin
41
+ opts.parse! argv
42
+
43
+ is_number = lambda { |str| str =~ /^([0-9]\.?[0-9]*)$|^([1-9][0-9]*)$/ }
44
+ set_options = lambda { |host_port, interval, count|
45
+ if host_port
46
+ host, port = host_port.split(':')
47
+ options[:host] = host
48
+ options[:port] = port.to_i if port
49
+ end
50
+
51
+ options[:interval] = interval.to_f if interval
52
+ options[:count] = count.to_i if count
53
+ }
54
+
55
+ case argv.length
56
+ when 1
57
+ if is_number.call argv.first
58
+ set_options.call nil, argv.first, nil
59
+ else
60
+ set_options.call argv.first, nil, nil
61
+ end
62
+ when 2
63
+ if is_number.call argv.first
64
+ set_options.call nil, argv.first, argv.last
65
+ else
66
+ set_options.call argv.first, argv.last, nil
67
+ end
68
+ when 3
69
+ set_options.call *argv
70
+ end
71
+
72
+ validate options
73
+
74
+ return options
75
+ rescue SystemExit => e
76
+ exit e.status
77
+ rescue Exception => e
78
+ puts e.to_s
79
+ puts opts
80
+ exit 1
81
+ end
82
+ end
83
+
84
+ def self.validate options
85
+ interval = options[:interval]
86
+ unless interval.is_a?(Numeric) && interval > 0
87
+ raise ArgumentError.new("Invalid interval: #{interval}")
88
+ end
89
+
90
+ count = options[:count]
91
+ unless count.nil? || (count.is_a?(Numeric) && count > 0)
92
+ raise ArgumentError.new("Invalid count: #{count}")
93
+ end
94
+
95
+ port = options[:port]
96
+ unless port.is_a?(Fixnum) && port > 0 && port < 65536
97
+ raise ArgumentError.new("Invalid port: #{port}")
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,3 @@
1
+ class RedisStat
2
+ VERSION = "0.1.2"
3
+ end
@@ -0,0 +1,24 @@
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 command-line Redis monitoring tool}
8
+ gem.summary = %q{A command-line Redis monitoring tool}
9
+ gem.homepage = "https://github.com/junegunn/redis-stat"
10
+
11
+ gem.files = `git ls-files`.split("\n").reject { |f| f =~ /^screenshots/ }
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "redis-stat"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = RedisStat::VERSION
17
+
18
+ gem.add_runtime_dependency "ansi", '~> 1.4.3'
19
+ gem.add_runtime_dependency "redis", '~> 3.0.1'
20
+ gem.add_runtime_dependency "tabularize", '~> 0.2.4'
21
+ gem.add_runtime_dependency "insensitive_hash", '~> 0.2.4'
22
+
23
+ gem.add_development_dependency 'test-unit'
24
+ end
@@ -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,74 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ require 'redis-stat'
5
+
6
+ class TestRedisStat < Test::Unit::TestCase
7
+ def test_option_parse
8
+ options = RedisStat::Option.parse([])
9
+ assert_equal RedisStat::Option::DEFAULT.sort, options.sort
10
+
11
+ options = RedisStat::Option.parse(%w[localhost:1000 20])
12
+ assert_equal({
13
+ :host => 'localhost',
14
+ :port => 1000,
15
+ :interval => 20,
16
+ :count => nil,
17
+ :csv => nil
18
+ }.sort, options.sort)
19
+
20
+ options = RedisStat::Option.parse(%w[localhost:1000 20 30])
21
+ assert_equal({
22
+ :host => 'localhost',
23
+ :port => 1000,
24
+ :interval => 20,
25
+ :count => 30,
26
+ :csv => nil
27
+ }.sort, options.sort)
28
+
29
+ options = RedisStat::Option.parse(%w[20])
30
+ assert_equal({
31
+ :host => '127.0.0.1',
32
+ :port => 6379,
33
+ :interval => 20,
34
+ :count => nil,
35
+ :csv => nil
36
+ }.sort, options.sort)
37
+
38
+ options = RedisStat::Option.parse(%w[20 30])
39
+ assert_equal({
40
+ :host => '127.0.0.1',
41
+ :port => 6379,
42
+ :interval => 20,
43
+ :count => 30,
44
+ :csv => nil
45
+ }.sort, options.sort)
46
+
47
+ options = RedisStat::Option.parse(%w[localhost:8888 10 --csv=/tmp/a.csv])
48
+ assert_equal({
49
+ :port => 8888,
50
+ :host => 'localhost',
51
+ :interval => 10,
52
+ :count => nil,
53
+ :csv => '/tmp/a.csv',
54
+ }.sort, options.sort)
55
+ end
56
+
57
+ def test_option_parse_invalid
58
+ [
59
+ %w[localhost 0],
60
+ %w[localhost 5 0]
61
+ ].each do |argv|
62
+ assert_raise(SystemExit) {
63
+ options = RedisStat::Option.parse(argv)
64
+ }
65
+ end
66
+ end
67
+
68
+ def test_start
69
+ rs = RedisStat.new :interval => 0.1, :count => 200, :verbose => true, :csv => '/tmp/redis-stat.csv'
70
+ rs.start $stdout
71
+ end
72
+ end
73
+
74
+
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis-stat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Junegunn Choi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: ansi
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.4.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.4.3
30
+ - !ruby/object:Gem::Dependency
31
+ name: redis
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 3.0.1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 3.0.1
46
+ - !ruby/object:Gem::Dependency
47
+ name: tabularize
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.2.4
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.2.4
62
+ - !ruby/object:Gem::Dependency
63
+ name: insensitive_hash
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.2.4
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.2.4
78
+ - !ruby/object:Gem::Dependency
79
+ name: test-unit
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: A command-line Redis monitoring tool
95
+ email:
96
+ - junegunn.c@gmail.com
97
+ executables:
98
+ - redis-stat
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - .gitignore
103
+ - Gemfile
104
+ - LICENSE
105
+ - README.md
106
+ - Rakefile
107
+ - bin/redis-stat
108
+ - lib/redis-stat.rb
109
+ - lib/redis-stat/option.rb
110
+ - lib/redis-stat/version.rb
111
+ - redis-stat.gemspec
112
+ - test/bin_helper.rb
113
+ - test/test_redis-stat.rb
114
+ homepage: https://github.com/junegunn/redis-stat
115
+ licenses: []
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 1.8.24
135
+ signing_key:
136
+ specification_version: 3
137
+ summary: A command-line Redis monitoring tool
138
+ test_files:
139
+ - test/bin_helper.rb
140
+ - test/test_redis-stat.rb