redis-stat 0.3.1 → 0.3.2

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.
@@ -9,14 +9,15 @@ class RedisStat
9
9
  MEASURES = {
10
10
  :static => [
11
11
  :redis_version,
12
+ :redis_mode,
12
13
  :process_id,
13
14
  :uptime_in_seconds,
14
15
  :uptime_in_days,
15
- :gcc_version,
16
16
  :role,
17
17
  :connected_slaves,
18
18
  :aof_enabled,
19
- :vm_enabled
19
+ [:rdb_bgsave_in_progress, :bgsave_in_progress],
20
+ [:rdb_last_save_time, :last_save_time],
20
21
  ],
21
22
  :default => [
22
23
  :at,
@@ -57,7 +58,7 @@ class RedisStat
57
58
  :keyspace_misses,
58
59
  :aof_current_size,
59
60
  :aof_base_size,
60
- :changes_since_last_save,
61
+ [:rdb_changes_since_last_save, :changes_since_last_save],
61
62
  :pubsub_channels,
62
63
  :pubsub_patterns,
63
64
  ]
@@ -85,7 +86,7 @@ class RedisStat
85
86
  :keyspace_misses_per_second => [:magenta],
86
87
  :aof_current_size => [:cyan],
87
88
  :aof_base_size => [:cyan],
88
- :changes_since_last_save => [:green, :bold],
89
+ :rdb_changes_since_last_save => [:green, :bold],
89
90
  :pubsub_channels => [:cyan, :bold],
90
91
  :pubsub_patterns => [:cyan, :bold],
91
92
  }
@@ -112,7 +113,7 @@ class RedisStat
112
113
  :keyspace_misses_per_second => 'mis/s',
113
114
  :aof_current_size => 'aofcs',
114
115
  :aof_base_size => 'aofbs',
115
- :changes_since_last_save => 'chsv',
116
+ :rdb_changes_since_last_save => 'chsv',
116
117
  :pubsub_channels => 'psch',
117
118
  :pubsub_patterns => 'psp',
118
119
  }
@@ -42,9 +42,6 @@ module Option
42
42
 
43
43
  opts.on('--server[=PORT]', "Launch redis-stat web server (default port: #{RedisStat::DEFAULT_SERVER_PORT})") do |v|
44
44
  options[:server_port] = v || RedisStat::DEFAULT_SERVER_PORT
45
- if RUBY_PLATFORM == 'java'
46
- raise ArgumentError.new("Sorry. redis-stat server is not supported in JRuby.")
47
- end
48
45
  end
49
46
 
50
47
  opts.on('--daemon', "Daemonize redis-stat. Must be used with --server option.") do |v|
@@ -66,7 +63,7 @@ module Option
66
63
  exit 0
67
64
  end
68
65
  }
69
-
66
+
70
67
  begin
71
68
  opts.parse! argv
72
69
 
@@ -125,7 +122,7 @@ module Option
125
122
  raise ArgumentError.new("Invalid style")
126
123
  end
127
124
  end
128
-
125
+
129
126
  if options[:daemon] && options[:server_port].nil?
130
127
  raise ArgumentError.new("--daemon option must be used in conjunction with --server option")
131
128
  end
@@ -5,8 +5,7 @@ var history = [],
5
5
  colors,
6
6
  info,
7
7
  fade_dur,
8
- chart_options,
9
- stats_to_update = ['uptime_in_seconds', 'uptime_in_days']
8
+ chart_options
10
9
 
