spoonsix-dognotgod 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # dog not god: performance monitoring simplified
1
+ # dog not god: server health monitoring simplified
2
2
 
3
- dog not god is a performance monitoring tool for *nix based servers. The focus is on simplicity and on a 100% ruby implementation.
3
+ dog not god is a server health monitoring tool for *nix based servers. The focus is on simplicity and on a 100% ruby implementation.
4
4
 
5
5
  ### Installation
6
6
 
@@ -26,7 +26,7 @@ This will run the client every minute. By default, the server-address is 127.0.0
26
26
 
27
27
  ## License
28
28
 
29
- dog not god: performance monitoring simplified
29
+ dog not god: server health monitoring simplified
30
30
  Copyright (C) 2009 spoonsix - Luis Correa d'Almeida
31
31
 
32
32
  This program is free software; you can redistribute it and/or
@@ -26,6 +26,10 @@ class FileSystem < Sequel::Model
26
26
  available_in_Gb + used_in_Gb
27
27
  end
28
28
 
29
+ def total_space_in_Gb
30
+ size_in_Gb
31
+ end
32
+
29
33
  def used_in_Gb
30
34
  if latest_disk_entry
31
35
  latest_disk_entry.used / 1024 / 1024
@@ -34,6 +38,10 @@ class FileSystem < Sequel::Model
34
38
  end
35
39
  end
36
40
 
41
+ def used_space_in_Gb
42
+ used_in_Gb
43
+ end
44
+
37
45
  def available_in_Gb
38
46
  if latest_disk_entry
39
47
  latest_disk_entry.available / 1024 / 1024
@@ -41,6 +49,24 @@ class FileSystem < Sequel::Model
41
49
  0
42
50
  end
43
51
  end
52
+
53
+ def available_space_in_Gb
54
+ available_in_Gb
55
+ end
56
+
57
+ def available_space_in_percent
58
+ sprintf('%.2f', available_space_in_Gb.to_f / total_space_in_Gb * 100)
59
+ end
60
+
61
+ def status
62
+ if available_space_in_percent.to_i > 30
63
+ STATUS_GREEN
64
+ elsif available_space_in_percent.to_i > 10
65
+ STATUS_YELLOW
66
+ else
67
+ STATUS_RED
68
+ end
69
+ end
44
70
 
45
71
  def disks_5_min_grain(start_time, end_time)
46
72
  disk = DB.fetch("SELECT ROUND(AVG(available)/1024/1024, 1) AS available, ROUND(AVG(used)/1024/1024, 1) AS used, grain_5_min FROM disks WHERE file_system_id = #{self.id} AND grain_5_min >= '#{start_time.to_five_minute_grain_format.to_sql_format}' AND grain_5_min <= '#{end_time.to_five_minute_grain_format.to_sql_format}' GROUP BY grain_5_min;").all
@@ -56,8 +82,8 @@ class FileSystem < Sequel::Model
56
82
  series[0] << five.to_minute_format
57
83
  if disk.size > 0 and disk[0][:grain_5_min].to_minute_format == five.to_minute_format
58
84
  disk_for_this_dim = disk.shift
59
- series[1] << (disk_for_this_dim[:available] + disk_for_this_dim[:used])
60
- series[2] << disk_for_this_dim[:used]
85
+ series[1] << (disk_for_this_dim[:available] + disk_for_this_dim[:used]).to_f
86
+ series[2] << disk_for_this_dim[:used].to_f
61
87
  else
62
88
  series[1] << -1
63
89
  series[2] << -1
@@ -81,8 +107,8 @@ class FileSystem < Sequel::Model
81
107
  series[0] << fifteen.to_minute_format
82
108
  if disk.size > 0 and disk[0][:grain_15_min].to_minute_format == fifteen.to_minute_format
83
109
  disk_for_this_dim = disk.shift
84
- series[1] << (disk_for_this_dim[:available] + disk_for_this_dim[:used])
85
- series[2] << disk_for_this_dim[:used]
110
+ series[1] << (disk_for_this_dim[:available] + disk_for_this_dim[:used]).to_f
111
+ series[2] << disk_for_this_dim[:used].to_f
86
112
  else
87
113
  series[1] << -1
88
114
  series[2] << -1
data/app/models/host.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class Host < Sequel::Model
2
-
2
+
3
3
  one_to_many :loads
4
4
 
5
5
  one_to_many :file_systems
@@ -51,7 +51,7 @@ class Host < Sequel::Model
51
51
  @total += fs.size_in_Gb
52
52
  end
53
53
 
54
- @total
54
+ @total_disk_space_in_Gb ||= @total
55
55
  end
56
56
 
57
57
  def available_disk_space_in_Gb
@@ -60,7 +60,21 @@ class Host < Sequel::Model
60
60
  @available += fs.available_in_Gb
61
61
  end
62
62
 
63
- @available
63
+ @available_disk_space_in_Gb ||= @available
64
+ end
65
+
66
+ def available_disk_space_in_percent
67
+ sprintf('%.2f', available_disk_space_in_Gb.to_f / total_disk_space_in_Gb * 100)
68
+ end
69
+
70
+ def disk_status
71
+ if available_disk_space_in_percent.to_i > 30
72
+ STATUS_GREEN
73
+ elsif available_disk_space_in_percent.to_i > 10
74
+ STATUS_YELLOW
75
+ else
76
+ STATUS_RED
77
+ end
64
78
  end
65
79
 
66
80
 
