spoonsix-dognotgod 0.1.5 → 0.1.9
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 +1 -1
- data/app/models/file_system.rb +9 -12
- data/app/models/host.rb +29 -29
- data/client.rb +1 -1
- data/lib/base.rb +7 -0
- data/lib/client_commands.rb +121 -0
- data/server.rb +8 -1
- data/views/main.haml +1 -1
- data/views/style.sass +10 -10
- metadata +4 -3
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
|
|
data/app/models/file_system.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
32
|
-
|
|
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
|
-
|
|
41
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
68
|
-
|
|
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
|
-
|
|
77
|
-
|
|
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
|
-
|
|
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
|
-
|
|
131
|
-
|
|
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
|
-
|
|
140
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
data/lib/base.rb
ADDED
|
@@ -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
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
|
-
|
|
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
|
-
|
|
55
|
+
.summary-table tr.level3
|
|
55
56
|
:background-color #999933
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
.summary-table tr.level1, .summary-table tr.level2
|
|
58
59
|
:background-color #DD3333
|
|
59
60
|
|
|
60
|
-
|
|
61
|
+
.summary-table tr.level0
|
|
61
62
|
:background-color #EFEFEF
|
|
62
63
|
|
|
63
|
-
|
|
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
|
-
|
|
68
|
+
.summary-table th
|
|
69
69
|
:background-color #EFEFEF
|
|
70
70
|
:padding-left 15px
|
|
71
71
|
:padding-right 15px
|
|
72
72
|
|
|
73
|
-
|
|
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.
|
|
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-
|
|
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:
|