spoonsix-dognotgod 0.1.5 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -20,7 +20,7 @@ This will kick off a thin server on port 4567. It will also create the folder ~/
20
20
  The client sits on the target machine - the machine to be monitored - captures performance data and sends it to the server. Note that this works on the machine acting as the server as well.
21
21
 
22
22
  crontab -e
23
- */1 * * * * dognotgod-client -a server-address -p port >> /dev/null 2>&1
23
+ */1 * * * * /path/to/dognotgod-client -a server-address -p port >> /dev/null 2>&1
24
24
 
25
25
  This will run the client every minute. By default, the server-address is 127.0.0.1 and the port is 4567.
26
26
 
@@ -3,6 +3,10 @@ class FileSystem < Sequel::Model
3
3
  many_to_one :hosts
4
4
  one_to_many :disks
5
5
 
6
+ def latest_disk_entry
7
+ @latest_disk_entry ||= self.disks_dataset.order(:created_at).last
8
+ end
9
+
6
10
  unless table_exists?
7
11
  set_schema do
8
12
  primary_key :id
@@ -19,27 +23,20 @@ class FileSystem < Sequel::Model
19
23
  end
20
24
 
21
25
  def size_in_Gb
22
- last_entry = DB[:disks].filter(:file_system_id => self.id).reverse_order(:created_at).last
23
- if last_entry
24
- (last_entry[:available].to_i + last_entry[:used].to_i) / 1024 / 1024
25
- else
26
- 0
27
- end
26
+ available_in_Gb + used_in_Gb
28
27
  end
29
28
 
30
29
  def used_in_Gb
31
- last_entry = DB[:disks].filter(:file_system_id => self.id).reverse_order(:created_at).last
32
- if last_entry
33
- last_entry[:used] / 1024 / 1024
30
+ if latest_disk_entry
31
+ latest_disk_entry.used / 1024 / 1024
34
32
  else
35
33
  0
36
34
  end
37
35
  end
38
36
 
39
37
  def available_in_Gb
40
- last_entry = DB[:disks].filter(:file_system_id => self.id).reverse_order(:created_at).last
41
- if last_entry
42
- last_entry[:available] / 1024 / 1024
38
+ if latest_disk_entry
39
+ latest_disk_entry.available / 1024 / 1024
43
40
  else
44
41
  0
45
42
  end
data/app/models/host.rb CHANGED
@@ -1,8 +1,18 @@
1
1
  class Host < Sequel::Model
2
2
 
3
3
  one_to_many :loads
4
+
4
5
  one_to_many :file_systems
5
6
  one_to_many :memories
7
+
8
+ def latest_load_entry
9
+ @latest_load_entry ||= self.loads_dataset.order(:created_at).last
10
+ end
11
+
12
+ def latest_memory_entry
13
+ @latest_memory_entry ||= self.memories_dataset.order(:created_at).last
14
+ end
15
+
6
16
 
7
17
  unless table_exists?
8
18
  set_schema do
@@ -19,12 +29,16 @@ class Host < Sequel::Model
19
29
 
20
30
  # Timestamp of last entry in 'loads' table for this host
21
31
  def last_contacted_on
22
- self.loads.last.created_at if self.loads.last
32
+ self.latest_load_entry.created_at if self.latest_load_entry
23
33
  end
24
34
 
25
35
  # Seconds to timestamp of last entry in 'loads' table for this host
26
36
  def distance_to_last_heartbeat_in_seconds
27
- (Time.now - self.loads.last.created_at) if self.loads.last
37
+ Time.now - last_contacted_on if last_contacted_on
38
+ end
39
+
40
+ def loads_last
41
+
28
42
  end
29
43
 
30
44
 
@@ -55,27 +69,20 @@ class Host < Sequel::Model
55
69
  ####################
56
70
 
57
71
  def total_memory_in_Mb
58
- last_entry = DB[:memories].filter(:host_id => self.id).reverse_order(:created_at).last
59
- if last_entry
60
- (last_entry[:mem_available] + last_entry[:mem_used]) / 1024
61
- else
62
- 0
63
- end
72
+ available_memory_in_Mb + used_memory_in_Mb
64
73
  end
65
74
 
66
75
  def available_memory_in_Mb
67
- last_entry = DB[:memories].filter(:host_id => self.id).reverse_order(:created_at).last
68
- if last_entry
69
- last_entry[:mem_available] / 1024
76
+ if latest_memory_entry
77
+ latest_memory_entry.mem_available / 1024
70
78
  else
71
79
  0
72
80
  end
73
81
  end
74
82
 
75
83
  def used_memory_in_Mb
76
- last_entry = DB[:memories].filter(:host_id => self.id).reverse_order(:created_at).last
77
- if last_entry
78
- last_entry[:mem_used] / 1024
84
+ if latest_memory_entry
85
+ latest_memory_entry.mem_used / 1024
79
86
  else
80
87
  0
81
88
  end