@@ -119,6 +133,19 @@ class Host < Sequel::Model
119
133
  series
120
134
  end
121
135
 
136
+ def available_memory_in_percent
137
+ sprintf('%.2f', available_memory_in_Mb.to_f / total_memory_in_Mb * 100)
138
+ end
139
+
140
+ def memory_status
141
+ if available_memory_in_percent.to_i > 30
142
+ STATUS_GREEN
143
+ elsif available_memory_in_percent.to_i > 10
144
+ STATUS_YELLOW
145
+ else
146
+ STATUS_RED
147
+ end
148
+ end
122
149
 
123
150
  ####################
124
151
  # Swap
@@ -144,6 +171,20 @@ class Host < Sequel::Model
144
171
  end
145
172
  end
146
173
 
174
+ def available_swap_in_percent
175
+ sprintf('%.2f', available_swap_in_Mb.to_f / total_swap_in_Mb * 100)
176
+ end
177
+
178
+ def swap_status
179
+ if available_swap_in_percent.to_i > 30
180
+ STATUS_GREEN
181
+ elsif available_swap_in_percent.to_i > 10
182
+ STATUS_YELLOW
183
+ else
184
+ STATUS_RED
185
+ end
186
+ end
187
+
147
188
  ####################
148
189
  # Load stats
149
190
  ####################
@@ -162,9 +203,9 @@ class Host < Sequel::Model
162
203
  series[0] << five.to_minute_format
163
204
  if load.size > 0 and load[0][:grain_5_min].to_minute_format == five.to_minute_format
164
205
  load_for_this_dim = load.shift
165
- series[1] << load_for_this_dim[:load_5_min]
166
- series[2] << load_for_this_dim[:load_10_min]
167
- series[3] << load_for_this_dim[:load_15_min]
206
+ series[1] << load_for_this_dim[:load_5_min].to_f
207
+ series[2] << load_for_this_dim[:load_10_min].to_f
208
+ series[3] << load_for_this_dim[:load_15_min].to_f
168
209
  else
169
210
  series[1] << -1
170
211
  series[2] << -1
@@ -200,9 +241,9 @@ class Host < Sequel::Model
200
241
  series[0] << fifteen.to_minute_format
201
242
  if load.size > 0 and load[0][:grain_15_min].to_minute_format == fifteen.to_minute_format
202
243
  load_for_this_dim = load.shift
203
- series[1] << load_for_this_dim[:load_5_min]
204
- series[2] << load_for_this_dim[:load_10_min]
205
- series[3] << load_for_this_dim[:load_15_min]
244
+ series[1] << load_for_this_dim[:load_5_min].to_f
245
+ series[2] << load_for_this_dim[:load_10_min].to_f
246
+ series[3] << load_for_this_dim[:load_15_min].to_f
206
247
  else
207
248
  series[1] << -1
208
249
  series[2] << -1
@@ -227,15 +268,13 @@ class Host < Sequel::Model
227
268
 
228
269
  def status
229
270
  if self.last_contacted_on == nil
230
- 0
231
- elsif Time.now - self.last_contacted_on < 90
232
- 5
233
- elsif Time.now - self.last_contacted_on < 180
234
- 3
235
- elsif Time.now - self.last_contacted_on < 300
236
- 2
271
+ STATUS_RED
272
+ elsif Time.now - self.last_contacted_on < 75
273
+ STATUS_GREEN
274
+ elsif Time.now - self.last_contacted_on < 120
275
+ STATUS_YELLOW
237
276
  else
238
- 1
277
+ STATUS_RED
239
278
  end
240
279
  end
241
280
 
