pimon 0.1.0
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/.gitignore +10 -0
- data/.travis.yml +6 -0
- data/Capfile +2 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +77 -0
- data/README.md +77 -0
- data/Rakefile +13 -0
- data/WTFPL-LICENSE +13 -0
- data/bin/clean_redis_stats +1 -0
- data/bin/free.c +12 -0
- data/bin/makefile +2 -0
- data/bin/pimon +19 -0
- data/bin/random.c +21 -0
- data/bin/random.h +1 -0
- data/bin/vmstat.c +12 -0
- data/config/config.ru +4 -0
- data/config/config_dev.ru +11 -0
- data/config/deploy.rb +65 -0
- data/config/development.yml +25 -0
- data/config/production.yml +27 -0
- data/config/test.yml +27 -0
- data/config/test_broken.yml +22 -0
- data/config/thin/config.yml +13 -0
- data/lib/pimon.rb +63 -0
- data/lib/pimon/hash_extensions.rb +12 -0
- data/lib/pimon/pimon_config.rb +75 -0
- data/lib/pimon/probe/cpu_usage.rb +11 -0
- data/lib/pimon/probe/disk_usage.rb +11 -0
- data/lib/pimon/probe/memory_usage.rb +13 -0
- data/lib/pimon/probe/probe.rb +13 -0
- data/lib/pimon/probe/swap_usage.rb +13 -0
- data/lib/pimon/probe/system_memory.rb +19 -0
- data/lib/pimon/probe/temperature.rb +16 -0
- data/lib/pimon/public/favicon.ico +0 -0
- data/lib/pimon/stats_collector.rb +65 -0
- data/lib/pimon/version.rb +3 -0
- data/lib/pimon/views/index.haml +10 -0
- data/lib/pimon/views/index.js.haml +111 -0
- data/pimon.gemspec +34 -0
- data/spec/pimon_config_spec.rb +34 -0
- data/spec/pimon_spec.rb +35 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/stats_collector_spec.rb +61 -0
- metadata +272 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Capfile
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source :rubygems
|
2
|
+
|
3
|
+
gem 'capistrano'
|
4
|
+
gem 'haml'
|
5
|
+
gem 'redis'
|
6
|
+
gem 'sinatra', :require => 'sinatra/base'
|
7
|
+
gem 'thin'
|
8
|
+
|
9
|
+
gem 'pry', :group => [:development, :test]
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem 'mock_redis', '~> 0.5.0'
|
13
|
+
gem 'rack-test'
|
14
|
+
gem 'rspec', '~> 2.11.0'
|
15
|
+
gem 'simplecov', :require => false
|
16
|
+
gem 'simplecov-rcov'
|
17
|
+
gem 'timecop'
|
18
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
capistrano (2.13.3)
|
5
|
+
highline
|
6
|
+
net-scp (>= 1.0.0)
|
7
|
+
net-sftp (>= 2.0.0)
|
8
|
+
net-ssh (>= 2.0.14)
|
9
|
+
net-ssh-gateway (>= 1.1.0)
|
10
|
+
coderay (1.0.7)
|
11
|
+
daemons (1.1.9)
|
12
|
+
diff-lcs (1.1.3)
|
13
|
+
eventmachine (0.12.10)
|
14
|
+
haml (3.1.7)
|
15
|
+
highline (1.6.13)
|
16
|
+
method_source (0.8)
|
17
|
+
mock_redis (0.5.0)
|
18
|
+
multi_json (1.0.4)
|
19
|
+
net-scp (1.0.4)
|
20
|
+
net-ssh (>= 1.99.1)
|
21
|
+
net-sftp (2.0.5)
|
22
|
+
net-ssh (>= 2.0.9)
|
23
|
+
net-ssh (2.5.2)
|
24
|
+
net-ssh-gateway (1.1.0)
|
25
|
+
net-ssh (>= 1.99.1)
|
26
|
+
pry (0.9.10)
|
27
|
+
coderay (~> 1.0.5)
|
28
|
+
method_source (~> 0.8)
|
29
|
+
slop (~> 3.3.1)
|
30
|
+
rack (1.4.1)
|
31
|
+
rack-protection (1.2.0)
|
32
|
+
rack
|
33
|
+
rack-test (0.6.1)
|
34
|
+
rack (>= 1.0)
|
35
|
+
redis (3.0.1)
|
36
|
+
rspec (2.11.0)
|
37
|
+
rspec-core (~> 2.11.0)
|
38
|
+
rspec-expectations (~> 2.11.0)
|
39
|
+
rspec-mocks (~> 2.11.0)
|
40
|
+
rspec-core (2.11.1)
|
41
|
+
rspec-expectations (2.11.2)
|
42
|
+
diff-lcs (~> 1.1.3)
|
43
|
+
rspec-mocks (2.11.2)
|
44
|
+
simplecov (0.6.1)
|
45
|
+
multi_json (~> 1.0)
|
46
|
+
simplecov-html (~> 0.5.3)
|
47
|
+
simplecov-html (0.5.3)
|
48
|
+
simplecov-rcov (0.2.3)
|
49
|
+
simplecov (>= 0.4.1)
|
50
|
+
sinatra (1.3.2)
|
51
|
+
rack (~> 1.3, >= 1.3.6)
|
52
|
+
rack-protection (~> 1.2)
|
53
|
+
tilt (~> 1.3, >= 1.3.3)
|
54
|
+
slop (3.3.2)
|
55
|
+
thin (1.4.1)
|
56
|
+
daemons (>= 1.0.9)
|
57
|
+
eventmachine (>= 0.12.6)
|
58
|
+
rack (>= 1.0.0)
|
59
|
+
tilt (1.3.3)
|
60
|
+
timecop (0.3.5)
|
61
|
+
|
62
|
+
PLATFORMS
|
63
|
+
ruby
|
64
|
+
|
65
|
+
DEPENDENCIES
|
66
|
+
capistrano
|
67
|
+
haml
|
68
|
+
mock_redis (~> 0.5.0)
|
69
|
+
pry
|
70
|
+
rack-test
|
71
|
+
redis
|
72
|
+
rspec (~> 2.11.0)
|
73
|
+
simplecov
|
74
|
+
simplecov-rcov
|
75
|
+
sinatra
|
76
|
+
thin
|
77
|
+
timecop
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Pimon
|
2
|
+
|
3
|
+
[](http://travis-ci.org/pedrocarrico/pimon) [](https://gemnasium.com/pedrocarrico/pimon) [](https://codeclimate.com/github/pedrocarrico/pimon)
|
4
|
+
|
5
|
+

|
6
|
+
|
7
|
+
## Description
|
8
|
+
Pimon is a simple server monitor designed for the Raspberry Pi.
|
9
|
+
It uses redis lists to keep the latest observed statistics and also uses
|
10
|
+
highcharts to display some nice charts on your web browser.
|
11
|
+
|
12
|
+
## What do I need to get it to work?
|
13
|
+
1. Install redis an configure it to run on a socket on /tmp/redis.sock
|
14
|
+
2. bundle
|
15
|
+
3. bin/pimon start # run the sinatra app
|
16
|
+
4. go to http://localhost:3000 and PROFIT!
|
17
|
+
Optionally you may install it as a gem and run it, please check "Installing as a gem" further down.
|
18
|
+
|
19
|
+
## Configuration
|
20
|
+
1. basic_auth - enable or disable, configure username and password
|
21
|
+
2. redis - location of the redis socket
|
22
|
+
3. chart - colors for each chart
|
23
|
+
4. queues - redis list names for the series in the charts
|
24
|
+
5. stats - configure number of stats and time period between them
|
25
|
+
|
26
|
+
## Deployment
|
27
|
+
To deploy on your raspberry pi you just have to have ssh enabled and your keys authorized.
|
28
|
+
Then you can deploy with capistrano using:
|
29
|
+
```
|
30
|
+
cap deploy:setup
|
31
|
+
cap deploy:cold
|
32
|
+
```
|
33
|
+
|
34
|
+
This will setup your raspberry pi and deploy the application.
|
35
|
+
The username and password for the basic_auth in the production environment will be asked in the
|
36
|
+
first deploy.
|
37
|
+
To start and stop the application you have the usual:
|
38
|
+
```
|
39
|
+
cap deploy:start
|
40
|
+
cap deploy:stop
|
41
|
+
```
|
42
|
+
|
43
|
+
## Running tests
|
44
|
+
To run the coverage suite:
|
45
|
+
```
|
46
|
+
rake coverage:spec
|
47
|
+
```
|
48
|
+
Results will be in coverage/index.html directory.
|
49
|
+
|
50
|
+
## Installing as a gem
|
51
|
+
```
|
52
|
+
gem install pimon
|
53
|
+
```
|
54
|
+
After installation just do _pimon start_ and go to http://localhost:3000 and check your stats
|
55
|
+
(This will only work on your Raspberry Pi and perhaps some other linux distros, check the quirks section for more info).
|
56
|
+
|
57
|
+
## Quirks
|
58
|
+
Pimon uses _vmstat_ and _free_ to collect it's stats from the operating system and these are only
|
59
|
+
available on operating systems that have the /proc filesystem.
|
60
|
+
So if you want to develop on a Mac you may use the mock implementations that are in the bin directory.
|
61
|
+
The mock implementations are programmed in C and mimic the output of _vmstat_ and _free_.
|
62
|
+
They just change and generate some random values on the observed stats using /dev/urandom.
|
63
|
+
To use them you must first compile them using _make_ and then include the bin directory of this project
|
64
|
+
in your $PATH to have them available when you run the sinatra application.
|
65
|
+
The temperature stat is only available with the latest Raspbian distro (2012-09-18) on your Raspberry Pi and will (may)
|
66
|
+
not work if you're developing on other systems.
|
67
|
+
|
68
|
+
## TODO
|
69
|
+
1. Improve disk stats, have a way of having custom mount points
|
70
|
+
2. Capistrano task to reset production basic_auth username and password
|
71
|
+
3. Show uptime
|
72
|
+
4. Change configuration in realtime
|
73
|
+
5. Daemonize if running in production through bin/pimon (usefull for production environments without deploying through
|
74
|
+
capistrano)
|
75
|
+
|
76
|
+
## Copyright
|
77
|
+
Licensed under the [WTFPL](http://en.wikipedia.org/wiki/WTFPL "Do What The Fuck You Want To Public License") license.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
|
3
|
+
desc 'run specs'
|
4
|
+
RSpec::Core::RakeTask.new
|
5
|
+
|
6
|
+
namespace :coverage do
|
7
|
+
desc 'run rspec code coverage'
|
8
|
+
task :spec do
|
9
|
+
ENV['COVERAGE'] = 'on'
|
10
|
+
FileUtils.rm_r 'coverage', :force => true
|
11
|
+
Rake::Task[:spec].execute
|
12
|
+
end
|
13
|
+
end
|
data/WTFPL-LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
2
|
+
Version 2, December 2004
|
3
|
+
|
4
|
+
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
5
|
+
|
6
|
+
Everyone is permitted to copy and distribute verbatim or modified
|
7
|
+
copies of this license document, and changing it is allowed as long
|
8
|
+
as the name is changed.
|
9
|
+
|
10
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
11
|
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
12
|
+
|
13
|
+
0. You just DO WHAT THE FUCK YOU WANT TO.
|
@@ -0,0 +1 @@
|
|
1
|
+
/Users/pecarrico/opt/redis/src/redis-cli -s /tmp/redis.sock del pimon_mem del pimon_swap del pimon_cpu del pimon_time del pimon_disk pimon_temp
|
data/bin/free.c
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
|
4
|
+
int main (int argc, char *argv[])
|
5
|
+
{
|
6
|
+
int mem_used = generate_random();
|
7
|
+
int swap_used = generate_random();
|
8
|
+
|
9
|
+
printf(" total used free shared buffers cached\nMem: 215 %d %d 0 4 110\nSwap: 100 %d %d\n", mem_used, 215 - mem_used, swap_used, 100 - swap_used);
|
10
|
+
|
11
|
+
exit (0);
|
12
|
+
}
|
data/bin/makefile
ADDED
data/bin/pimon
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
action = ARGV[0]
|
3
|
+
environment = ARGV[1]
|
4
|
+
|
5
|
+
case action
|
6
|
+
when "start"
|
7
|
+
require 'rack'
|
8
|
+
|
9
|
+
puts 'Pimon is starting at http://localhost:3000'
|
10
|
+
config = "#{File.dirname(__FILE__)}/../config/config.ru"
|
11
|
+
|
12
|
+
ARGV[1] ? ENV['RACK_ENV'] = environment : ENV['RACK_ENV'] = 'development'
|
13
|
+
|
14
|
+
puts "Running in #{ENV['RACK_ENV']} mode."
|
15
|
+
server = Rack::Server.new(:config => config, :Port => 3000, :server => 'thin')
|
16
|
+
server.start
|
17
|
+
else
|
18
|
+
puts "Usage: pimon start <environment>"
|
19
|
+
end
|
data/bin/random.c
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <unistd.h>
|
3
|
+
#include <stdlib.h>
|
4
|
+
#include <math.h>
|
5
|
+
|
6
|
+
int generate_random()
|
7
|
+
{
|
8
|
+
FILE *urandom;
|
9
|
+
unsigned int seed;
|
10
|
+
int cpu_idle;
|
11
|
+
|
12
|
+
urandom = fopen ("/dev/urandom", "r");
|
13
|
+
if (urandom == NULL) {
|
14
|
+
fprintf (stderr, "ERROR: Cannot open /dev/urandom!\n");
|
15
|
+
exit (1);
|
16
|
+
}
|
17
|
+
fread (&seed, sizeof (seed), 1, urandom);
|
18
|
+
srand (seed);
|
19
|
+
|
20
|
+
return ((int) floor (rand() * 100.0 / ((double) RAND_MAX + 1) ) + 1);
|
21
|
+
}
|
data/bin/random.h
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
extern int generate_random();
|
data/bin/vmstat.c
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include "random.h"
|
4
|
+
|
5
|
+
int main (int argc, char *argv[])
|
6
|
+
{
|
7
|
+
int cpu_idle = generate_random();
|
8
|
+
|
9
|
+
printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n r b swpd free buff cache si so bi bo in cs us sy id wa\n 1 0 10976 50992 4900 113188 1 2 109 244 101 183 11 10 77 1\n 0 0 10976 50992 4900 113188 0 0 0 0 8366 315 10 5 %d 0\n", cpu_idle);
|
10
|
+
|
11
|
+
exit (0);
|
12
|
+
}
|
data/config/config.ru
ADDED
data/config/deploy.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
set :application, "pimon"
|
2
|
+
set :user, "pi"
|
3
|
+
|
4
|
+
set :scm, :git
|
5
|
+
|
6
|
+
set :repository, "git://github.com/pedrocarrico/pimon.git"
|
7
|
+
|
8
|
+
set :deploy_to, '/home/pi/app/pimon'
|
9
|
+
set :deploy_via, :remote_cache # quicker checkouts from github
|
10
|
+
|
11
|
+
set :domain, 'raspberrypi'
|
12
|
+
role :app, domain
|
13
|
+
role :web, domain
|
14
|
+
|
15
|
+
set :runner, user
|
16
|
+
set :use_sudo, false
|
17
|
+
|
18
|
+
after 'deploy:update_code', 'deploy:bundle_install'
|
19
|
+
|
20
|
+
namespace :deploy do
|
21
|
+
task :start, :roles => [:web, :app] do
|
22
|
+
run "cd #{deploy_to}/current && nohup thin -C config/thin/config.yml -R config/config.ru start"
|
23
|
+
end
|
24
|
+
|
25
|
+
task :stop, :roles => [:web, :app] do
|
26
|
+
run "cd #{deploy_to}/current && nohup thin -C config/thin/config.yml -R config/config.ru stop"
|
27
|
+
end
|
28
|
+
|
29
|
+
task :restart, :roles => [:web, :app] do
|
30
|
+
deploy.stop
|
31
|
+
deploy.check_basic_auth
|
32
|
+
deploy.start
|
33
|
+
end
|
34
|
+
|
35
|
+
task :cold do
|
36
|
+
deploy.update
|
37
|
+
deploy.check_basic_auth
|
38
|
+
deploy.start
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "After deploying check if there's need for a new username/password for the basic_auth"
|
42
|
+
task :check_basic_auth, :roles => :app do
|
43
|
+
require "yaml"
|
44
|
+
set :username, proc { Capistrano::CLI.ui.ask("username : ") }
|
45
|
+
set :password, proc { Capistrano::CLI.password_prompt("password : ") }
|
46
|
+
set :shared_config, "#{deploy_to}/shared/production.yml"
|
47
|
+
|
48
|
+
if 'true' == capture("if [ -e #{shared_config} ]; then echo 'true'; fi").strip
|
49
|
+
run "cp #{shared_config} #{deploy_to}/current/config/production.yml"
|
50
|
+
else
|
51
|
+
production_config = YAML::load_file('config/production.yml')
|
52
|
+
production_config['basic_auth']['username'] = username
|
53
|
+
production_config['basic_auth']['password'] = password
|
54
|
+
|
55
|
+
put YAML::dump(production_config), shared_config, :mode => 0664
|
56
|
+
run "cp #{shared_config} #{deploy_to}/current/config/production.yml"
|
57
|
+
puts "DONE"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "run 'bundle install' to install Bundler's packaged gems for the current deploy"
|
62
|
+
task :bundle_install, :roles => :app do
|
63
|
+
run "cd #{deploy_to}/current && bundle install --without test development"
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
basic_auth:
|
2
|
+
enabled: false
|
3
|
+
redis:
|
4
|
+
socket: /tmp/redis.sock
|
5
|
+
chart:
|
6
|
+
cpu:
|
7
|
+
color: '#D2691E'
|
8
|
+
disk:
|
9
|
+
color: '#CDC673'
|
10
|
+
mem:
|
11
|
+
color: '#87CEFA'
|
12
|
+
temp:
|
13
|
+
color: '#FF9B04'
|
14
|
+
swap:
|
15
|
+
color: '#3CB371'
|
16
|
+
queues:
|
17
|
+
time: pimon_time
|
18
|
+
cpu: pimon_cpu
|
19
|
+
disk: pimon_disk
|
20
|
+
mem: pimon_mem
|
21
|
+
swap: pimon_swap
|
22
|
+
temp: pimon_temp
|
23
|
+
stats_collector:
|
24
|
+
number_of_stats: 6
|
25
|
+
time_period_in_min: 1
|
@@ -0,0 +1,27 @@
|
|
1
|
+
basic_auth:
|
2
|
+
enabled: true
|
3
|
+
username: changed_on_deploy
|
4
|
+
password: changed_on_deploy
|
5
|
+
redis:
|
6
|
+
socket: /tmp/redis.sock
|
7
|
+
chart:
|
8
|
+
cpu:
|
9
|
+
color: '#D2691E'
|
10
|
+
disk:
|
11
|
+
color: '#CDC673'
|
12
|
+
mem:
|
13
|
+
color: '#87CEFA'
|
14
|
+
temp:
|
15
|
+
color: '#FF9B04'
|
16
|
+
swap:
|
17
|
+
color: '#3CB371'
|
18
|
+
queues:
|
19
|
+
time: pimon_time
|
20
|
+
cpu: pimon_cpu
|
21
|
+
disk: pimon_disk
|
22
|
+
mem: pimon_mem
|
23
|
+
swap: pimon_swap
|
24
|
+
temp: pimon_temp
|
25
|
+
stats_collector:
|
26
|
+
number_of_stats: 12
|
27
|
+
time_period_in_min: 5
|