@@ -118,27 +125,20 @@ class Host < Sequel::Model
118
125
  ####################
119
126
 
120
127
  def total_swap_in_Mb
121
- last_entry = DB[:memories].filter(:host_id => self.id).reverse_order(:created_at).last
122
- if last_entry
123
- (last_entry[:swap_available] + last_entry[:swap_used]) / 1024
124
- else
125
- 0
126
- end
128
+ available_swap_in_Mb + used_swap_in_Mb
127
129
  end
128
130
 
129
131
  def available_swap_in_Mb
130
- last_entry = DB[:memories].filter(:host_id => self.id).reverse_order(:created_at).last
131
- if last_entry
132
- last_entry[:swap_available] / 1024
132
+ if latest_memory_entry
133
+ latest_memory_entry.swap_available / 1024
133
134
  else
134
135
  0
135
136
  end
136
137
  end
137
138
 
138
139
  def used_swap_in_Mb
139
- last_entry = DB[:memories].filter(:host_id => self.id).reverse_order(:created_at).last
140
- if last_entry
141
- last_entry[:swap_used] / 1024
140
+ if latest_memory_entry
141
+ latest_memory_entry.swap_used / 1024
142
142
  else
143
143
  0
144
144
  end
@@ -214,15 +214,15 @@ class Host < Sequel::Model
214
214
  end
215
215
 
216
216
  def load_5_min
217
- self.loads.last.load_5_min if self.loads.last
217
+ self.latest_load_entry.load_5_min if self.latest_load_entry
218
218
  end
219
219
 
220
220
  def load_10_min
221
- self.loads.last.load_10_min if self.loads.last
221
+ self.latest_load_entry.load_10_min if self.latest_load_entry
222
222
  end
223
223
 
224
224
  def load_15_min
225
- self.loads.last.load_15_min if self.loads.last
225
+ self.latest_load_entry.load_15_min if self.latest_load_entry
226
226
  end
227
227
 
228
228
  def status
data/client.rb CHANGED
@@ -66,4 +66,4 @@ module DogNotGod
66
66
 
67
67
  end
68
68
 
69
- DogNotGod::Client.new(ARGV).run!
69
+ DogNotGod::Client.new(ARGV).run!
data/lib/base.rb ADDED
@@ -0,0 +1,7 @@
1
+ class String
2
+
3
+ def camelize
4
+ self.split('_').map {|w| w.capitalize}.join
5
+ end
6
+
7
+ end
@@ -0,0 +1,121 @@
1
+ module DogNotGod
2
+
3
+ class Shell
4
+
5
+ def initialize
6
+ raise "StaticClass"
7
+ end
8
+
9
+ def self.call(command)
10
+ `#{command}`
11
+ end
12
+ end
13
+
14
+ class Client
15
+
16
+ def self.capture(array_of_command_symbols)
17
+ @@command_symbols = array_of_command_symbols
18
+ end
19
+
20
+ end
21
+
22
+ #
23
+ #
24
+ #
25
+ module Commands
26
+
27
+ def self.factory(command_name_symbol)
28
+ class_name = command_name_symbol.to_s.camelize
29
+ klass = self.const_get class_name
30
+ klass.new
31
+ end
32
+
33
+
34
+ class ClientCommand
35
+
36
+ def run!(resource)
37
+ @resource = resource
38
+ _prepare
39
+ _execute
40
+ end
41
+
42
+ def get_hostname_from_shell
43
+ DogNotGod::Shell.call("hostname").split("\n")[0]
44
+ end
45
+
46
+ end
47
+
48
+ #
49
+ # Load average statistics
50
+ #
51
+ class LoadStats < ClientCommand
52
+
53
+ def _prepare
54
+ @hostname = get_hostname_from_shell
55
+ @load_averages = get_load_averages_from_shell
56
+ end
57
+
58
+ def _execute
59
+ @resource["/load_stats"].post({:load_5_min => @load_averages[0], :load_10_min => @load_averages[1], :load_15_min => @load_averages[2], :hostname => @hostname})
60
+ end
61
+
62
+ def get_load_averages_from_shell
63
+ DogNotGod::Shell.call("uptime").scan(/(\d+\.\d\d)/)
64
+ end
65
+
66
+ end
67
+
68
+ #
69
+ # Disk statistics
70
+ #
71
+ class DiskStats < ClientCommand
72
+
73
+ def _prepare
74
+ @hostname = get_hostname_from_shell
75
+ @disk_stats = get_disk_statistics_from_shell
76
+ end
77
+
78
+ def _execute
79
+ @disk_stats.each do |line|
80
+ @resource["/file_system_stats"].post({:file_system_name => line[0], :mounted_on => line[-1], :used => line[2], :available => line[3], :hostname => @hostname})
81
+ end
82
+ end
83
+
84
+ #
85
+ # Extract disk data from df call
86
+ #
87
+ # - Only extract entries for filesystems starting with a /
88
+ # - Ignore capacity % column
89
+ #
90
+ def get_disk_statistics_from_shell
91
+ DogNotGod::Shell.call("df -ak").scan(/^(\/[\w+\/-]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+\%\s+(\/.*)\n/)
92
+ end
93
+
94
+ end
95
+
96
+ #
97
+ # Memory statistics, including swap
98
+ #
99
+ class MemoryStats < ClientCommand
100
+
101
+ def _prepare
102
+ @hostname = get_hostname_from_shell
103
+ @memory_stats = get_memory_and_swap_statistics_from_shell
104
+ end
105
+
106
+ def _execute
107
+ @resource["/mem_stats"].post({:hostname => @hostname, :mem_available => @memory_stats[:mem_available], :mem_used => @memory_stats[:mem_used], :swap_available => @memory_stats[:swap_available], :swap_used => @memory_stats[:swap_used]})
108
+ end
109
+
110
+ def get_memory_and_swap_statistics_from_shell
111
+ # Note: the 'free' command is not available on Mac OSX
112
+ mem = DogNotGod::Shell.call("free").split("\n")
113
+ mem.shift # lose column headers
114
+
115
+ {:mem_available => mem[0].split(" ")[3], :mem_used => mem[0].split(" ")[2], :swap_available => mem[2].split(" ")[3], :swap_used => mem[2].split(" ")[2] }
116
+ end
117
+
118
+ end
119
+ end
120
+
121
+ end
data/server.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'sinatra'
3
-
3
+ # require 'ruby-prof'
4
+
4
5
  configure do
5
6
  DB_DIR = "#{ENV['HOME']}/.dognotgod"
6
7
 
@@ -59,6 +60,8 @@ get '/stylesheets/style.css' do
59
60
  end
60
61
 
61
62
  get "/" do
63
+ # result = RubyProf.profile do
64
+
62
65
  @hosts = Host.order(:hostname).all
63
66
 
64
67
  @end_now = Time.now.utc.to_fifteen_minute_grain_format
@@ -66,6 +69,10 @@ get "/" do
66
69
  @start_6h_ago = @end_now - (60*60*6)
67
70
 
68
71
  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)