@@ -0,0 +1,8 @@
1
+ /*
2
+ * SimpleModal 1.2.3 - jQuery Plugin
3
+ * http://www.ericmmartin.com/projects/simplemodal/
4
+ * Copyright (c) 2009 Eric Martin
5
+ * Dual licensed under the MIT and GPL licenses
6
+ * Revision: $Id: jquery.simplemodal.js 185 2009-02-09 21:51:12Z emartin24 $
7
+ */
8
+ (function($){var ie6=$.browser.msie&&parseInt($.browser.version)==6&&typeof window['XMLHttpRequest']!="object",ieQuirks=null,w=[];$.modal=function(data,options){return $.modal.impl.init(data,options);};$.modal.close=function(){$.modal.impl.close();};$.fn.modal=function(options){return $.modal.impl.init(this,options);};$.modal.defaults={opacity:50,overlayId:'simplemodal-overlay',overlayCss:{},containerId:'simplemodal-container',containerCss:{},dataCss:{},zIndex:1000,close:true,closeHTML:'<a class="modalCloseImg" title="Close"></a>',closeClass:'simplemodal-close',position:null,persist:false,onOpen:null,onShow:null,onClose:null};$.modal.impl={opts:null,dialog:{},init:function(data,options){if(this.dialog.data){return false;}ieQuirks=$.browser.msie&&!$.boxModel;this.opts=$.extend({},$.modal.defaults,options);this.zIndex=this.opts.zIndex;this.occb=false;if(typeof data=='object'){data=data instanceof jQuery?data:$(data);if(data.parent().parent().size()>0){this.dialog.parentNode=data.parent();if(!this.opts.persist){this.dialog.orig=data.clone(true);}}}else if(typeof data=='string'||typeof data=='number'){data=$('<div/>').html(data);}else{alert('SimpleModal Error: Unsupported data type: '+typeof data);return false;}this.dialog.data=data.addClass('simplemodal-data').css(this.opts.dataCss);data=null;this.create();this.open();if($.isFunction(this.opts.onShow)){this.opts.onShow.apply(this,[this.dialog]);}return this;},create:function(){w=this.getDimensions();if(ie6){this.dialog.iframe=$('<iframe src="javascript:false;"/>').css($.extend(this.opts.iframeCss,{display:'none',opacity:0,position:'fixed',height:w[0],width:w[1],zIndex:this.opts.zIndex,top:0,left:0})).appendTo('body');}this.dialog.overlay=$('<div/>').attr('id',this.opts.overlayId).addClass('simplemodal-overlay').css($.extend(this.opts.overlayCss,{display:'none',opacity:this.opts.opacity/100,height:w[0],width:w[1],position:'fixed',left:0,top:0,zIndex:this.opts.zIndex+1})).appendTo('body');this.dialog.container=$('<div/>').attr('id',this.opts.containerId).addClass('simplemodal-container').css($.extend(this.opts.containerCss,{display:'none',position:'fixed',zIndex:this.opts.zIndex+2})).append(this.opts.close?$(this.opts.closeHTML).addClass(this.opts.closeClass):'').appendTo('body');this.setPosition();if(ie6||ieQuirks){this.fixIE();}this.dialog.container.append(this.dialog.data.hide());},bindEvents:function(){var self=this;$('.'+this.opts.closeClass).bind('click.simplemodal',function(e){e.preventDefault();self.close();});$(window).bind('resize.simplemodal',function(){w=self.getDimensions();self.setPosition();if(ie6||ieQuirks){self.fixIE();}else{self.dialog.iframe&&self.dialog.iframe.css({height:w[0],width:w[1]});self.dialog.overlay.css({height:w[0],width:w[1]});}});},unbindEvents:function(){$('.'+this.opts.closeClass).unbind('click.simplemodal');$(window).unbind('resize.simplemodal');},fixIE:function(){var p=this.opts.position;$.each([this.dialog.iframe||null,this.dialog.overlay,this.dialog.container],function(i,el){if(el){var bch='document.body.clientHeight',bcw='document.body.clientWidth',bsh='document.body.scrollHeight',bsl='document.body.scrollLeft',bst='document.body.scrollTop',bsw='document.body.scrollWidth',ch='document.documentElement.clientHeight',cw='document.documentElement.clientWidth',sl='document.documentElement.scrollLeft',st='document.documentElement.scrollTop',s=el[0].style;s.position='absolute';if(i<2){s.removeExpression('height');s.removeExpression('width');s.setExpression('height',''+bsh+' > '+bch+' ? '+bsh+' : '+bch+' + "px"');s.setExpression('width',''+bsw+' > '+bcw+' ? '+bsw+' : '+bcw+' + "px"');}else{var te,le;if(p&&p.constructor==Array){var top=p[0]?typeof p[0]=='number'?p[0].toString():p[0].replace(/px/,''):el.css('top').replace(/px/,'');te=top.indexOf('%')==-1?top+' + (t = '+st+' ? '+st+' : '+bst+') + "px"':parseInt(top.replace(/%/,''))+' * (('+ch+' || '+bch+') / 100) + (t = '+st+' ? '+st+' : '+bst+') + "px"';if(p[1]){var left=typeof p[1]=='number'?p[1].toString():p[1].replace(/px/,'');le=left.indexOf('%')==-1?left+' + (t = '+sl+' ? '+sl+' : '+bsl+') + "px"':parseInt(left.replace(/%/,''))+' * (('+cw+' || '+bcw+') / 100) + (t = '+sl+' ? '+sl+' : '+bsl+') + "px"';}}else{te='('+ch+' || '+bch+') / 2 - (this.offsetHeight / 2) + (t = '+st+' ? '+st+' : '+bst+') + "px"';le='('+cw+' || '+bcw+') / 2 - (this.offsetWidth / 2) + (t = '+sl+' ? '+sl+' : '+bsl+') + "px"';}s.removeExpression('top');s.removeExpression('left');s.setExpression('top',te);s.setExpression('left',le);}}});},getDimensions:function(){var el=$(window);var h=$.browser.opera&&$.browser.version>'9.5'&&$.fn.jquery<='1.2.6'?document.documentElement['clientHeight']:el.height();return[h,el.width()];},setPosition:function(){var top,left,hCenter=(w[0]/2)-((this.dialog.container.height()||this.dialog.data.height())/2),vCenter=(w[1]/2)-((this.dialog.container.width()||this.dialog.data.width())/2);if(this.opts.position&&this.opts.position.constructor==Array){top=this.opts.position[0]||hCenter;left=this.opts.position[1]||vCenter;}else{top=hCenter;left=vCenter;}this.dialog.container.css({left:left,top:top});},open:function(){this.dialog.iframe&&this.dialog.iframe.show();if($.isFunction(this.opts.onOpen)){this.opts.onOpen.apply(this,[this.dialog]);}else{this.dialog.overlay.show();this.dialog.container.show();this.dialog.data.show();}this.bindEvents();},close:function(){if(!this.dialog.data){return false;}if($.isFunction(this.opts.onClose)&&!this.occb){this.occb=true;this.opts.onClose.apply(this,[this.dialog]);}else{if(this.dialog.parentNode){if(this.opts.persist){this.dialog.data.hide().appendTo(this.dialog.parentNode);}else{this.dialog.data.remove();this.dialog.orig.appendTo(this.dialog.parentNode);}}else{this.dialog.data.remove();}this.dialog.container.remove();this.dialog.overlay.remove();this.dialog.iframe&&this.dialog.iframe.remove();this.dialog={};}this.unbindEvents();}};})(jQuery);
data/server.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'rubygems'
2
2
  require 'sinatra'
