health_mode 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +30 -0
- data/LICENSE +13 -0
- data/README.md +7 -0
- data/Rakefile +34 -0
- data/bin/health-mode-agent +18 -0
- data/lib/authentication.rb +22 -0
- data/lib/health_mode.rb +72 -0
- data/lib/metric.rb +3 -0
- data/lib/metrics/cpu_metric.rb +62 -0
- data/lib/metrics/disk_space_metric.rb +52 -0
- data/lib/metrics/load_metric.rb +45 -0
- data/lib/metrics/memory_metric.rb +60 -0
- data/lib/metrics/network_io_metric.rb +84 -0
- data/lib/metrics/process_metric.rb +42 -0
- data/lib/metrics/swap_metric.rb +45 -0
- data/lib/metrics/user_metric.rb +37 -0
- data/lib/views/index.erb +12 -0
- data/test/health_mode_test.rb +154 -0
- metadata +128 -0
data/CHANGELOG.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Health Mode Change log
|
2
|
+
|
3
|
+
## 0.0.1 (22 Nov 2011)
|
4
|
+
|
5
|
+
Initial commit
|
6
|
+
|
7
|
+
## 0.0.2 (23 Nov 2011)
|
8
|
+
|
9
|
+
Basic Sinatra app working
|
10
|
+
1. Index route ready
|
11
|
+
2. Load service ready
|
12
|
+
|
13
|
+
## 0.1.0 (25 Nov 2011)
|
14
|
+
|
15
|
+
Basic metrics ready
|
16
|
+
|
17
|
+
## 0.1.1 (27 Nov 2011)
|
18
|
+
|
19
|
+
Shifing to use modular style
|
20
|
+
|
21
|
+
## 0.1.2 (28 Nov 2011)
|
22
|
+
|
23
|
+
Changed the name from broadcast mode to health mode
|
24
|
+
Able to set authorized host via command line options
|
25
|
+
|
26
|
+
## 0.1.3 (29 Nov 2011)
|
27
|
+
|
28
|
+
Added the public option
|
29
|
+
Tested against centos, ubuntu
|
30
|
+
Published into a gem
|
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2011 Wong Liang Zan
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# Health Mode
|
2
|
+
|
3
|
+
Health mode is a tiny Sinatra app that provides an API interface to the system. System statistics such as system load, disk space, and memory are exposed via web services. This makes it easy to integrate with other web services such as twitter or twilio.
|
4
|
+
|
5
|
+
## Uses
|
6
|
+
|
7
|
+
1. System monitoring.
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
def gemspec
|
5
|
+
@gemspec ||= begin
|
6
|
+
file = File.expand_path("../health_mode.gemspec", __FILE__)
|
7
|
+
eval(File.read(file), binding, file)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'rake/gempackagetask'
|
13
|
+
Rake::GemPackageTask.new(gemspec) do |pkg|
|
14
|
+
pkg.gem_spec = gemspec
|
15
|
+
end
|
16
|
+
task :gem => :gemspec
|
17
|
+
rescue LoadError
|
18
|
+
task(:gem){abort "`gem install rake` to package gems"}
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Install the gem locally"
|
22
|
+
task :install => :gem do
|
23
|
+
sh "gem install pkg/#{gemspec.full_name}.gem"
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Validate the gemspec"
|
27
|
+
task :gemspec do
|
28
|
+
gemspec.validate
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Runs the tests"
|
32
|
+
task :test do
|
33
|
+
sh "ruby test/health_mode_test.rb"
|
34
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "bundler/setup"
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/health_mode')
|
6
|
+
require 'vegas'
|
7
|
+
|
8
|
+
Vegas::Runner.new(HealthMode::Agent, 'health-mode-agent') do |runner, opts, app|
|
9
|
+
opts.on('-a HOSTNAME', "--authorized-host HOSTNAME", "set the host allowed to access the server") { |auth_host|
|
10
|
+
runner.logger.info "Authorizing connections from '#{auth_host}'"
|
11
|
+
HealthMode::Authentication.set_authorized_host auth_host
|
12
|
+
}
|
13
|
+
|
14
|
+
opts.on('-u', "--public", "allows the public to access") { |auth_host|
|
15
|
+
runner.logger.info "Allowing connections from public"
|
16
|
+
HealthMode::Authentication.set_public_access
|
17
|
+
}
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module HealthMode
|
4
|
+
module Authentication
|
5
|
+
@@authorized_host = "127.0.0.1"
|
6
|
+
@@public_access = false
|
7
|
+
|
8
|
+
def self.set_authorized_host(hostname)
|
9
|
+
@@authorized_host = hostname
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.set_public_access
|
13
|
+
@@public_access = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.from_authorized_host?(req)
|
17
|
+
req.ip == "127.0.0.1" ||
|
18
|
+
@@public_access ||
|
19
|
+
Socket.getaddrinfo(@@authorized_host, nil)[0][2] == req.ip
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/health_mode.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
require "sinatra/base"
|
4
|
+
require "json"
|
5
|
+
$:.unshift File.dirname(__FILE__)
|
6
|
+
require 'metric'
|
7
|
+
require 'authentication'
|
8
|
+
Dir[File.dirname(__FILE__) + "/metrics/*.rb"].each {|file| require file }
|
9
|
+
|
10
|
+
module HealthMode
|
11
|
+
class Agent < Sinatra::Base
|
12
|
+
before do
|
13
|
+
if !HealthMode::Authentication.from_authorized_host?(request)
|
14
|
+
request.path_info = "/unauthorized"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
get "/" do
|
19
|
+
erb :index
|
20
|
+
end
|
21
|
+
|
22
|
+
get "/unauthorized" do
|
23
|
+
'Unauthorized request'
|
24
|
+
end
|
25
|
+
|
26
|
+
get "/load.json" do
|
27
|
+
content_type :json
|
28
|
+
HealthMode::LoadMetric.current_state.to_json
|
29
|
+
end
|
30
|
+
|
31
|
+
get "/memory.json" do
|
32
|
+
content_type :json
|
33
|
+
HealthMode::MemoryMetric.current_state.to_json
|
34
|
+
end
|
35
|
+
|
36
|
+
get "/swap.json" do
|
37
|
+
content_type :json
|
38
|
+
HealthMode::SwapMetric.current_state.to_json
|
39
|
+
end
|
40
|
+
|
41
|
+
get "/disk_space.json" do
|
42
|
+
content_type :json
|
43
|
+
HealthMode::DiskSpaceMetric.current_state.to_json
|
44
|
+
end
|
45
|
+
|
46
|
+
get "/disk_io.json" do
|
47
|
+
content_type :json
|
48
|
+
HealthMode::DiskIOMetric.current_state.to_json
|
49
|
+
end
|
50
|
+
|
51
|
+
get "/users.json" do
|
52
|
+
content_type :json
|
53
|
+
HealthMode::UserMetric.current_state.to_json
|
54
|
+
end
|
55
|
+
|
56
|
+
get "/cpu.json" do
|
57
|
+
content_type :json
|
58
|
+
HealthMode::CPUMetric.current_state.to_json
|
59
|
+
end
|
60
|
+
|
61
|
+
get "/process.json" do
|
62
|
+
content_type :json
|
63
|
+
HealthMode::ProcessMetric.current_state.to_json
|
64
|
+
end
|
65
|
+
|
66
|
+
get "/network_io.json" do
|
67
|
+
content_type :json
|
68
|
+
HealthMode::NetworkIOMetric.current_state.to_json
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
data/lib/metric.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
module HealthMode
|
2
|
+
class CPUMetric < HealthMode::Metric
|
3
|
+
class << self
|
4
|
+
attr_accessor :system_metrics,
|
5
|
+
:cpu_user,
|
6
|
+
:cpu_nice,
|
7
|
+
:cpu_system,
|
8
|
+
:cpu_iowait,
|
9
|
+
:cpu_irq,
|
10
|
+
:cpu_idle,
|
11
|
+
:cpu_softirq
|
12
|
+
|
13
|
+
def current_state
|
14
|
+
refresh_state
|
15
|
+
{
|
16
|
+
"cpu_user" => @cpu_user,
|
17
|
+
"cpu_nice" => @cpu_nice,
|
18
|
+
"cpu_system" => @cpu_system,
|
19
|
+
"cpu_iowait" => @cpu_iowait,
|
20
|
+
"cpu_irq" => @cpu_irq,
|
21
|
+
"cpu_idle" => @cpu_idle,
|
22
|
+
"cpu_softirq" => @cpu_softirq
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def refresh_state
|
29
|
+
set_system_metrics
|
30
|
+
match_system_metrics
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_system_metrics
|
34
|
+
`cat /proc/stat`
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_system_metrics
|
38
|
+
@system_metrics = get_system_metrics
|
39
|
+
end
|
40
|
+
|
41
|
+
def metrics_regexp
|
42
|
+
/cpu\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/
|
43
|
+
end
|
44
|
+
|
45
|
+
def match_system_metrics
|
46
|
+
metrics_match = metrics_regexp.match(@system_metrics)
|
47
|
+
total = (1..6).map { |index| metrics_match[index].to_i }.reduce(:+)
|
48
|
+
@cpu_user = percentage_cpu_time(metrics_match[1], total)
|
49
|
+
@cpu_nice = percentage_cpu_time(metrics_match[2], total)
|
50
|
+
@cpu_system = percentage_cpu_time(metrics_match[3], total)
|
51
|
+
@cpu_idle = percentage_cpu_time(metrics_match[4], total)
|
52
|
+
@cpu_iowait = percentage_cpu_time(metrics_match[5], total)
|
53
|
+
@cpu_irq = percentage_cpu_time(metrics_match[6], total)
|
54
|
+
@cpu_softirq = percentage_cpu_time(metrics_match[7], total)
|
55
|
+
end
|
56
|
+
|
57
|
+
def percentage_cpu_time(num, denom)
|
58
|
+
(num.to_f / denom.to_f * 100.0).round(2)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module HealthMode
|
2
|
+
class DiskSpaceMetric < HealthMode::Metric
|
3
|
+
class << self
|
4
|
+
attr_accessor :system_metrics,
|
5
|
+
:total_disk_space,
|
6
|
+
:used_disk_space,
|
7
|
+
:free_disk_space,
|
8
|
+
:percentage_disk_space_used
|
9
|
+
|
10
|
+
def current_state
|
11
|
+
refresh_state
|
12
|
+
{
|
13
|
+
"disk_total" => @total_disk_space,
|
14
|
+
"disk_used" => @used_disk_space,
|
15
|
+
"disk_free" => @free_disk_space,
|
16
|
+
"disk_used_percentage" => @percentage_disk_space_used
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def refresh_state
|
23
|
+
set_system_metrics
|
24
|
+
match_system_metrics
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_system_metrics
|
28
|
+
`df`
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_system_metrics
|
32
|
+
@system_metrics = get_system_metrics
|
33
|
+
end
|
34
|
+
|
35
|
+
def metrics_regexp
|
36
|
+
/\S+\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+/
|
37
|
+
end
|
38
|
+
|
39
|
+
def match_system_metrics
|
40
|
+
@system_metrics.split("\n").each do |line|
|
41
|
+
metrics_match = metrics_regexp.match(line)
|
42
|
+
if !metrics_match.nil?
|
43
|
+
@total_disk_space = (@total_disk_space || 0) + metrics_match[1].to_i
|
44
|
+
@used_disk_space = (@used_disk_space || 0) + metrics_match[2].to_i
|
45
|
+
@free_disk_space = (@free_disk_space || 0) + metrics_match[3].to_i
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@percentage_disk_space_used = (@used_disk_space.to_f / @total_disk_space.to_f * 100).round
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module HealthMode
|
2
|
+
class LoadMetric < HealthMode::Metric
|
3
|
+
class << self
|
4
|
+
attr_accessor :system_metrics,
|
5
|
+
:one_minute_load_average,
|
6
|
+
:five_minutes_load_average,
|
7
|
+
:fifteen_minutes_load_average
|
8
|
+
|
9
|
+
def current_state
|
10
|
+
refresh_state
|
11
|
+
{
|
12
|
+
"load_one" => @one_minute_load_average,
|
13
|
+
"load_five" => @five_minutes_load_average,
|
14
|
+
"load_fifteen" => @fifteen_minutes_load_average
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def refresh_state
|
21
|
+
set_system_metrics
|
22
|
+
match_system_metrics
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_system_metrics
|
26
|
+
`cat /proc/loadavg`
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_system_metrics
|
30
|
+
@system_metrics = get_system_metrics
|
31
|
+
end
|
32
|
+
|
33
|
+
def metrics_regexp
|
34
|
+
/^(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+/
|
35
|
+
end
|
36
|
+
|
37
|
+
def match_system_metrics
|
38
|
+
metrics_match = metrics_regexp.match(@system_metrics)
|
39
|
+
@one_minute_load_average = metrics_match[1].to_f
|
40
|
+
@five_minutes_load_average = metrics_match[2].to_f
|
41
|
+
@fifteen_minutes_load_average = metrics_match[3].to_f
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module HealthMode
|
2
|
+
class MemoryMetric < HealthMode::Metric
|
3
|
+
class << self
|
4
|
+
attr_accessor :system_metrics,
|
5
|
+
:total_memory,
|
6
|
+
:used_memory,
|
7
|
+
:free_memory,
|
8
|
+
:shared_memory,
|
9
|
+
:buffers_memory,
|
10
|
+
:cached_memory,
|
11
|
+
:normalized_free_memory,
|
12
|
+
:normalized_used_memory
|
13
|
+
|
14
|
+
def current_state
|
15
|
+
refresh_state
|
16
|
+
{
|
17
|
+
"mem_total" => @total_memory,
|
18
|
+
"mem_used" => @used_memory,
|
19
|
+
"mem_free" => @free_memory,
|
20
|
+
"mem_shared" => @shared_memory,
|
21
|
+
"mem_buffers" => @buffers_memory,
|
22
|
+
"mem_cached" => @cached_memory,
|
23
|
+
"mem_used_normalized" => @normalized_used_memory,
|
24
|
+
"mem_free_normalized" => @normalized_free_memory
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def refresh_state
|
31
|
+
set_system_metrics
|
32
|
+
match_system_metrics
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_system_metrics
|
36
|
+
@system_metrics = get_system_metrics
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_system_metrics
|
40
|
+
`free`
|
41
|
+
end
|
42
|
+
|
43
|
+
def metrics_regexp
|
44
|
+
/Mem\:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+/
|
45
|
+
end
|
46
|
+
|
47
|
+
def match_system_metrics
|
48
|
+
metrics_match = metrics_regexp.match(@system_metrics)
|
49
|
+
@total_memory = metrics_match[1].to_i
|
50
|
+
@used_memory = metrics_match[2].to_i
|
51
|
+
@free_memory = metrics_match[3].to_i
|
52
|
+
@shared_memory = metrics_match[4].to_i
|
53
|
+
@buffers_memory = metrics_match[5].to_i
|
54
|
+
@cached_memory = metrics_match[6].to_i
|
55
|
+
@normalized_used_memory = @used_memory - @shared_memory - @buffers_memory - @cached_memory
|
56
|
+
@normalized_free_memory = @total_memory - @normalized_used_memory
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module HealthMode
|
2
|
+
class NetworkIOMetric < HealthMode::Metric
|
3
|
+
class << self
|
4
|
+
attr_accessor :curr_system_metrics,
|
5
|
+
:prev_system_metrics,
|
6
|
+
:curr_bytes_in,
|
7
|
+
:curr_bytes_out,
|
8
|
+
:curr_packets_in,
|
9
|
+
:curr_packets_out,
|
10
|
+
:prev_bytes_in,
|
11
|
+
:prev_bytes_out,
|
12
|
+
:prev_packets_in,
|
13
|
+
:prev_packets_out
|
14
|
+
|
15
|
+
def current_state
|
16
|
+
refresh_state
|
17
|
+
{
|
18
|
+
"bytes_in" => @curr_bytes_in - @prev_bytes_in,
|
19
|
+
"bytes_out" => @curr_bytes_out - @prev_bytes_out,
|
20
|
+
"packets_in" => @curr_packets_in - @prev_packets_in,
|
21
|
+
"packets_out" => @curr_packets_out - @prev_packets_out
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def refresh_state
|
28
|
+
set_previous_system_metrics
|
29
|
+
match_previous_system_metrics
|
30
|
+
set_current_system_metrics
|
31
|
+
match_current_system_metrics
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_system_metrics
|
35
|
+
`cat /proc/net/dev`
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_current_system_metrics
|
39
|
+
sleep 1
|
40
|
+
get_system_metrics
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_previous_system_metrics
|
44
|
+
get_system_metrics
|
45
|
+
end
|
46
|
+
|
47
|
+
def set_current_system_metrics
|
48
|
+
@curr_system_metrics = get_current_system_metrics
|
49
|
+
end
|
50
|
+
|
51
|
+
def set_previous_system_metrics
|
52
|
+
@prev_system_metrics = get_previous_system_metrics
|
53
|
+
end
|
54
|
+
|
55
|
+
def metrics_regexp
|
56
|
+
/\s+(\d+)\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+/
|
57
|
+
end
|
58
|
+
|
59
|
+
def match_current_system_metrics
|
60
|
+
@curr_system_metrics.split("\n").each do |line|
|
61
|
+
metrics_match = metrics_regexp.match(line)
|
62
|
+
if !metrics_match.nil?
|
63
|
+
@curr_bytes_in = (@curr_bytes_in || 0) + metrics_match[1].to_i
|
64
|
+
@curr_packets_in = (@curr_packets_in || 0) + metrics_match[2].to_i
|
65
|
+
@curr_bytes_out = (@curr_bytes_out || 0) + metrics_match[3].to_i
|
66
|
+
@curr_packets_out = (@curr_packets_out || 0) + metrics_match[4].to_i
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def match_previous_system_metrics
|
72
|
+
@prev_system_metrics.split("\n").each do |line|
|
73
|
+
metrics_match = metrics_regexp.match(line)
|
74
|
+
if !metrics_match.nil?
|
75
|
+
@prev_bytes_in = (@prev_bytes_in || 0) + metrics_match[1].to_i
|
76
|
+
@prev_packets_in = (@prev_packets_in || 0) + metrics_match[2].to_i
|
77
|
+
@prev_bytes_out = (@prev_bytes_out || 0) + metrics_match[3].to_i
|
78
|
+
@prev_packets_out = (@prev_packets_out || 0) + metrics_match[4].to_i
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module HealthMode
|
2
|
+
class ProcessMetric < HealthMode::Metric
|
3
|
+
class << self
|
4
|
+
attr_accessor :system_metrics,
|
5
|
+
:proc_run,
|
6
|
+
:proc_total
|
7
|
+
|
8
|
+
def current_state
|
9
|
+
refresh_state
|
10
|
+
{
|
11
|
+
"proc_total" => @proc_total,
|
12
|
+
"proc_run" => @proc_run
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def refresh_state
|
19
|
+
set_system_metrics
|
20
|
+
match_system_metrics
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_system_metrics
|
24
|
+
`cat /proc/loadavg`
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_system_metrics
|
28
|
+
@system_metrics = get_system_metrics
|
29
|
+
end
|
30
|
+
|
31
|
+
def metrics_regexp
|
32
|
+
/^\d+\.\d+\s+\d+\.\d+\s+\d+\.\d+\s+(\d+)\/(\d+)\s+\d+/
|
33
|
+
end
|
34
|
+
|
35
|
+
def match_system_metrics
|
36
|
+
metrics_match = metrics_regexp.match(@system_metrics)
|
37
|
+
@proc_run = metrics_match[1].to_i
|
38
|
+
@proc_total = metrics_match[2].to_i
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module HealthMode
|
2
|
+
class SwapMetric < HealthMode::Metric
|
3
|
+
class << self
|
4
|
+
attr_accessor :system_metrics,
|
5
|
+
:total_memory,
|
6
|
+
:used_memory,
|
7
|
+
:free_memory
|
8
|
+
|
9
|
+
def current_state
|
10
|
+
refresh_state
|
11
|
+
{
|
12
|
+
"swap_total" => @total_memory,
|
13
|
+
"swap_used" => @used_memory,
|
14
|
+
"swap_free" => @free_memory
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def refresh_state
|
21
|
+
set_system_metrics
|
22
|
+
match_system_metrics
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_system_metrics
|
26
|
+
`free`
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_system_metrics
|
30
|
+
@system_metrics = get_system_metrics
|
31
|
+
end
|
32
|
+
|
33
|
+
def metrics_regexp
|
34
|
+
/Swap\:\s+(\d+)\s+(\d+)\s+(\d+)/
|
35
|
+
end
|
36
|
+
|
37
|
+
def match_system_metrics
|
38
|
+
metrics_match = metrics_regexp.match(@system_metrics)
|
39
|
+
@total_memory = metrics_match[1].to_i
|
40
|
+
@used_memory = metrics_match[2].to_i
|
41
|
+
@free_memory = metrics_match[3].to_i
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module HealthMode
|
2
|
+
class UserMetric < HealthMode::Metric
|
3
|
+
class << self
|
4
|
+
attr_accessor :system_metrics,
|
5
|
+
:users_num
|
6
|
+
|
7
|
+
def current_state
|
8
|
+
refresh_state
|
9
|
+
{ "users_num" => @users_num }
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def refresh_state
|
15
|
+
set_system_metrics
|
16
|
+
match_system_metrics
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_system_metrics
|
20
|
+
`who -q`
|
21
|
+
end
|
22
|
+
|
23
|
+
def set_system_metrics
|
24
|
+
@system_metrics = get_system_metrics
|
25
|
+
end
|
26
|
+
|
27
|
+
def metrics_regexp
|
28
|
+
/#\s+users=(\d+)/
|
29
|
+
end
|
30
|
+
|
31
|
+
def match_system_metrics
|
32
|
+
metrics_match = metrics_regexp.match(@system_metrics)
|
33
|
+
@users_num = metrics_match[1].to_i
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/views/index.erb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
<h1>Health mode</h1>
|
2
|
+
|
3
|
+
<ul>
|
4
|
+
<li><a href="/load.json">Load</a></li>
|
5
|
+
<li><a href="/memory.json">Memory</a></li>
|
6
|
+
<li><a href="/swap.json">Swap</a></li>
|
7
|
+
<li><a href="/disk_space.json">Disk Space</a></li>
|
8
|
+
<li><a href="/users.json">Users</a></li>
|
9
|
+
<li><a href="/cpu.json">CPU</a></li>
|
10
|
+
<li><a href="/process.json">Process</a></li>
|
11
|
+
<li><a href="/network_io.json">Network IO</a></li>
|
12
|
+
</ul>
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/health_mode')
|
2
|
+
require 'test/unit'
|
3
|
+
require 'rack/test'
|
4
|
+
require 'mocha'
|
5
|
+
|
6
|
+
class HealthModeTest < Test::Unit::TestCase
|
7
|
+
include Rack::Test::Methods
|
8
|
+
|
9
|
+
def app
|
10
|
+
HealthMode::Agent.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_index
|
14
|
+
get "/"
|
15
|
+
assert last_response.ok?
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_load
|
19
|
+
HealthMode::LoadMetric.stubs(:get_system_metrics).returns("0.18 0.14 0.10 1/419 6130")
|
20
|
+
get "/load.json"
|
21
|
+
load_average = JSON.parse last_response.body
|
22
|
+
assert_equal load_average["load_one"], 0.18
|
23
|
+
assert_equal load_average["load_five"], 0.14
|
24
|
+
assert_equal load_average["load_fifteen"], 0.10
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_memory
|
28
|
+
HealthMode::MemoryMetric.stubs(:get_system_metrics).returns <<-sys_output
|
29
|
+
total used free shared buffers cached
|
30
|
+
Mem: 2004104 1887516 116588 0 419368 669652
|
31
|
+
-/+ buffers/cache: 798496 1205608
|
32
|
+
Swap: 0 0 0
|
33
|
+
sys_output
|
34
|
+
get "/memory.json"
|
35
|
+
memory_usage = JSON.parse last_response.body
|
36
|
+
assert_equal memory_usage["mem_total"], 2004104
|
37
|
+
assert_equal memory_usage["mem_used"], 1887516
|
38
|
+
assert_equal memory_usage["mem_free"], 116588
|
39
|
+
assert_equal memory_usage["mem_shared"], 0
|
40
|
+
assert_equal memory_usage["mem_buffers"], 419368
|
41
|
+
assert_equal memory_usage["mem_cached"], 669652
|
42
|
+
assert_equal memory_usage["mem_used_normalized"], 798496
|
43
|
+
assert_equal memory_usage["mem_free_normalized"], 1205608
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_swap
|
47
|
+
HealthMode::SwapMetric.stubs(:get_system_metrics).returns <<-sys_output
|
48
|
+
total used free shared buffers cached
|
49
|
+
Mem: 2004104 1887516 116588 0 419368 669652
|
50
|
+
-/+ buffers/cache: 798496 1205608
|
51
|
+
Swap: 0 0 0
|
52
|
+
sys_output
|
53
|
+
get "/swap.json"
|
54
|
+
swap_usage = JSON.parse last_response.body
|
55
|
+
assert_equal swap_usage["swap_total"], 0
|
56
|
+
assert_equal swap_usage["swap_used"], 0
|
57
|
+
assert_equal swap_usage["swap_free"], 0
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_disk_usage
|
61
|
+
HealthMode::DiskSpaceMetric.stubs(:get_system_metrics).returns <<-sys_output
|
62
|
+
Filesystem 1024-blocks Used Available Capacity Mounted on
|
63
|
+
/dev/sda2 19222656 15440068 2806052 85% /
|
64
|
+
none 995424 728 994696 1% /dev
|
65
|
+
none 1002052 1096 1000956 1% /dev/shm
|
66
|
+
none 1002052 132 1001920 1% /var/run
|
67
|
+
none 1002052 0 1002052 0% /var/lock
|
68
|
+
/dev/sda4 198071540 80614372 107395652 43% /home
|
69
|
+
sys_output
|
70
|
+
get "/disk_space.json"
|
71
|
+
disk_usage = JSON.parse last_response.body
|
72
|
+
assert_equal disk_usage["disk_total"], 221295776
|
73
|
+
assert_equal disk_usage["disk_used"], 96056396
|
74
|
+
assert_equal disk_usage["disk_free"], 114201328
|
75
|
+
assert_equal disk_usage["disk_used_percentage"], 43
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_number_of_users
|
79
|
+
HealthMode::UserMetric.stubs(:get_system_metrics).returns <<-sys_output
|
80
|
+
zan
|
81
|
+
# users=10
|
82
|
+
sys_output
|
83
|
+
get "/users.json"
|
84
|
+
users_usage = JSON.parse last_response.body
|
85
|
+
assert_equal users_usage["users_num"], 10
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_cpu_stat
|
89
|
+
HealthMode::CPUMetric.stubs(:get_system_metrics).returns <<-sys_output
|
90
|
+
cpu 40201 1327 14358 233796 20558 8 230 0 0 0
|
91
|
+
cpu0 19402 620 7456 117510 10136 4 115 0 0 0
|
92
|
+
cpu1 20798 706 6901 116286 10422 3 114 0 0 0
|
93
|
+
intr 2373672 1158643 2805 0 0 0 0 0 0 1 2318 0 0 245 0 36062 0 8201 22 0 4 0 394 0 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47 207 114893 183486 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
94
|
+
ctxt 4329537
|
95
|
+
btime 1322526863
|
96
|
+
processes 4468
|
97
|
+
procs_running 1
|
98
|
+
procs_blocked 0
|
99
|
+
softirq 638959 1 193943 38 2262 36164 1 156031 64861 418 185240
|
100
|
+
sys_output
|
101
|
+
get "/cpu.json"
|
102
|
+
# 310478
|
103
|
+
cpu_usage = JSON.parse last_response.body
|
104
|
+
assert_equal cpu_usage["cpu_user"], 12.96
|
105
|
+
assert_equal cpu_usage["cpu_nice"], 0.43
|
106
|
+
assert_equal cpu_usage["cpu_system"], 4.63
|
107
|
+
assert_equal cpu_usage["cpu_idle"], 75.36
|
108
|
+
assert_equal cpu_usage["cpu_iowait"], 6.63
|
109
|
+
assert_equal cpu_usage["cpu_irq"], 0.00
|
110
|
+
assert_equal cpu_usage["cpu_softirq"], 0.07
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_processes
|
114
|
+
HealthMode::ProcessMetric.stubs(:get_system_metrics).returns("0.18 0.14 0.10 1/419 6130")
|
115
|
+
get "/process.json"
|
116
|
+
process_usage = JSON.parse last_response.body
|
117
|
+
assert_equal process_usage["proc_run"], 1
|
118
|
+
assert_equal process_usage["proc_total"], 419
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_network_io
|
122
|
+
HealthMode::NetworkIOMetric.stubs(:get_previous_system_metrics).returns <<-sys_output
|
123
|
+
Inter-| Receive | Transmit
|
124
|
+
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
|
125
|
+
lo: 430741 2815 0 0 0 0 0 0 430741 2815 0 0 0 0 0 0
|
126
|
+
eth0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
127
|
+
wlan0: 212395394 173050 0 0 0 0 0 0 15434201 120532 0 0 0 0 0 0
|
128
|
+
sys_output
|
129
|
+
|
130
|
+
HealthMode::NetworkIOMetric.stubs(:get_current_system_metrics).returns <<-sys_output
|
131
|
+
Inter-| Receive | Transmit
|
132
|
+
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
|
133
|
+
lo: 430746 2815 0 0 0 0 0 0 430741 2815 0 0 0 0 0 0
|
134
|
+
eth0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
135
|
+
wlan0: 212395399 173060 0 0 0 0 0 0 15434221 120533 0 0 0 0 0 0
|
136
|
+
sys_output
|
137
|
+
get "/network_io.json"
|
138
|
+
network_io_usage = JSON.parse last_response.body
|
139
|
+
assert_equal network_io_usage["bytes_in"], 10
|
140
|
+
assert_equal network_io_usage["bytes_out"], 20
|
141
|
+
assert_equal network_io_usage["packets_in"], 10
|
142
|
+
assert_equal network_io_usage["packets_out"], 1
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_authentication
|
146
|
+
HealthMode::Authentication.stubs(:from_authorized_host?).returns(true)
|
147
|
+
get "/"
|
148
|
+
assert_not_equal last_response.body, 'Unauthorized request'
|
149
|
+
|
150
|
+
HealthMode::Authentication.stubs(:from_authorized_host?).returns(false)
|
151
|
+
get "/"
|
152
|
+
assert_equal last_response.body, 'Unauthorized request'
|
153
|
+
end
|
154
|
+
end
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: health_mode
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.3
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Wong Liang Zan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-11-29 00:00:00 +08:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: sinatra
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 1.3.1
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ~>
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 1.6.1
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: thin
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.3.1
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: vegas
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 0.1.8
|
58
|
+
type: :runtime
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: rake
|
62
|
+
prerelease: false
|
63
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
type: :runtime
|
70
|
+
version_requirements: *id005
|
71
|
+
description: "Health mode exposes the system metrics via a JSON api. This opens the door for integration with web services. "
|
72
|
+
email: zan@liangzan.net
|
73
|
+
executables:
|
74
|
+
- health-mode-agent
|
75
|
+
extensions: []
|
76
|
+
|
77
|
+
extra_rdoc_files:
|
78
|
+
- LICENSE
|
79
|
+
- README.md
|
80
|
+
files:
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- LICENSE
|
84
|
+
- CHANGELOG.md
|
85
|
+
- lib/metrics/swap_metric.rb
|
86
|
+
- lib/metrics/disk_space_metric.rb
|
87
|
+
- lib/metrics/cpu_metric.rb
|
88
|
+
- lib/metrics/user_metric.rb
|
89
|
+
- lib/metrics/load_metric.rb
|
90
|
+
- lib/metrics/network_io_metric.rb
|
91
|
+
- lib/metrics/memory_metric.rb
|
92
|
+
- lib/metrics/process_metric.rb
|
93
|
+
- lib/metric.rb
|
94
|
+
- lib/authentication.rb
|
95
|
+
- lib/health_mode.rb
|
96
|
+
- lib/views/index.erb
|
97
|
+
- bin/health-mode-agent
|
98
|
+
- test/health_mode_test.rb
|
99
|
+
has_rdoc: true
|
100
|
+
homepage: http://github.com/liangzan/health_mode
|
101
|
+
licenses: []
|
102
|
+
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options:
|
105
|
+
- --charset=UTF-8
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: "0"
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: "0"
|
120
|
+
requirements: []
|
121
|
+
|
122
|
+
rubyforge_project:
|
123
|
+
rubygems_version: 1.6.2
|
124
|
+
signing_key:
|
125
|
+
specification_version: 3
|
126
|
+
summary: Health mode exposes system health metrics via an api
|
127
|
+
test_files: []
|
128
|
+
|