11
10
  var initialize = function(params) {
12
11
  measures = params.measures
@@ -89,7 +88,7 @@ var initialize = function(params) {
89
88
  shadow: false,
90
89
  },
91
90
  series: [
92
- { label: "used" },
91
+ { label: "mem" },
93
92
  { label: "rss" }
94
93
  ],
95
94
  axesDefaults: {
@@ -134,8 +133,13 @@ var initialize = function(params) {
134
133
  }
135
134
 
136
135
  var appendToHistory = function(json) {
137
- history.push(json)
138
- if (history.length > max) history.shift()
136
+ if (history.length == 0 || json.at > history[ history.length - 1 ].at) {
137
+ history.push(json)
138
+ if (history.length > max) history.shift()
139
+ return true
140
+ } else {
141
+ return false
142
+ }
139
143
  }
140
144
 
141
145
  var updateTable = function() {
@@ -144,12 +148,10 @@ var updateTable = function() {
144
148
  jd = json.dynamic
145
149
 
146
150
  // Instance information (mostly static)
147
- // for (stat in js) {
148
- for (var i = 0; i < stats_to_update.length; ++i) {
149
- var stat = stats_to_update[i]
151
+ for (var stat in js) {
150
152
  $("#" + stat).replaceWith(
151
153
  "<tr id='" + stat + "'><th>" + stat + "</th>" +
152
- js[stat].map(function(e) { return "<td>" + e + "</td>" }).join() +
154
+ js[stat].map(function(e) { return "<td>" + (e == null ? "" : e) + "</td>" }).join() +
153
155
  "</tr>"
154
156
  )
155
157
  }
@@ -26,6 +26,11 @@
26
26
  <div class="row">
27
27
  <div class="span12">
28
28
  <h3>Dashboard</h3>
29
+ <% unless RUBY_PLATFORM == 'java' %>
30
+ <div class="alert alert-error hide">
31
+ <h4>Lost connection to redis-stat</h4>
32
+ </div>
33
+ <% end %>
29
34
  </div>
30
35
  </div>
31
36
 
@@ -80,7 +85,7 @@
80
85
  </tr>
81
86
  </thead>
82
87
  <tbody>
83
- <% RedisStat::MEASURES[:static].each do |stat| %>
88
+ <% @tab_measures.each do |stat| %>
84
89
  <tr id="<%= stat %>">
85
90
  <th>
86
91
  <%= stat %>
@@ -103,19 +108,6 @@
103
108
  <img style="position: fixed; top: 0; right: 0; border: 0; z-index: 10000" src="/forkme.png" alt="Fork me on GitHub">
104
109
  </a>
105
110
 
106
- <div class="modal hide fade" id="fail" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
107
- <div class="modal-header">
108
- <h3 id="myModalLabel">Oops!</h3>
109
- </div>
110
- <div class="modal-body">
111
- <p>Lost connection to redis-stat.</p>
112
- <p>Try reloading the page.</p>
113
- </div>
114
- <div class="modal-footer">
115
- <a href="/" class="btn btn-primary">Reload</a>
116
- </div>
117
- </div>
118
-
119
111
  <footer class="footer">
120
112
  <div class="container">
121
113
  <p>Powered by <a href="http://twitter.github.com/bootstrap/">Bootstrap</a>, <a href="http://jquery.com/">jQuery</a> and <a href="http://www.jqplot.com/">jqPlot</a>.</p>
@@ -134,15 +126,19 @@
134
126
 
135
127
  $("#stat_table th a").tooltip()
136
128
 
129
+ // TODO Check (typeof(EventSource) !== "undefined")
130
+
137
131
  var source = new EventSource("/pull")
138
132
  source.onmessage = function(e) {
139
- appendToHistory(JSON.parse(e.data))
140
- updateTable()
141
- updatePlot()
133
+ if (appendToHistory(JSON.parse(e.data))) {
134
+ $(".alert").fadeOut()
135
+ updateTable()
136
+ updatePlot()
137
+ }
142
138
  }
143
139
  source.onerror = function(e) {
144
- source.close()
145
- $('#fail').modal({backdrop: 'static'})
140
+ $(".alert").fadeIn()
141
+ // source.close()
146
142
  }
147
143
  })
148
144
  </script>
@@ -1,5 +1,6 @@
1
1
  require 'sinatra/base'
2
2
  require 'json'
3
+ require 'thread'
3
4
 
4
5
  class RedisStat
5
6
  class Server < Sinatra::Base
@@ -7,7 +8,10 @@ class Server < Sinatra::Base
7
8
  STAT_TABLE_ROWS = 10
8
9
 
9
10
  configure do
10
- unless RUBY_PLATFORM == 'java'
11
+ if RUBY_PLATFORM == 'java'
12
+ require 'puma'
13
+ set :server, :puma
14
+ else
11
15
  require 'thin'
12
16
  set :server, :thin
13
17
  end
@@ -15,24 +19,32 @@ class Server < Sinatra::Base
15
19
  set :root, File.join( File.dirname(__FILE__), 'server' )
16
20
  set :clients, []
17
21
  set :history, []
22
+ set :mutex, Mutex.new
18
23
  end
19
24
 
20
25
  get '/' do
21
- @hosts = settings.redis_stat.hosts
22
- @info = settings.redis_stat.info
23
- @measures = settings.redis_stat.measures
24
- @interval = settings.redis_stat.interval
25
- @verbose = settings.redis_stat.verbose ? 'verbose' : ''
26
- @history = settings.history
26
+ @hosts = settings.redis_stat.hosts
27
+ @info = settings.redis_stat.info
28
+ @measures = settings.redis_stat.measures
29
+ @tab_measures = settings.redis_stat.tab_measures
30
+ @interval = settings.redis_stat.interval
31
+ @verbose = settings.redis_stat.verbose ? 'verbose' : ''
32
+ @history = settings.history
27
33
  erb :index
28
34
  end
29
35
 
30
36
  get '/pull' do
31
37
  content_type 'text/event-stream'
32
38
 
33
- stream(:keep_open) do |out|
34
- settings.clients << out
35
- out.callback { settings.clients.delete out }
39
+ if RUBY_PLATFORM == 'java'
40
+ if last = settings.mutex.synchronize { settings.history.last }
41
+ body "retry: #{settings.redis_stat.interval * 900}\ndata: #{last.to_json}\n\n"
42
+ end
43
+ else
44
+ stream(:keep_open) do |out|
45
+ settings.clients << out
46
+ out.callback { settings.clients.delete out }
47
+ end
36
48
  end
37
49
  end
38
50
 
@@ -44,14 +56,18 @@ class Server < Sinatra::Base
44
56
  end
45
57
 
46
58
  def push info, data
47
- static = Hash[RedisStat::MEASURES[:static].map { |stat|
59
+ static = Hash[settings.redis_stat.tab_measures.map { |stat|
48
60
  [stat, info[stat]]
49
61
  }]
50
- data = {:static => static, :dynamic => data}
62
+ data = {:at => Time.now.to_i, :static => static, :dynamic => data}
63
+
64
+ hist = settings.history
65
+ settings.mutex.synchronize do
66
+ hist << data
67
+ hist.shift if hist.length > HISTORY_LENGTH
68
+ end
51
69
 
52
- @history = settings.history
53
- @history << data
54
- @history.shift if @history.length > HISTORY_LENGTH
70
+ return if settings.clients.empty?
55
71
 
56
72
  resp = "data: #{data.to_json}\n\n"
57
73
  settings.clients.each do |cl|
@@ -1,3 +1,3 @@
1
1
  class RedisStat
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
data/lib/redis-stat.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require 'redis-stat/version'
4
4
  require 'redis-stat/constants'
5
5
  require 'redis-stat/option'
6
- require 'redis-stat/server' unless RUBY_PLATFORM == 'java'
6
+ require 'redis-stat/server'
7
7
  require 'insensitive_hash'
8
8
  require 'redis'
9
9
  require 'tabularize'
@@ -13,12 +13,12 @@ require 'parallelize'
13
13
  require 'si'
14
14
 
15
15
  class RedisStat
16
- attr_reader :hosts, :measures, :verbose, :interval
16
+ attr_reader :hosts, :measures, :tab_measures, :verbose, :interval
17
17
 
18
18
  def initialize options = {}
19
19
  options = RedisStat::Option::DEFAULT.merge options
20
20
  @hosts = options[:hosts]
21
- @redises = @hosts.map { |e|
21
+ @redises = @hosts.map { |e|
22
22
  host, port = e.split(':')
23
23
  Redis.new(Hash[ {:host => host, :port => port, :timeout => DEFAULT_REDIS_TIMEOUT}.select { |k, v| v } ])
24
24
  }
@@ -29,7 +29,8 @@ class RedisStat
29
29
  @csv = options[:csv]
30
30
  @auth = options[:auth]
31
31
  @verbose = options[:verbose]
32
- @measures = MEASURES[ @verbose ? :verbose : :default ]
32
+ @measures = MEASURES[ @verbose ? :verbose : :default ].map { |m| [*m].first }
33
+ @tab_measures= MEASURES[:static].map { |m| [*m].first }
33
34
  @all_measures= MEASURES.values.inject(:+).uniq - [:at]
34
35
  @count = 0
35
36
  @style = options[:style]
@@ -72,9 +73,12 @@ class RedisStat
72
73
  rescue Interrupt
73
74
  raise
74
75
  rescue Exception => e
75
- if (errs += 1) < NUM_RETRIES
76
+ errs += 1
77
+ if server || errs < NUM_RETRIES
76
78
  @os.puts if errs == 1
77
- @os.puts ansi(:red, :bold) { "#{e} (#{errs}/#{NUM_RETRIES})" }
79
+ @os.puts ansi(:red, :bold) {
80
+ "#{e} (#{ server ? "#{errs}" : [errs, NUM_RETRIES].join('/') })"
81
+ }
78
82
  sleep @interval
79
83
  retry
80
84
  else
@@ -128,8 +132,11 @@ private
128
132
  redis.info.insensitive
129
133
  }.each do |rinfo|
130
134
  (@all_measures + rinfo.keys.select { |k| k =~ /^db[0-9]+$/ }).each do |k|
135
+ ks = [*k]
136
+ v = ks.map { |e| rinfo[e] }.compact.first
137
+ k = ks.first
131
138
  info[k] ||= []
132
- info[k] << rinfo[k]
139
+ info[k] << v
133
140
  end
134
141
  end
135
142
  end
@@ -241,7 +248,7 @@ private
241
248
  )
242
249
  tab << [nil] + @hosts.map { |h| ansi(:bold, :green) { h } }
243
250
  tab.separator!
244
- MEASURES[:static].each do |key|
251
+ @tab_measures.each do |key|
245
252
  tab << [ansi(:bold) { key }] + info[key] unless info[key].compact.empty?
246
253
  end
247
254
  @os.puts tab
@@ -260,7 +267,7 @@ private
260
267
  table << info_output.map { |pair|
261
268
  ansi(*((@colors[pair.first] || []) + [:underline])) {
262
269
  LABELS[pair.first] || pair.first
263
- }
270
+ }
264
271
  }
265
272
  table.separator!
266
273
  table
@@ -292,7 +299,7 @@ private
292
299
  val &&= (val * 100).round
293
300
  [humanize_number(val), val]
294
301
  when :keys
295
- val = Hash[ info.select { |k, v| k =~ /^db[0-9]+$/ } ].values.inject(0) { |sum, vs|
302
+ val = Hash[ info.select { |k, v| k =~ /^db[0-9]+$/ } ].values.inject(0) { |sum, vs|
296
303
  sum + vs.map { |v| Hash[ v.split(',').map { |e| e.split '=' } ]['keys'].to_i }.inject(:+)
297
304
  }
298
305
  [humanize_number(val), val]
data/redis-stat.gemspec CHANGED
@@ -17,15 +17,18 @@ Gem::Specification.new do |gem|
17
17
  gem.version = RedisStat::VERSION
18
18
 
19
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'
20
+ gem.add_runtime_dependency "redis", '~> 3.0.2'
21
+ gem.add_runtime_dependency "tabularize", '~> 0.2.9'
22
22
  gem.add_runtime_dependency "insensitive_hash", '~> 0.3.0'
23
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'
24
+ gem.add_runtime_dependency "si", '~> 0.1.4'
25
+ gem.add_runtime_dependency "sinatra", '~> 1.3.3'
26
+ gem.add_runtime_dependency "json", '~> 1.7.5'
27
+
28
+ if RUBY_PLATFORM == 'java'
29
+ gem.add_runtime_dependency "puma", '~> 1.6.3'
30
+ else
31
+ gem.add_runtime_dependency "thin", '~> 1.5.0'
29
32
  gem.add_runtime_dependency "daemons", '~> 1.1.9'
30
33
  end
31
34
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-stat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-31 00:00:00.000000000 Z
12
+ date: 2012-12-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ansi
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 3.0.1
37
+ version: 3.0.2
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 3.0.1
45
+ version: 3.0.2
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: tabularize
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: 0.2.8
53
+ version: 0.2.9
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 0.2.8
61
+ version: 0.2.9
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: insensitive_hash
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -98,7 +98,7 @@ dependencies:
98
98
  requirements:
99
99
  - - ~>
100
100
  - !ruby/object:Gem::Version
101
- version: 0.1.3
101
+ version: 0.1.4
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
@@ -106,7 +106,7 @@ dependencies:
106
106
  requirements:
107
107
  - - ~>
108
108
  - !ruby/object:Gem::Version
109
- version: 0.1.3
109
+ version: 0.1.4
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: sinatra
112
112
  requirement: !ruby/object:Gem::Requirement
@@ -124,13 +124,13 @@ dependencies:
124
124
  - !ruby/object:Gem::Version
125
125
  version: 1.3.3
126
126
  - !ruby/object:Gem::Dependency
127
- name: thin
127
+ name: json
128
128
  requirement: !ruby/object:Gem::Requirement
129
129
  none: false
130
130
  requirements:
131
131
  - - ~>
132
132
  - !ruby/object:Gem::Version
133
- version: 1.5.0
133
+ version: 1.7.5
134
134
  type: :runtime
135
135
  prerelease: false
136
136
  version_requirements: !ruby/object:Gem::Requirement
@@ -138,15 +138,15 @@ dependencies:
138
138
  requirements:
139
139
  - - ~>
140
140
  - !ruby/object:Gem::Version
141
- version: 1.5.0
141
+ version: 1.7.5
142
142
  - !ruby/object:Gem::Dependency
143
- name: json
143
+ name: thin
144
144
  requirement: !ruby/object:Gem::Requirement
145
145
  none: false
146
146
  requirements:
147
147
  - - ~>
148
148
  - !ruby/object:Gem::Version
149
- version: 1.7.5
149
+ version: 1.5.0
150
150
  type: :runtime
151
151
  prerelease: false
152
152
  version_requirements: !ruby/object:Gem::Requirement
@@ -154,7 +154,7 @@ dependencies:
154
154
  requirements:
155
155
  - - ~>
156
156
  - !ruby/object:Gem::Version
157
- version: 1.7.5
157
+ version: 1.5.0
158
158
  - !ruby/object:Gem::Dependency
159
159
  name: daemons
160
160
  requirement: !ruby/object:Gem::Requirement