3
- # require 'ruby-prof'
4
3
 
5
4
  configure do
6
5
  DB_DIR = "#{ENV['HOME']}/.dognotgod"
@@ -19,6 +18,11 @@ configure do
19
18
  require 'load'
20
19
  require 'disk'
21
20
  require 'memory'
21
+
22
+ STATUS_GREEN = 1
23
+ STATUS_YELLOW = 2
24
+ STATUS_RED = 3
25
+
22
26
  end
23
27
 
24
28
  error do
@@ -43,11 +47,11 @@ helpers do
43
47
  end
44
48
 
45
49
  def get_fs_or_create_if_not_exist(host_id, fs_name, mounted_on)
46
- fs = DB[:file_systems].filter(:name => fs_name, :mounted_on => mounted_on).first
50
+ fs = DB[:file_systems].filter(:name => fs_name, :host_id => host_id, :mounted_on => mounted_on).first
47
51
 
48
52
  unless fs
49
53
  DB[:file_systems] << {:name => fs_name, :mounted_on => mounted_on, :host_id => host_id}
50
- fs = DB[:file_systems].filter(:name => fs_name, :mounted_on => mounted_on).first
54
+ fs = DB[:file_systems].filter(:name => fs_name, :host_id => host_id, :mounted_on => mounted_on).first
51
55
  end
52
56
  fs
53
57
  end
@@ -60,21 +64,25 @@ get '/stylesheets/style.css' do
60
64
  end
61
65
 
62
66
  get "/" do
63
- # result = RubyProf.profile do
64
-
65
67
  @hosts = Host.order(:hostname).all
66
-
68
+
67
69
  @end_now = Time.now.utc.to_fifteen_minute_grain_format
68
70
  @start_24h_ago = @end_now - (60*60*24)
69
71
  @start_6h_ago = @end_now - (60*60*6)
70
72
 
71
73
  haml :main
72
- # end
73
- # Print a graph profile to text
74
- # printer = RubyProf::GraphPrinter.new(result)
75
- # printer.print(File.new("tmp/profile.log", "w"), 0)
76
74
  end
77
75
 
76
+ get "/hosts/:id" do
77
+ @host = Host.find(:id => params[:id])
78
+
79
+ @end_now = Time.now.utc.to_fifteen_minute_grain_format
80
+ @start_24h_ago = @end_now - (60*60*24)
81
+ @start_6h_ago = @end_now - (60*60*6)
82
+
83
+ haml :host, :layout => false
84
+ end
85
+
78
86
  post "/load_stats" do
79
87
 
80
88
  begin
data/views/host.haml ADDED
@@ -0,0 +1,43 @@
1
+ - series_6h = @host.loads_15_min_grain(@start_6h_ago, @end_now)
2
+ - params_for_6h = "cht=ls&chs=300x100&chco=FF0000,00FF00,0000FF&chm=r,DDDDDD,0,0.25,0.26&chxt=x,y&chxr=1,0,4,1&chds=0,4&chl=&chd=t:#{series_6h[1].join(",")}|#{series_6h[2].join(",")}|#{series_6h[3].join(",")}"
3
+ - series_24h = @host.loads_15_min_grain(@start_24h_ago, @end_now)
4
+ - params_for_24h = "cht=lc&chs=300x100&chco=FF0000,00FF00,0000FF&chm=r,DDDDDD,0,0.25,0.26&chxt=x,y&chxr=1,0,4,1&chds=0,4&chl=&chd=t:#{series_24h[1].join(",")}|#{series_24h[2].join(",")}|#{series_24h[3].join(",")}"
5
+ - mem_series_24h = @host.memory_stats_15_min_grain(@start_24h_ago, @end_now)
6
+ - mem_params_for_24h = "cht=lc&chs=300x100&chco=FF0000,00FF00,0000FF&chm=r,DDDDDD,0,0.95,0.96&chxr=1,0,#{@host.total_memory_in_Mb * 1.05}&chxt=x,y&chl=&chds=0,#{@host.total_memory_in_Mb * 1.05}&chd=t:#{mem_series_24h[2].join(",")}|#{mem_series_24h[4].join(",")}"
7
+ - swap_params_for_24h = "cht=lc&chs=300x100&chco=FF0000,00FF00,0000FF&chm=r,DDDDDD,0,0.95,0.96&chxr=1,0,#{@host.total_swap_in_Mb * 1.05}&chxt=x,y&chl=&chds=0,#{@host.total_swap_in_Mb * 1.05}&chd=t:#{mem_series_24h[4].join(",")}"
8
+ .section
9
+ %h3=@host.hostname
10
+ %p== Last heard from on #{@host.last_contacted_on}
11
+
12
+ %table
13
+ %tr
14
+ %td{:style=> "vertical-align: top"}
15
+ %h4.load Load averages for the last 24 hours
16
+ %p{:style => "float:right;"}== 5, 10 and 15 min averages
17
+ %br
18
+ %img{ :src => "http://chart.apis.google.com/chart?#{params_for_24h}"}
19
+ %td
20
+ %h4.memory Memory & Swap
21
+ %p{:style => "float:right;"}== Total memory is #{@host.total_memory_in_Mb}Mb
22
+ %br
23
+ %img{ :src => "http://chart.apis.google.com/chart?#{mem_params_for_24h}"}
24
+ %tr
25
+ %td{:colspan => 2}
26
+ %h4.disk Disk space & File system info
27
+ %table.detail-table{:cellspacing => 0, :cellpading => 0}
28
+ %tr
29
+ %th
30
+ %th File system
31
+ %th Disk space
32
+ %th Percentage free disk space
33
+ - @host.file_systems.each do |fs|
34
+ %tr
35
+ %td=fs.mounted_on
36
+ %td=fs.name
37
+ - if fs.is_dev? and fs.size_in_Gb > 0
38
+ - series_24h = fs.disks_15_min_grain(@start_24h_ago, @end_now)
39
+ - params_for_24h = "cht=ls&chs=75x20&chco=999999&chds=0,#{series_24h[2].max.ceil}&chd=t:#{series_24h[2].join(",")}"
40
+ %td.space{:style => "padding-left: 100px; background: url(http://chart.apis.google.com/chart?#{params_for_24h}) no-repeat 5px 12px"}="#{fs.available_space_in_Gb} Gb free / #{fs.total_space_in_Gb} Gb total"
41
+ %td
42
+ %span.bar{:class => "status#{fs.status}", :style => "width: #{fs.available_space_in_percent.to_i}%"}="#{fs.available_space_in_percent}%" if fs.total_space_in_Gb > 0
43
+
data/views/layout.haml CHANGED
@@ -3,12 +3,15 @@
3
3
  %head