69
76
  end
70
77
 
71
78
  post "/load_stats" do
data/views/main.haml CHANGED
@@ -1,6 +1,6 @@
1
1
  %h2 Summary
2
2
  #summary-section
3
- %table{:id => "summary-table", :cellspacing => 0, :cellpading => 0}
3
+ %table{:class => "summary-table", :cellspacing => 0, :cellpading => 0}
4
4
  %tr
5
5
  %th Host
6
6
  %th Last heartbeat
data/views/style.sass CHANGED
@@ -43,34 +43,34 @@ h4
43
43
  :padding-bottom 20px
44
44
  :border-bottom 1px solid #DDD
45
45
 
46
- #summary-table
46
+ // summary-table
47
+
48
+ .summary-table
47
49
  :border-top 1px solid #DDD
48
50
  :border-left 1px solid #DDD
49
51
 
50
-
51
- #summary-table tr.level4, #summary-table tr.level5
52
+ .summary-table tr.level4, .summary-table tr.level5
52
53
  :background-color #99FF99
53
54
 
54
- #summary-table tr.level3
55
+ .summary-table tr.level3
55
56
  :background-color #999933
56
57
 
57
- #summary-table tr.level1, #summary-table tr.level2
58
+ .summary-table tr.level1, .summary-table tr.level2
58
59
  :background-color #DD3333
59
60
 
60
- #summary-table tr.level0
61
+ .summary-table tr.level0
61
62
  :background-color #EFEFEF
62
63
 
63
- #summary-table th, #summary-table td
64
+ .summary-table th, #summary-table td
64
65
  :border-bottom 1px solid #DDD
65
66
  :border-right 1px solid #DDD
66
-
67
67
 
68
- #summary-table th
68
+ .summary-table th
69
69
  :background-color #EFEFEF
70
70
  :padding-left 15px
71
71
  :padding-right 15px
72
72
 
73
- #summary-table td
73
+ .summary-table td
74
74
  :padding-left 5px
75
75
  :padding-right 5px
76
76
 
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.5
4
+ version: 0.1.9
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-03 00:00:00 -08:00
12
+ date: 2009-03-05 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -82,7 +82,6 @@ extensions: []
82
82
  extra_rdoc_files: []
83
83
 
84
84
  files:
85
- - app/models
86
85
  - app/models/disk.rb
87
86
  - app/models/file_system.rb
88
87
  - app/models/host.rb
@@ -98,6 +97,8 @@ files:
98
97
  - config/thin.yml
99
98
  - server.rb
100
99
  - client.rb
100
+ - bin/dognotgod
101
+ - bin/dognotgod-client
101
102
  has_rdoc: false
102
103
  homepage: http://github.com/spoonsix/dognotgod
103
104
  post_install_message: