visage-app 0.9.0.pre2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ source :rubygems
4
+
5
+ gem "haml"
6
+ gem "tilt"
7
+ gem "sinatra"
8
+ gem "errand"
9
+ gem "yajl-ruby"
10
+
11
+ group :development do
12
+ gem "shotgun"
13
+ gem "rack-test"
14
+ gem "rspec"
15
+ gem "cucumber"
16
+ gem "webrat"
17
+ gem "jeweler"
18
+ end
data/LICENCE CHANGED
@@ -19,7 +19,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  THE SOFTWARE.
20
20
 
21
21
  Visage is distributed with Highcharts. Torstein Hønsi has kindly granted
22
- permission to distribute Highcharts under the GPL as part of Visage.
22
+ permission to distribute Highcharts under the GPLv2 as part of Visage.
23
23
 
24
24
  If you ever need an excellent JavaScript charting library, please consider
25
25
  purchasing a [commercial license](http://highcharts.com/license) for
data/README.md CHANGED
@@ -33,7 +33,7 @@ On Ubuntu, to install dependencies run:
33
33
 
34
34
  On CentOS, to install dependencies run:
35
35
 
36
- $ sudo yum install -y ruby-rrdtool ruby rubygems collectd
36
+ $ sudo yum install -y ruby-RRDtool ruby rubygems collectd
37
37
 
38
38
  Then install the app with:
39
39
 
@@ -136,21 +136,22 @@ Check out the code with:
136
136
 
137
137
  $ git clone git://github.com/auxesis/visage.git
138
138
 
139
- Install the development dependencies with
139
+ Install the development dependencies with:
140
140
 
141
- $ gem install shotgun rack-test rspec cucumber webrat
141
+ $ gem install bundler
142
+ $ bundle install
142
143
 
143
- And run the app with:
144
+ Run all cucumber features:
144
145
 
145
- $ shotgun visage.rb
146
+ $ rake cucumber
146
147
 
147
- Create and install a new gem from the current source tree:
148
+ And run the app with:
148
149
 
149
- $ rake install
150
+ $ shotgun lib/visage-app/config.ru
150
151
 
151
- Run all cucumber features:
152
+ To create and install a new gem from the current source tree:
152
153
 
153
- $ rake cucumber
154
+ $ rake install
154
155
 
155
156
  Licencing
156
157
  ---------
@@ -158,7 +159,7 @@ Licencing
158
159
  Visage is MIT licensed.
159
160
 
160
161
  Visage is distributed with Highcharts. Torstein Hønsi has kindly granted
161
- permission to distribute Highcharts under the GPL as part of Visage.
162
+ permission to distribute Highcharts under the GPLv2 as part of Visage.
162
163
 
163
164
  If you ever need an excellent JavaScript charting library, please consider
164
165
  purchasing a [commercial license](http://highcharts.com/license) for
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.0.pre2
1
+ 0.9.0
@@ -36,9 +36,9 @@ class CollectdJSON
36
36
  instance_name = parts[2].split('.').first
37
37
  rrd = Errand.new(:filename => rrdname)
38
38
 
39
- data << { :plugin => plugin_name, :instance => instance_name,
39
+ data << { :plugin => plugin_name, :instance => instance_name,
40
40
  :host => host,
41
- :start => opts[:start] || (Time.now - 3600).to_i,
41
+ :start => opts[:start] || (Time.now - 3600).to_i,
42
42
  :finish => opts[:finish] || Time.now.to_i,
43
43
  :rrd => rrd }
44
44
  end
@@ -54,8 +54,8 @@ class CollectdJSON
54
54
  structure = {}
55
55
  datas.each do |data|
56
56
  fetch = data[:rrd].fetch(:function => "AVERAGE",
57
- :start => data[:start],
58
- :finish => data[:finish])
57
+ :start => data[:start],
58
+ :finish => data[:finish])
59
59
  rrd_data = fetch[:data]
60
60
 
61
61
  # A single rrd can have multiple data sets (multiple metrics within
@@ -75,15 +75,22 @@ class CollectdJSON
75
75
  end
76
76
  end
77
77
 
78
+ # Last value is always wack. Set to 0, so the timescale isn't off by 1.
78
79
  metric[-1] = 0.0
80
+ host = data[:host]
81
+ plugin = data[:plugin]
82
+ instance = data[:instance]
83
+ start = data[:start].to_i
84
+ finish = data[:finish].to_i
85
+
86
+ structure[host] ||= {}
87
+ structure[host][plugin] ||= {}
88
+ structure[host][plugin][instance] ||= {}
89
+ structure[host][plugin][instance][source] ||= {}
90
+ structure[host][plugin][instance][source][:start] ||= start
91
+ structure[host][plugin][instance][source][:finish] ||= finish
92
+ structure[host][plugin][instance][source][:data] ||= metric
79
93
 
80
- structure[data[:host]] ||= {}
81
- structure[data[:host]][data[:plugin]] ||= {}
82
- structure[data[:host]][data[:plugin]][data[:instance]] ||= {}
83
- structure[data[:host]][data[:plugin]][data[:instance]][source] ||= {}
84
- structure[data[:host]][data[:plugin]][data[:instance]][source][:start] ||= data[:start]
85
- structure[data[:host]][data[:plugin]][data[:instance]][source][:finish] ||= data[:finish]
86
- structure[data[:host]][data[:plugin]][data[:instance]][source][:data] ||= metric
87
94
  end
88
95
  end
89
96
 
@@ -5,78 +5,86 @@ function formatSeriesLabel(labels) {
5
5
  metric = labels[3],
6
6
  name;
7
7
 
8
- // Generic label building
9
- name = instance
10
- name = name.replace(plugin, '')
11
- name = name.replace(plugin.split('-')[0], '')
12
- name = name.replace('tcp_connections', '')
13
- name = name.replace('ps_state', '')
14
- name += metric == "value" ? "" : " (" + metric + ")"
15
- name = name.replace(/^[-|_]*/, '')
16
- name = name.trim().replace(/^\((.*)\)$/, '$1')
17
- name = plugin == "irq" ? name.replace(/^/, 'irq ') : ''
18
8
 
9
+ if (plugin == "irq") {
10
+ name = name.replace(/^/, 'irq ')
11
+ }
19
12
  // Plugin specific labeling
20
- if (plugin == "interface") {
21
- name += instance.replace(/^if_(.*)-(.*)/, '$2 $1') + ' (' + metric + ')'
13
+ else if (plugin == "interface") {
14
+ name = instance.replace(/^if_(.*)-(.*)/, '$2 $1') + ' (' + metric + ')'
22
15
  }
23
- if (["processes", "memory"].contains(plugin) || plugin.test(/^cpu-\d+/) ) {
24
- name += instance.split('-')[1]
16
+ else if (["processes", "memory"].contains(plugin) || plugin.test(/^cpu-\d+/) ) {
17
+ name = instance.split('-')[1]
25
18
  }
26
- if (plugin == "swap") {
19
+ else if (plugin == "swap") {
27
20
  if (instance.test(/^swap_io/)) {
28
- name += instance.replace(/^swap_(\w*)-(.*)$/, '$1 $2')
21
+ name = instance.replace(/^swap_(\w*)-(.*)$/, '$1 $2')
29
22
  }
30
23
  if (instance.test(/^swap-/)) {
31
- name += instance.split('-')[1]
24
+ name = instance.split('-')[1]
32
25
  }
33
26
  }
34
- if (plugin == "load") {
35
- name += metric.replace(/^\((.*)\)$/, '$1')
27
+ else if (plugin == "load") {
28
+ name = metric.replace(/^\((.*)\)$/, '$1')
36
29
  }
37
- if (plugin.test(/^disk/)) {
38
- name += instance.replace(/^disk_/, '') + ' (' + metric + ')'
30
+ else if (plugin.test(/^disk/)) {
31
+ name = instance.replace(/^disk_/, '') + ' (' + metric + ')'
39
32
  }
40
- if (["entropy","users"].contains(plugin)) {
41
- name += metric
33
+ else if (["entropy","users"].contains(plugin)) {
34
+ name = metric
42
35
  }
43
- if (plugin == "uptime") {
44
- name += instance
36
+ else if (plugin == "uptime") {
37
+ name = instance
45
38
  }
46
- if (plugin == "ping") {
39
+ else if (plugin == "ping") {
47
40
  if (instance.test(/^ping_/)) {
48
- name += instance.replace(/^ping_(.*)-(.*)$/, '$1 $2')
41
+ name = instance.replace(/^ping_(.*)-(.*)$/, '$1 $2')
49
42
  } else {
50
- name += metric + ' ' + instance.split('-')[1]
43
+ name = metric + ' ' + instance.split('-')[1]
51
44
  }
52
45
  }
53
- if (plugin == "vmem") {
46
+ else if (plugin.test(/^vmem/)) {
54
47
  if (instance.test(/^vmpage_number-/)) {
55
- name += instance.replace(/^vmpage_number-(.*)$/, '$1').replace('_', ' ')
48
+ name = instance.replace(/^vmpage_number-(.*)$/, '$1').replace('_', ' ')
56
49
  }
57
50
  if (instance.test(/^vmpage_io/)) {
58
- name += instance.replace(/^vmpage_io-(.*)$/, '$1 ') + metric
51
+ name = instance.replace(/^vmpage_io-(.*)$/, '$1 ') + metric
59
52
  }
60
53
  if (instance.test(/^vmpage_faults/)) {
61
- name += metric.trim() == "minflt" ? 'minor' : 'major'
54
+ name = metric.trim() == "minflt" ? 'minor' : 'major'
62
55
  name += ' faults'
63
56
  }
57
+ if (instance.test(/^vmpage_action-/)) {
58
+ name = instance.replace(/^vmpage_action-(.*)$/, '$1').replace('_', ' ')
59
+ }
64
60
  }
65
- if (plugin.test(/^tcpconns/)) {
66
- name += instance.split('-')[1].replace('_', ' ')
61
+ else if (plugin.test(/^tcpconns/)) {
62
+ name = instance.split('-')[1].replace('_', ' ')
67
63
  }
68
- if (plugin.test(/^tail/)) {
69
- name += plugin.split('-').slice(1).join('-') + ' '
70
- name += instance.split('-').slice(1).join('-')
64
+ else if (plugin.test(/^tail/)) {
65
+ name = plugin.split('-').slice(1).join('-') + ' '
66
+ name = instance.split('-').slice(1).join('-')
71
67
  }
72
- if (plugin == "apache") {
68
+ else if (plugin == "apache") {
73
69
  var stash = instance.split('_')[1]
74
70
  if (stash.test(/^scoreboard/)) {
75
- name += 'connections: ' + stash.split('-')[1]
71
+ name = 'connections: ' + stash.split('-')[1]
76
72
  } else {
77
- name += stash
73
+ name = stash
78
74
  }
79
-
75
+ }
76
+ else if ( plugin.test(/^curl_json/) ) {
77
+ var stash = instance.split('-')[2];
78
+ var stash = stash.replace(/[-|_]/, ' ');
79
+ name = stash
80
+ }
81
+ else {
82
+ // Generic label building
83
+ name = instance
84
+ name = name.replace(plugin.split('-')[0], '')
85
+ name += metric == "value" ? "" : " (" + metric + ")"
86
+ name = name.replace(/^[-|_]*/, '')
87
+ name = name.trim().replace(/^\((.*)\)$/, '$1')
80
88
  }
81
89
  return name.trim()
82
90
  }
@@ -120,6 +128,12 @@ function formatDate(d) {
120
128
  return datetime.format("%Y-%m-%d %H:%M:%S UTC%T")
121
129
  }
122
130
 
131
+ function formatPluginName(name) {
132
+ if (name.test(/^curl_json/)) {
133
+ name = name.split('-')[1].replace(/(-|_)/, ' ');
134
+ }
135
+ return name
136
+ }
123
137
 
124
138
 
125
139
  /*
@@ -130,24 +144,26 @@ function formatDate(d) {
130
144
  *
131
145
  */
132
146
  var visageBase = new Class({
133
- Implements: [Options, Events],
147
+ Implements: [ Options, Events ],
134
148
  options: {
135
149
  secureJSON: false,
136
150
  httpMethod: 'get',
137
151
  live: false
138
152
  },
139
153
  initialize: function(element, host, plugin, options) {
140
- this.parentElement = element
141
- this.setOptions(options)
142
- this.options.host = host
154
+ this.parentElement = element
155
+ this.options.host = host
143
156
  this.options.plugin = plugin
144
- data = new Hash()
157
+ this.setOptions(options)
158
+
159
+ var data = new Hash()
145
160
  if($chk(this.options.start)) {
146
161
  data.set('start', this.options.start)
147
162
  }
148
163
  if($chk(this.options.finish)) {
149
164
  data.set('finish', this.options.finish)
150
165
  }
166
+
151
167
  this.requestData = data;
152
168
  this.getData(); // calls graphData
153
169
  },
@@ -184,7 +200,13 @@ var visageBase = new Class({
184
200
  this.request.send();
185
201
  },
186
202
  graphName: function() {
187
- name = $chk(this.options.name) ? this.options.name : this.options.plugin
203
+ if ($chk(this.options.name)) {
204
+ var name = this.options.name
205
+ } else {
206
+ var name = [ formatPluginName(this.options.plugin),
207
+ 'on',
208
+ this.options.host ].join(' ')
209
+ }
188
210
  return name
189
211
  },
190
212
  });
@@ -209,7 +231,7 @@ var visageGraph = new Class({
209
231
 
210
232
  if ( $defined(this.chart) ) {
211
233
  this.series.each(function(series, index) {
212
- this.chart.series[index].setData(series.data)
234
+ this.chart.series[index].setData(series.data, true)
213
235
  }, this);
214
236
  } else {
215
237
  this.drawChart()
@@ -223,11 +245,19 @@ var visageGraph = new Class({
223
245
 
224
246
  $each(data[host][plugin], function(instance, iname) {
225
247
  $each(instance, function(metric, mname) {
248
+ var start = metric.start,
249
+ finish = metric.finish,
250
+ interval = (finish - start) / metric.data.length;
251
+
252
+ var data = metric.data.map(function(value, index) {
253
+ var x = start + index * interval,
254
+ y = value;
255
+ return [ x, y ];
256
+ });
257
+
226
258
  var set = {
227
- name: [ host, plugin, iname, mname ],
228
- data: metric.data,
229
- pointStart: metric.start,
230
- pointInterval: (metric.finish - metric.start) / metric.data.length
259
+ name: [ host, plugin, iname, mname ],
260
+ data: data,
231
261
  };
232
262
 
233
263
  series.push(set)
@@ -240,7 +270,7 @@ var visageGraph = new Class({
240
270
  var series = this.series,
241
271
  title = this.graphName(),
242
272
  element = this.parentElement,
243
- ytitle = this.options.plugin
273
+ ytitle = formatPluginName(this.options.plugin),
244
274
  max = 0
245
275
 
246
276
  /* Get the maximum value across all sets.
@@ -406,7 +436,6 @@ var visageGraph = new Class({
406
436
  html: html,
407
437
  value: value,
408
438
  selected: (current ? 'selected' : '')
409
-
410
439
  });
411
440
  select.grab(option)
412
441
  });
@@ -3,7 +3,7 @@
3
3
 
4
4
  (c) 2009-2010 Torstein H�nsi
5
5
 
6
- License: www.highcharts.com/license
6
+ License: GPLv2, as part of Visage
7
7
  */
8
8
  (function(){function R(a,b){a||(a={});for(var c in b)a[c]=b[c];return a}function T(a){return a!==Na&&a!==null}function oa(a,b,c){var d,e="setAttribute",f;if(typeof b=="string")if(T(c))a[e](b,c);else{if(a&&a.getAttribute)f=a.getAttribute(b)}else if(T(b)&&typeof b=="object")for(d in b)a[e](d,b[d]);return f}function pc(a){if(!a||a.constructor!=Array)a=[a];return a}function z(){var a=arguments,b,c;for(b=0;b<a.length;b++){c=a[b];if(T(c))return c}}function qc(a){var b="",c;for(c in a)b+=rc(c)+":"+a[c]+
9
9
  ";";return b}function Oa(a,b){if(Zb)if(b&&b.opacity!==Na)b.filter="alpha(opacity="+b.opacity*100+")";R(a.style,b)}function Ea(a,b,c,d,e){a=ka.createElement(a);b&&R(a,b);e&&Oa(a,{padding:0,border:fb,margin:0});c&&Oa(a,c);d&&d.appendChild(a);return a}function Pc(){var a=va.global.useUTC;$b=a?Date.UTC:function(b,c,d,e,f,g){return(new Date(b,c,z(d,1),z(e,0),z(f,0),z(g,0))).getTime()};sc=a?"getUTCMinutes":"getMinutes";tc=a?"getUTCHours":"getHours";uc=a?"getUTCDay":"getDay";Qb=a?"getUTCDate":"getDate";
@@ -10,10 +10,10 @@
10
10
  window.addEvent('domready', function() {
11
11
  var graph = new visageGraph('#{graph.id}', '#{graph.host}', '#{graph.plugin}', {
12
12
  pluginInstance: '#{graph.instances.join(',')}',
13
- name: '#{graph.plugin} on #{graph.host}',
14
- start: '#{@start}',
15
- #{ "baseurl: '" + ENV['VISAGE_APP_BASE_URL_PATH'].gsub(/^\//, '') + "'," if ENV['VISAGE_APP_BASE_URL_PATH'] }
16
- finish: '#{@finish}'
13
+ //name: '#{graph.plugin} on #{graph.host}',
14
+ start: '#{@start}',
15
+ finish: '#{@finish}',
16
+ #{ "baseurl: '" + ENV['BASE_URL'].gsub(/^\//, '') if ENV['BASE_URL'] }
17
17
  });
18
18
  });
19
19
  - if @profile.graphs.size == 0
data/visage-app.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{visage-app}
8
- s.version = "0.9.0.pre2"
8
+ s.version = "0.9.0"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Lindsay Holmwood"]
12
- s.date = %q{2011-01-24}
12
+ s.date = %q{2011-02-04}
13
13
  s.default_executable = %q{visage-app}
14
14
  s.description = %q{Visage is a web interface for viewing collectd statistics. It also provides a JSON interface onto collectd's RRD data, giving you an easy way to mash up the data.}
15
15
  s.email = %q{lindsay@holmwood.id.au}
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
20
20
  s.files = [
21
21
  ".gitignore",
22
22
  "AUTHORS",
23
+ "Gemfile",
23
24
  "LICENCE",
24
25
  "README.md",
25
26
  "Rakefile",
@@ -73,14 +74,14 @@ Gem::Specification.new do |s|
73
74
  s.homepage = %q{http://visage-app.com/}
74
75
  s.rdoc_options = ["--charset=UTF-8"]
75
76
  s.require_paths = ["lib"]
76
- s.rubygems_version = %q{1.3.6}
77
+ s.rubygems_version = %q{1.3.7}
77
78
  s.summary = %q{a web (interface | service) for viewing collectd statistics}
78
79
 
79
80
  if s.respond_to? :specification_version then
80
81
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
81
82
  s.specification_version = 3
82
83
 
83
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
84
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
84
85
  s.add_runtime_dependency(%q<sinatra>, ["= 1.0"])
85
86
  s.add_runtime_dependency(%q<tilt>, ["= 1.0.1"])
86
87
  s.add_runtime_dependency(%q<haml>, ["= 3.0.13"])
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: visage-app
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: true
4
+ hash: 59
5
+ prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 9
8
9
  - 0
9
- - pre2
10
- version: 0.9.0.pre2
10
+ version: 0.9.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Lindsay Holmwood
@@ -15,16 +15,18 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-24 00:00:00 +11:00
18
+ date: 2011-02-04 00:00:00 +11:00
19
19
  default_executable: visage-app
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: sinatra
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
25
26
  requirements:
26
27
  - - "="
27
28
  - !ruby/object:Gem::Version
29
+ hash: 15
28
30
  segments:
29
31
  - 1
30
32
  - 0
@@ -35,9 +37,11 @@ dependencies:
35
37
  name: tilt
36
38
  prerelease: false
37
39
  requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
38
41
  requirements:
39
42
  - - "="
40
43
  - !ruby/object:Gem::Version
44
+ hash: 21
41
45
  segments:
42
46
  - 1
43
47
  - 0
@@ -49,9 +53,11 @@ dependencies:
49
53
  name: haml
50
54
  prerelease: false
51
55
  requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
52
57
  requirements:
53
58
  - - "="
54
59
  - !ruby/object:Gem::Version
60
+ hash: 29
55
61
  segments:
56
62
  - 3
57
63
  - 0
@@ -63,9 +69,11 @@ dependencies:
63
69
  name: errand
64
70
  prerelease: false
65
71
  requirement: &id004 !ruby/object:Gem::Requirement
72
+ none: false
66
73
  requirements:
67
74
  - - "="
68
75
  - !ruby/object:Gem::Version
76
+ hash: 7
69
77
  segments:
70
78
  - 0
71
79
  - 7
@@ -77,9 +85,11 @@ dependencies:
77
85
  name: yajl-ruby
78
86
  prerelease: false
79
87
  requirement: &id005 !ruby/object:Gem::Requirement
88
+ none: false
80
89
  requirements:
81
90
  - - "="
82
91
  - !ruby/object:Gem::Version
92
+ hash: 15
83
93
  segments:
84
94
  - 0
85
95
  - 7
@@ -98,6 +108,7 @@ extra_rdoc_files:
98
108
  files:
99
109
  - .gitignore
100
110
  - AUTHORS
111
+ - Gemfile
101
112
  - LICENCE
102
113
  - README.md
103
114
  - Rakefile
@@ -157,25 +168,27 @@ rdoc_options:
157
168
  require_paths:
158
169
  - lib
159
170
  required_ruby_version: !ruby/object:Gem::Requirement
171
+ none: false
160
172
  requirements:
161
173
  - - ">="
162
174
  - !ruby/object:Gem::Version
175
+ hash: 3
163
176
  segments:
164
177
  - 0
165
178
  version: "0"
166
179
  required_rubygems_version: !ruby/object:Gem::Requirement
180
+ none: false
167
181
  requirements:
168
- - - ">"
182
+ - - ">="
169
183
  - !ruby/object:Gem::Version
184
+ hash: 3
170
185
  segments:
171
- - 1
172
- - 3
173
- - 1
174
- version: 1.3.1
186
+ - 0
187
+ version: "0"
175
188
  requirements: []
176
189
 
177
190
  rubyforge_project:
178
- rubygems_version: 1.3.6
191
+ rubygems_version: 1.3.7
179
192
  signing_key:
180
193
  specification_version: 3
181
194
  summary: a web (interface | service) for viewing collectd statistics