4
4
  %title dog not god
5
5
  %link{:rel=>'stylesheet', :href=>'/stylesheets/style.css', :type => "text/css"}
6
+ %script{:src => "http://www.google.com/jsapi"}
7
+ %script google.load("jquery", "1");
8
+ %script{:src => "/javascripts/jquery.simplemodal-1.2.3.min.js"}
6
9
 
7
10
 
8
11
  %body
9
12
  #header
10
13
  #content
11
- %h1 dog not god
14
+ %h1="dog not god <br/><span style='font-size: 0.4em'>server health monitoring simplified</span>"
12
15
  =yield
13
16
  #footer
14
17
  %p
data/views/main.haml CHANGED
@@ -1,64 +1,28 @@
1
1
  %h2 Summary
2
+
2
3
  #summary-section
3
- %table{:class => "summary-table", :cellspacing => 0, :cellpading => 0}
4
+ %table.summary-table{:cellspacing => 0, :cellpading => 0}
4
5
  %tr
5
6
  %th Host
6
7
  %th Last heartbeat
7
8
  %th 5 min average
8
- %th 10 min average
9
- %th 15 min average
9
+ %th 10 min
10
+ %th 15 min
10
11
  %th Free disk space
11
12
  %th Free memory
12
13
  %th Free swap space
13
- -for host in @hosts
14
- %tr{:class => "level#{host.status}"}
15
- %td= host.hostname
16
- %td= "#{host.distance_to_last_heartbeat_in_seconds.to_i} seconds ago" unless host.status == 0
17
- %td= host.load_5_min
18
- %td= host.load_10_min
19
- %td= host.load_15_min
20
- %td= "#{host.available_disk_space_in_Gb}Gb out of #{host.total_disk_space_in_Gb}Gb (#{sprintf('%.2f', (host.available_disk_space_in_Gb.to_f / host.total_disk_space_in_Gb) * 100)}%)" if host.total_disk_space_in_Gb > 0
21
- %td= "#{host.available_memory_in_Mb}Mb out of #{host.total_memory_in_Mb}Mb (#{sprintf('%.2f', (host.available_memory_in_Mb.to_f / host.total_memory_in_Mb) * 100)}%)" if host.total_memory_in_Mb > 0
22
- %td= "#{host.available_swap_in_Mb}Mb out of #{host.total_swap_in_Mb}Mb (#{sprintf('%.2f', (host.available_swap_in_Mb.to_f / host.total_swap_in_Mb) * 100)}%)" if host.total_swap_in_Mb > 0
23
-
24
- %table{:id => "section-table"}
25
- %tr
26
14
  -for host in @hosts
27
15
  - series_6h = host.loads_5_min_grain(@start_6h_ago, @end_now)
