pimon 0.1.11 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/pimon +26 -19
- data/config/config.ru +11 -3
- data/config/default.yml +7 -13
- data/config/test.yml +6 -12
- data/config/test_broken.yml +0 -1
- data/lib/pimon.rb +2 -69
- data/lib/pimon/app.rb +81 -0
- data/lib/pimon/config.rb +34 -0
- data/lib/pimon/probe.rb +15 -0
- data/lib/pimon/probe/cpu_freq.rb +14 -0
- data/lib/pimon/probe/cpu_usage.rb +11 -8
- data/lib/pimon/probe/disk_usage.rb +11 -8
- data/lib/pimon/probe/memory_usage.rb +15 -10
- data/lib/pimon/probe/swap_usage.rb +16 -10
- data/lib/pimon/probe/system_memory.rb +16 -16
- data/lib/pimon/probe/temperature.rb +11 -13
- data/lib/pimon/probe/uptime.rb +37 -9
- data/lib/pimon/public/index.js +60 -120
- data/lib/pimon/public/normalize.css +427 -0
- data/lib/pimon/public/piecon.js +194 -0
- data/lib/pimon/public/style.css +13 -0
- data/lib/pimon/stats_collector.rb +66 -66
- data/lib/pimon/version.rb +1 -1
- data/lib/pimon/views/index.haml +17 -7
- data/pimon.gemspec +26 -25
- data/spec/{pimon_spec.rb → pimon/app_spec.rb} +9 -6
- data/spec/pimon/config_spec.rb +33 -0
- data/spec/pimon/stats_collector_spec.rb +13 -0
- data/spec/spec_helper.rb +9 -2
- metadata +195 -219
- data/.gitignore +0 -10
- data/.travis.yml +0 -6
- data/Gemfile +0 -20
- data/Gemfile.lock +0 -87
- data/README.md +0 -68
- data/Rakefile +0 -13
- data/WTFPL-LICENSE +0 -13
- data/bin/free.c +0 -12
- data/bin/makefile +0 -2
- data/bin/random.c +0 -21
- data/bin/random.h +0 -1
- data/bin/vmstat.c +0 -12
- data/lib/pimon/hash_extensions.rb +0 -12
- data/lib/pimon/pimon_config.rb +0 -32
- data/lib/pimon/probe/probe.rb +0 -13
- data/lib/pimon/probe/time_check.rb +0 -11
- data/lib/pimon/public/piecon.min.js +0 -5
- data/lib/pimon/stats.rb +0 -25
- data/spec/pimon_config_spec.rb +0 -17
- data/spec/stats_collector_spec.rb +0 -67
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a8ca73f2a9b9b25e474fb1104f343eeba425dbba
|
4
|
+
data.tar.gz: 4fdee4b13a77a452c4023aed9e3701c23764d3f7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b489ca2b46048bd2e5f1b7d8d43ef02807c62212e43622cc84933499bfa83537c59c86f69c7e8cd90fe8672d7f6da4c9ff9f50594509e4ee0b3eb112a1ababce
|
7
|
+
data.tar.gz: 40dd2febfa8e037079beb66839abaaf61d0fe9aba177acb2ec9c41d9cc0d22a851761e66b5fc97658f66894b04c59565727d5c8f90f175024e2415f189eed515
|
data/bin/pimon
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
$: << "#{File.dirname(__FILE__)}/../lib"
|
3
2
|
require 'optparse'
|
4
3
|
|
5
4
|
options = {}
|
@@ -13,20 +12,20 @@ Options:
|
|
13
12
|
'YAML configuration file for pimon') do |config|
|
14
13
|
options[:pimon_config] = config
|
15
14
|
end
|
16
|
-
|
15
|
+
|
17
16
|
opts.on('-d',
|
18
17
|
'--daemonize',
|
19
18
|
'Run Pimon daemonized in the background') do
|
20
19
|
options[:daemonize] = true
|
21
20
|
end
|
22
|
-
|
21
|
+
|
23
22
|
opts.on('-e ENVIRONMENT',
|
24
23
|
'--environment ENVIRONMENT',
|
25
24
|
'Application environment (default: "development", options: "development", "production")',
|
26
25
|
/^development|production$/) do |environment|
|
27
26
|
options[:environment] = environment
|
28
27
|
end
|
29
|
-
|
28
|
+
|
30
29
|
opts.on('-i INTERFACE',
|
31
30
|
'--interface INTERFACE',
|
32
31
|
'Hostname or IP address of the interface to listen on (default: "localhost")') do |interface|
|
@@ -38,16 +37,16 @@ Options:
|
|
38
37
|
'Port to use (default: 3000)') do |port|
|
39
38
|
options[:port] = port
|
40
39
|
end
|
41
|
-
|
40
|
+
|
42
41
|
opts.on('-P PIDFILE',
|
43
42
|
'--pid PIDFILE',
|
44
43
|
'File to store PID (default: /tmp/pimon.pid)') do |pid_file|
|
45
44
|
options[:pid_file] = pid_file
|
46
45
|
end
|
47
|
-
|
46
|
+
|
48
47
|
opts.on('-v',
|
49
48
|
'--version',
|
50
|
-
'Display Pimon version') do |
|
49
|
+
'Display Pimon version') do |_|
|
51
50
|
ARGV[0] = 'version'
|
52
51
|
end
|
53
52
|
end
|
@@ -55,13 +54,13 @@ end
|
|
55
54
|
begin
|
56
55
|
option_parser.parse!
|
57
56
|
if ARGV.empty?
|
58
|
-
puts
|
57
|
+
puts 'error: you must supply an action'
|
59
58
|
puts option_parser.help
|
60
59
|
exit 1
|
61
60
|
end
|
62
|
-
|
61
|
+
|
63
62
|
pid_file = options[:pid_file] || '/tmp/pimon.pid'
|
64
|
-
|
63
|
+
|
65
64
|
case ARGV[0]
|
66
65
|
when 'start'
|
67
66
|
require 'thin'
|
@@ -72,27 +71,35 @@ begin
|
|
72
71
|
ENV['PIMON_CONFIG'] = options[:pimon_config] if options[:pimon_config]
|
73
72
|
puts "Pimon is starting at http://#{interface}:#{port}"
|
74
73
|
puts "Running in #{ENV['RACK_ENV']} mode."
|
75
|
-
|
74
|
+
|
76
75
|
if ENV['PIMON_CONFIG']
|
77
76
|
puts "Using configuration file #{ENV['PIMON_CONFIG']}"
|
78
77
|
else
|
79
|
-
puts
|
78
|
+
puts 'Using default configuration'
|
80
79
|
end
|
81
|
-
|
82
|
-
|
80
|
+
|
81
|
+
server_options = {
|
82
|
+
config: config,
|
83
|
+
daemonize: options[:daemonize],
|
84
|
+
pid: pid_file,
|
85
|
+
Port: port,
|
86
|
+
server: 'thin',
|
87
|
+
Host: interface
|
88
|
+
}
|
89
|
+
|
90
|
+
server = Rack::Server.new(server_options)
|
83
91
|
server.start
|
84
92
|
when 'stop'
|
85
93
|
if File.file?(pid_file)
|
86
|
-
pid =
|
87
|
-
Process.kill(
|
88
|
-
File.delete(pid_file) if File.
|
94
|
+
pid = File.read(pid_file).to_i
|
95
|
+
Process.kill('KILL', pid)
|
96
|
+
File.delete(pid_file) if File.exist?(pid_file)
|
89
97
|
puts 'Pimon stopped...'
|
90
98
|
else
|
91
99
|
puts "Pid file not found at #{pid_file}, please supply a valid pid_file using -p or --pid"
|
92
100
|
end
|
93
101
|
when 'version'
|
94
|
-
|
95
|
-
puts "Pimon version is #{Pimon::VERSION}"
|
102
|
+
puts "Pimon version is #{Gem::Specification.load("#{File.dirname(__FILE__)}/../pimon.gemspec").version}"
|
96
103
|
else
|
97
104
|
STDERR.puts option_parser
|
98
105
|
end
|
data/config/config.ru
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
-
|
2
|
-
require '
|
1
|
+
if ENV['RACK_ENV'] == 'development'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler'
|
3
4
|
|
4
|
-
|
5
|
+
Bundler.require
|
6
|
+
end
|
7
|
+
|
8
|
+
require_relative '../lib/pimon'
|
9
|
+
|
10
|
+
$PROGRAM_NAME = 'pimon'
|
11
|
+
|
12
|
+
run Pimon::App
|
data/config/default.yml
CHANGED
@@ -1,14 +1,8 @@
|
|
1
|
-
|
2
|
-
cpu:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
color: '#87CEFA'
|
8
|
-
temp:
|
9
|
-
color: '#FF9B04'
|
10
|
-
swap:
|
11
|
-
color: '#3CB371'
|
1
|
+
colors:
|
2
|
+
cpu: '#D2691E'
|
3
|
+
disk: '#CDC673'
|
4
|
+
mem: '#87CEFA'
|
5
|
+
temp: '#FF9B04'
|
6
|
+
swap: '#3CB371'
|
12
7
|
stats_collector:
|
13
|
-
|
14
|
-
time_period_in_secs: 30
|
8
|
+
time_period_in_secs: 10
|
data/config/test.yml
CHANGED
@@ -1,15 +1,9 @@
|
|
1
|
-
|
2
|
-
cpu:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
color: '#87CEFA'
|
8
|
-
temp:
|
9
|
-
color: '#FF9B04'
|
10
|
-
swap:
|
11
|
-
color: '#3CB371'
|
1
|
+
colors:
|
2
|
+
cpu: '#D2691E'
|
3
|
+
disk: '#CDC673'
|
4
|
+
mem: '#87CEFA'
|
5
|
+
temp: '#FF9B04'
|
6
|
+
swap: '#3CB371'
|
12
7
|
hostname: 'test_hostname'
|
13
8
|
stats_collector:
|
14
|
-
number_of_stats: 6
|
15
9
|
time_period_in_min: 10
|
data/config/test_broken.yml
CHANGED
data/lib/pimon.rb
CHANGED
@@ -1,71 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'pimon/app'
|
2
2
|
|
3
|
-
|
4
|
-
require 'bundler/setup'
|
5
|
-
Bundler.require(:default, ENV['RACK_ENV'])
|
6
|
-
end
|
7
|
-
require 'eventmachine'
|
8
|
-
require 'json'
|
9
|
-
require 'haml'
|
10
|
-
require 'pimon/pimon_config'
|
11
|
-
require 'pimon/stats_collector'
|
12
|
-
require 'sinatra'
|
13
|
-
require 'sinatra-websocket'
|
14
|
-
|
15
|
-
class Pimon < Sinatra::Base
|
16
|
-
set :public_folder, "#{File.dirname(__FILE__)}/pimon/public"
|
17
|
-
set :views, "#{File.dirname(__FILE__)}/pimon/views"
|
18
|
-
set :sockets, []
|
19
|
-
|
20
|
-
configure :development, :production do
|
21
|
-
filename = "#{File.dirname(__FILE__)}/../config/default.yml"
|
22
|
-
config = PimonConfig.create_new(ENV['PIMON_CONFIG'] || filename)
|
23
|
-
|
24
|
-
EventMachine::next_tick do
|
25
|
-
settings.timer = EventMachine::add_periodic_timer(config.stats[:time_period_in_secs]) do
|
26
|
-
settings.stats_checker.collect_stats
|
27
|
-
@stats = settings.stats_checker.show_stats
|
28
|
-
|
29
|
-
settings.sockets.each{ |s| s.send(@stats) }
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
set :config, config
|
34
|
-
set :stats_checker, StatsCollector.new(config)
|
35
|
-
set :timer, nil
|
36
|
-
|
37
|
-
settings.stats_checker.collect_stats
|
38
|
-
@stats = settings.stats_checker.show_stats
|
39
|
-
end
|
40
|
-
|
41
|
-
configure :test do
|
42
|
-
config = PimonConfig.create_new("#{File.dirname(__FILE__)}/../config/test.yml")
|
43
|
-
|
44
|
-
set :config, config
|
45
|
-
set :stats_checker, StatsCollector.new(config)
|
46
|
-
set :timer, nil
|
47
|
-
end
|
48
|
-
|
49
|
-
get '/' do
|
50
|
-
if !request.websocket?
|
51
|
-
last_update = settings.stats_checker.last_update
|
52
|
-
last_modified(last_update) if ENV['RACK_ENV'] != 'development' && last_update
|
53
|
-
|
54
|
-
haml :index
|
55
|
-
else
|
56
|
-
request.websocket do |ws|
|
57
|
-
ws.onopen do
|
58
|
-
settings.sockets << ws
|
59
|
-
@stats ||= settings.stats_checker.show_stats
|
60
|
-
ws.send(@stats)
|
61
|
-
end
|
62
|
-
ws.onmessage do |msg|
|
63
|
-
puts "message received!! -> #{msg}"
|
64
|
-
end
|
65
|
-
ws.onclose do
|
66
|
-
settings.sockets.delete(ws)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
3
|
+
module Pimon
|
71
4
|
end
|
data/lib/pimon/app.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'json'
|
3
|
+
require 'haml'
|
4
|
+
require 'sinatra'
|
5
|
+
require 'faye/websocket'
|
6
|
+
|
7
|
+
require 'pimon/config'
|
8
|
+
require 'pimon/stats_collector'
|
9
|
+
|
10
|
+
Faye::WebSocket.load_adapter('thin')
|
11
|
+
|
12
|
+
module Pimon
|
13
|
+
class App < Sinatra::Base
|
14
|
+
set :public_folder, "#{File.dirname(__FILE__)}/public"
|
15
|
+
set :views, "#{File.dirname(__FILE__)}/views"
|
16
|
+
set :connected_websockets, []
|
17
|
+
|
18
|
+
configure :development, :production do
|
19
|
+
filename = "#{File.dirname(__FILE__)}/../../config/default.yml"
|
20
|
+
config = Pimon::Config.load(ENV['PIMON_CONFIG'] || filename)
|
21
|
+
|
22
|
+
set :config, config
|
23
|
+
set :stats_collector, Pimon::StatsCollector.new(config)
|
24
|
+
set :timer, nil
|
25
|
+
end
|
26
|
+
|
27
|
+
configure :test do
|
28
|
+
config = Pimon::Config.load("#{File.dirname(__FILE__)}/../../config/test.yml")
|
29
|
+
|
30
|
+
set :config, config
|
31
|
+
set :stats_collector, Pimon::StatsCollector.new(config)
|
32
|
+
set :timer, nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(*args, &bk)
|
36
|
+
super
|
37
|
+
start_collecting_stats
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
get '/' do
|
42
|
+
locals = {
|
43
|
+
charts: settings.stats_collector.charts,
|
44
|
+
single_stats: settings.stats_collector.single_stats,
|
45
|
+
hostname: settings.config.hostname
|
46
|
+
}
|
47
|
+
|
48
|
+
haml :index, locals: locals
|
49
|
+
end
|
50
|
+
|
51
|
+
get '/stats' do
|
52
|
+
if Faye::WebSocket.websocket?(request.env)
|
53
|
+
websocket = Faye::WebSocket.new(request.env)
|
54
|
+
|
55
|
+
websocket.on(:open) do
|
56
|
+
settings.connected_websockets << websocket
|
57
|
+
websocket.send(settings.stats_collector.show_stats.to_json)
|
58
|
+
end
|
59
|
+
|
60
|
+
websocket.on(:close) do
|
61
|
+
settings.connected_websockets.delete(websocket)
|
62
|
+
end
|
63
|
+
|
64
|
+
websocket.rack_response
|
65
|
+
else
|
66
|
+
halt 404
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def start_collecting_stats
|
71
|
+
return if settings.test?
|
72
|
+
settings.stats_collector.collect_stats
|
73
|
+
EventMachine.next_tick do
|
74
|
+
settings.timer = EventMachine.add_periodic_timer(settings.config.stats['time_period_in_secs']) do
|
75
|
+
settings.stats_collector.collect_stats
|
76
|
+
settings.connected_websockets.each { |s| s.send(settings.stats_collector.show_stats.to_json) }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/pimon/config.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Pimon
|
4
|
+
class Config
|
5
|
+
attr_reader :config
|
6
|
+
attr_reader :hostname
|
7
|
+
|
8
|
+
def self.load(filename)
|
9
|
+
new(filename)
|
10
|
+
end
|
11
|
+
|
12
|
+
def colors
|
13
|
+
config['colors']
|
14
|
+
end
|
15
|
+
|
16
|
+
def stats
|
17
|
+
config['stats_collector']
|
18
|
+
end
|
19
|
+
|
20
|
+
def hostname
|
21
|
+
@hostname ||= config['hostname'].nil? ? `hostname` : config['hostname']
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def initialize(filename)
|
27
|
+
@config = YAML.load_file(filename)
|
28
|
+
@config.freeze
|
29
|
+
rescue StandardError => e
|
30
|
+
puts "Error while loading config file: #{filename}"
|
31
|
+
raise e
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/pimon/probe.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'pimon/probe/cpu_freq'
|
2
|
+
require 'pimon/probe/cpu_usage'
|
3
|
+
require 'pimon/probe/disk_usage'
|
4
|
+
require 'pimon/probe/memory_usage'
|
5
|
+
require 'pimon/probe/swap_usage'
|
6
|
+
require 'pimon/probe/system_memory'
|
7
|
+
require 'pimon/probe/temperature'
|
8
|
+
require 'pimon/probe/uptime'
|
9
|
+
|
10
|
+
# Monkeypatching OpenStruct to render correct json in a probe sample
|
11
|
+
class OpenStruct
|
12
|
+
def to_json(options)
|
13
|
+
table.to_json(options)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Pimon
|
2
|
+
module Probe
|
3
|
+
class CpuFreq
|
4
|
+
def self.check(date = Time.now)
|
5
|
+
value = `cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq`.to_i / 1000
|
6
|
+
OpenStruct.new(date: date.strftime('%Y-%m-%d %H:%M:%S'), probe_name: 'cpu_freq', value: value, unit: unit)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.unit
|
10
|
+
'Mhz'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,11 +1,14 @@
|
|
1
|
-
|
1
|
+
module Pimon
|
2
|
+
module Probe
|
3
|
+
class CpuUsage
|
4
|
+
def self.check(date = Time.now)
|
5
|
+
value = 100 - `vmstat 1 2`.split(/\n/)[3].split(' ')[14].to_i
|
6
|
+
OpenStruct.new(date: date.strftime('%Y-%m-%d %H:%M:%S'), probe_name: 'cpu', value: value, unit: unit)
|
7
|
+
end
|
2
8
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def self.symbol
|
9
|
-
:cpu
|
9
|
+
def self.unit
|
10
|
+
'%'
|
11
|
+
end
|
12
|
+
end
|
10
13
|
end
|
11
14
|
end
|
@@ -1,11 +1,14 @@
|
|
1
|
-
|
1
|
+
module Pimon
|
2
|
+
module Probe
|
3
|
+
class DiskUsage
|
4
|
+
def self.check(date = Time.now)
|
5
|
+
value = `df`.split(/\n/)[1].split(' ')[4].to_i
|
6
|
+
OpenStruct.new(date: date.strftime('%Y-%m-%d %H:%M:%S'), probe_name: 'disk', value: value, unit: unit)
|
7
|
+
end
|
2
8
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def self.symbol
|
9
|
-
:disk
|
9
|
+
def self.unit
|
10
|
+
'%'
|
11
|
+
end
|
12
|
+
end
|
10
13
|
end
|
11
14
|
end
|