spoonsix-dognotgod 0.1.9 → 0.1.10

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.
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