28
- - params_for_6h = "cht=lc&chs=350x120&chco=FF0000,00FF00,0000FF&chm=r,DDDDDD,0,0.2,0.21&chxt=x,y&chxr=1,0,4,1&chds=0,4&chl=&chd=t:#{series_6h[1].join(",")}|#{series_6h[2].join(",")}|#{series_6h[3].join(",")}"
29
- - series_24h = host.loads_15_min_grain(@start_24h_ago, @end_now)
30
- - params_for_24h = "cht=lc&chs=350x120&chco=FF0000,00FF00,0000FF&chm=r,DDDDDD,0,0.2,0.21&chxt=x,y&chxr=1,0,4,1&chds=0,4&chl=&chd=t:#{series_24h[1].join(",")}|#{series_24h[2].join(",")}|#{series_24h[3].join(",")}"
31
- - mem_series_24h = host.memory_stats_15_min_grain(@start_24h_ago, @end_now)
32
- - mem_params_for_24h = "cht=lc&chs=350x120&chco=FF0000,00FF00,0000FF&chm=r,DDDDDD,0,0.95,0.96&chxr=1,0,#{host.total_memory_in_Mb * 1.05}&chxt=x,y&chl=&chds=0,#{host.total_memory_in_Mb * 1.05}&chd=t:#{mem_series_24h[2].join(",")}"
33
- - swap_params_for_24h = "cht=lc&chs=350x120&chco=FF0000,00FF00,0000FF&chm=r,DDDDDD,0,0.95,0.96&chxr=1,0,#{host.total_swap_in_Mb * 1.05}&chxt=x,y&chl=&chds=0,#{host.total_swap_in_Mb * 1.05}&chd=t:#{mem_series_24h[4].join(",")}"
34
- %td
35
- .section
36
- %h2=host.hostname
37
- %p== Last heard from on #{host.last_contacted_on}
38
-
39
- %h4 Load averages for the last 24 hours
40
- %img{ :src => "http://chart.apis.google.com/chart?#{params_for_24h}"}
41
-
42
- %h4 Load averages for the last 6 hours
43
- %img{ :src => "http://chart.apis.google.com/chart?#{params_for_6h}"}
44
-
45
- %h4 Memory
46
- %p{:style => "float:right;"}== Total memory is #{host.total_memory_in_Mb}Mb
47
- %br
48
- %img{ :src => "http://chart.apis.google.com/chart?#{mem_params_for_24h}"}
49
-
50
- %h4 Swap
51
- %p{:style => "float:right;"}== Total memory is #{host.total_swap_in_Mb}Mb
52
- %br
53
- %img{ :src => "http://chart.apis.google.com/chart?#{swap_params_for_24h}"}
54
-
55
- - host.file_systems.each do |fs|
56
- - if fs.is_dev? and fs.size_in_Gb > 0
57
- - series_24h = fs.disks_15_min_grain(@start_24h_ago, @end_now)
58
- - params_for_24h = "cht=lc&chs=350x120&chco=FF0000,00FF00,0000FF&chxr=1,0,#{fs.size_in_Gb * 1.05}&chxt=x,y&chds=0,#{fs.size_in_Gb * 1.05}&chl=&chd=t:#{series_24h[2].join(",")}"
59
- %h4== #{fs.mounted_on} on #{fs.name}
60
- %p{:style => "float:right;"}== Device size is #{fs.size_in_Gb}Gb
61
- %br
62
- %img{ :src => "http://chart.apis.google.com/chart?#{params_for_24h}"}
63
-
64
-
16
+ - params_for_6h = "cht=ls&chs=75x20&chco=999999&chds=0,#{series_6h[1].max}&chd=t:#{series_6h[1].join(",")}"
17
+ %tr.link{:onclick => "jQuery.get('/hosts/#{host.id}', {}, function(data) {jQuery.modal(data, {})})"}
18
+ %td{:class => "status#{host.status}"}= host.hostname
19
+ %td.distance-in-secs{:class => "status#{host.status}"}= "#{host.distance_to_last_heartbeat_in_seconds.to_i} seconds ago" unless host.status == 0
20
+ %td.load{:style => "background: url(http://chart.apis.google.com/chart?#{params_for_6h}) no-repeat 5px 12px"}=host.load_5_min
21
+ %td.load= host.load_10_min
22
+ %td.load= host.load_15_min
23
+ %td
24
+ %span.bar{:class => "status#{host.disk_status}", :style => "width: #{host.available_disk_space_in_percent.to_i}%"}="#{host.available_disk_space_in_percent}%" if host.total_disk_space_in_Gb > 0
25
+ %td
26
+ %span.bar{:class => "status#{host.memory_status}", :style => "width: #{host.available_memory_in_percent.to_i}%"}="#{host.available_memory_in_percent}%" if host.total_memory_in_Mb > 0
27
+ %td
28
+ %span.bar{:class => "status#{host.swap_status}", :style => "width: #{host.available_swap_in_percent.to_i}"}= "#{host.available_swap_in_percent}%" if host.total_swap_in_Mb > 0
data/views/style.sass CHANGED
@@ -1,7 +1,7 @@
1
1
  body
2
2
  :margin 0
3
3
  :padding 0
4
- :font-family Courier
4
+ :font-family Georgia, serif
5
5
  :font-size 1.0em
6
6
 
7
7
  br
@@ -10,56 +10,94 @@ br
10
10
  a, a:visited
11
11
  :color #AAA
12
12
 
13
+ //************************************************************
14
+ // headers
15
+
13
16
  h1, h2, h3, h4, h5, h6
14
- :font-family Georgia, serif
15
17
  :font-weight normal
16
18
  :margin 0px 10px 10px 0px
17
19
  :white-space nowrap
20
+ :clear both
18
21
 
19
22
  h1
20
23
  :padding-bottom 10px
21
- :margin-bottom 30px
24
+ :margin 0px 0px 30px 0px
22
25
  :border-bottom double #DDDDDD
23
26
 
24
27
  h2
25
- :text-decoration underline
28
+ :background url(/images/blossom/48x48/world_globe.png) no-repeat 5px 10px
29
+ :padding 20px 10px 18px 60px
30
+ :margin 3px 0px 30px 0px
31
+ :border 1px solid #DDD
32
+ :border-bottom 1px solid #555
33
+ :background-color #EFEFEF
34
+
35
+
36
+ h3
37
+ :background url(/images/blossom/48x48/user.png) no-repeat 5px 7px
38
+ :padding 20px 10px 18px 60px
39
+ :margin 3px 0px 3px 0px
40
+ :border-top 1px solid #DDD
41
+ :border-bottom 1px solid #555
42
+ :background-color #EFEFEF
26
43
 
27
44
  h4
28
- :margin 20px 10px 10px 0px
29
- :padding 5px
45
+ :padding 10px 0px 10px 40px
46
+ :margin 2px 10px 3px 20px
47
+ :border-top 1px solid #DDD
48
+ :border-left 1px solid #DDD
49
+ :border-right 1px solid #DDD
50
+ :border-bottom 1px solid #555
51
+
52
+ h4.load
53
+ :background url(/images/blossom/32x32/process.png) no-repeat 5px 3px
54
+ :background-color #EFEFEF
55
+
56
+ h4.memory, h4.swap
57
+ :background url(/images/blossom/32x32/chart.png) no-repeat
30
58
  :background-color #EFEFEF
59
+
60
+ h4.disk
61
+ :background url(/images/blossom/32x32/hard_disk.png) no-repeat
62
+ :background-color #EFEFEF
63
+
31
64
 
32
65
  #header
33
66
  :height 10px
34
67
  :background-color #EFEFEF
68
+ :border-bottom 1px solid #DDD
35
69
  :margin-bottom 20px
36
70
 
37
71
  #content
38
72
  :margin 0px 30px 10px 20px
73
+
74
+ #content-lightbox
75
+ :padding 10px 50px
76
+ :margin 10px auto
39
77
 
40
78
  #summary-section
41
- :font-size 0.7em
79
+ :font-size 0.8em
42
80
  :margin-bottom 30px
43
81
  :padding-bottom 20px
44
82
  :border-bottom 1px solid #DDD
45
83
 
84
+
85
+ //************************************************************
46
86
  // summary-table
47
87
 
48
88
  .summary-table
49
89
  :border-top 1px solid #DDD
50
90
  :border-left 1px solid #DDD
51
-
52
- .summary-table tr.level4, .summary-table tr.level5
53
- :background-color #99FF99
91
+ :width 100%
54
92
 
55
- .summary-table tr.level3
56
- :background-color #999933
93
+ .summary-table tr
94
+ :height 35px
57
95
 
58
- .summary-table tr.level1, .summary-table tr.level2
59
- :background-color #DD3333
96
+ .summary-table tr.link
97
+ :cursor pointer
60
98
 
61
- .summary-table tr.level0
62
- :background-color #EFEFEF
99
+ .summary-table tr.link:hover
100
+ :background-color #FFFFEF
63
101
 
64
102
  .summary-table th, #summary-table td
65
103
  :border-bottom 1px solid #DDD
@@ -73,32 +111,196 @@ h4
73
111
  .summary-table td
74
112
  :padding-left 5px
75
113
  :padding-right 5px
114
+ :border-bottom 1px solid #DDD
115
+ :border-right 1px solid #DDD
116
+
117
+ .summary-table td.status3
118
+ :background url(/images/coquette/24x24/red_button.png) no-repeat 8px 5px
119
+ :padding 0px 0px 0px 40px
120
+ :margin 0px 0px 0px 5px
121
+
122
+ .summary-table td.status2
123
+ :background url(/images/coquette/24x24/yellow_button.png) no-repeat 8px 5px
124
+ :padding 0px 0px 0px 40px
125
+ :margin 0px 0px 0px 5px
126
+
127
+ .summary-table td.status1
128
+ :background url(/images/coquette/24x24/green_button.png) no-repeat 8px 5px
129
+ :padding 0px 0px 0px 40px
130
+ :margin 0px 0px 0px 5px
131
+
132
+ .summary-table td.distance-in-secs, .summary-table td.load, .summary-table td.free-disk-space, .summary-table td.free-memory, .summary-table td.swap-space
133
+ :text-align right
134
+ :padding-right 5px
135
+
136
+ .summary-table td.distance-in-secs.status1
137
+ :background url(/images/coquette/16x16/green_button.png) no-repeat 10px 11px
138
+
139
+ .summary-table td.distance-in-secs.status2
140
+ :background url(/images/coquette/16x16/yellow_button.png) no-repeat 10px 11px
141
+
142
+ .summary-table td.distance-in-secs.status3
143
+ :background url(/images/coquette/16x16/red_button.png) no-repeat 10px 11px
144
+
145
+
146
+ .summary-table span.bar
147
+ :display block
148
+ :position relative
149
+ :text-align center
150
+ :color #000
151
+ :height 1.7em
152
+ :line-height 1.5em
153
+ :font-size 0.9em
154
+
155
+ .summary-table span.status1
156
+ :background-color #99DD00
157
+
158
+ .summary-table span.status2
159
+ :background-color #FFAA00
160
+
161
+ .summary-table span.status3
162
+ :background-color #CC0000
163
+
164
+
165
+ .summary-table img.sparkline
166
+ :padding-top 5px
167
+
168
+
169
+
170
+ //************************************************************
171
+ // detail-table
172
+
173
+ .detail-table
174
+ :border-top 1px solid #DDD
175
+ :border-left 1px solid #DDD
176
+ :font-size 0.7em
177
+ :margin 20px 20px 0px 20px
178
+ :width 100%
179
+
180
+ .detail-table tr
181
+ :height 25px
182
+
183
+ .detail-table th, #summary-table td
184
+ :border-bottom 1px solid #DDD
185
+ :border-right 1px solid #DDD
186
+
187
+ .detail-table th
188
+ :background-color #EFEFEF
189
+ :padding-left 15px
190
+ :padding-right 15px
191
+
192
+ .detail-table td
193
+ :padding-left 5px
194
+ :padding-right 5px
195
+ :border-bottom 1px solid #DDD
196
+ :border-right 1px solid #DDD
197
+
198
+ .detail-table td.status3
199
+ :background url(/images/coquette/24x24/red_button.png) no-repeat 8px 5px
200
+ :padding 0px 0px 0px 40px
201
+ :margin 0px 0px 0px 5px
202
+
203
+ .detail-table td.status2
204
+ :background url(/images/coquette/24x24/yellow_button.png) no-repeat 8px 5px
205
+ :padding 0px 0px 0px 40px
206
+ :margin 0px 0px 0px 5px
207
+
208
+ .detail-table td.status1
209
+ :background url(/images/coquette/24x24/green_button.png) no-repeat 8px 5px
210
+ :padding 0px 0px 0px 40px
211
+ :margin 0px 0px 0px 5px
212
+
213
+ .detail-table td.space
214
+ :text-align right
215
+ :padding-right 5px
216
+
217
+ .detail-table span.bar
218
+ :display block
219
+ :position relative
220
+ :text-align center
221
+ :color #000
222
+ :height 1.7em
223
+ :line-height 1.5em
224
+ :font-size 0.9em
225
+
226
+ .detail-table span.status1
227
+ :background-color #99DD00
228
+
229
+ .detail-table span.status2
230
+ :background-color #FFAA00
231
+
232
+ .detail-table span.status3
233
+ :background-color #CC0000
234
+
76
235
 
236
+ .detail-table img.sparkline
237
+ :padding-top 5px
238
+
239
+
240
+ //************************************************************
241
+ // section-table
77
242
 
78
243
  #section-table
79
244
  :border 0px
80
245
 
81
246
  #section-table td
82
247
  :vertical-align top
83
-
248
+ :padding-right 20px
249
+
84
250
  .section
251
+ :padding 0px
252
+ :margin 0px
85
253
  :margin-bottom 20px
86
- :margin-left 20px
87
- :border-right 1px solid #DDD
254
+ :width 100%
88
255
 
89
- p
90
- :font-size 0.7em
91
- :margin 0px
92
- :padding 0px
93
- :margin-right 10px
256
+ .section p
257
+ :padding 0px 15px 10px 0px
258
+ :margin 0px 0px 20px 0px
259
+ :color #333
260
+ :font-size 0.6em
261
+ :float right
262
+
263
+ .section img
264
+ :margin 10px 40px 0px 30px
265
+
266
+
267
+ //************************************************************
268
+ // footer
94
269
 
95
270
  #footer
96
271
  :margin-top 20px
97
272
  :clear both
98
273
  :padding 10px
99
- :color #AAA
100
- :text-align left
101
- :font-family sans-serif
274
+ :color #666
102
275
  :text-align center
276
+ :background-color #EFEFEF
277
+ :border-top 1px solid #DDD
278
+ :font-size 0.8em
279
+
280
+ #footer a
281
+ :color #666
282
+
283
+
284
+ //************************************************************
285
+ // lightbox
286
+
287
+ #simplemodal-overlay
288
+ :background-color #000
289
+ :cursor wait
103
290
 
291
+ #simplemodal-container
292
+ :height 550px
293
+ :width 800px
294
+ :background-color #FFF
295
+ :border 5px solid #666
104
296
 
297
+ #simplemodal-container a.modalCloseImg
298
+ :background url(/images/blossom/32x32/delete_item.png) no-repeat
299
+ :width 32px
300
+ :height 32px
301
+ :display inline
302
+ :z-index 3200
303
+ :position absolute
304
+ :top -14px
305
+ :right -18px
306
+ :cursor pointer
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spoonsix-dognotgod
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luis Correa d'Almeida
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-05 00:00:00 -08:00
12
+ date: 2009-03-07 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -72,7 +72,7 @@ dependencies:
72
72
  - !ruby/object:Gem::Version
73
73
  version: "0.9"
74
74
  version:
75
- description: dog not god is a performance monitoring tool.
75
+ description: dog not god is a server health monitoring tool.
76
76
  email: luis.ca@gmail.com
77
77
  executables:
78
78
  - dognotgod
@@ -82,6 +82,7 @@ extensions: []
82
82
  extra_rdoc_files: []
83
83
 
84
84
  files:
85
+ - app/models
85
86
  - app/models/disk.rb
86
87
  - app/models/file_system.rb
87
88
  - app/models/host.rb
@@ -91,6 +92,7 @@ files:
91
92
  - lib/client_commands.rb
92
93
  - config.ru
93
94
  - README.md
95
+ - views/host.haml
94
96
  - views/layout.haml
95
97
  - views/main.haml
96
98
  - views/style.sass
@@ -99,6 +101,7 @@ files:
99
101
  - client.rb
100
102
  - bin/dognotgod
101
103
  - bin/dognotgod-client
104
+ - public/javascripts/jquery.simplemodal-1.2.3.min.js
102
105
  has_rdoc: false
103
106
  homepage: http://github.com/spoonsix/dognotgod
104
107
  post_install_message:
@@ -124,6 +127,6 @@ rubyforge_project:
124
127
  rubygems_version: 1.2.0
125
128
  signing_key:
126
129
  specification_version: 2
127
- summary: dog not god is a performance monitoring tool.
130
+ summary: dog not god is a server health monitoring tool.
128
131
  test_files: []
129
132