pimon 0.1.11 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/bin/pimon +26 -19
  3. data/config/config.ru +11 -3
  4. data/config/default.yml +7 -13
  5. data/config/test.yml +6 -12
  6. data/config/test_broken.yml +0 -1
  7. data/lib/pimon.rb +2 -69
  8. data/lib/pimon/app.rb +81 -0
  9. data/lib/pimon/config.rb +34 -0
  10. data/lib/pimon/probe.rb +15 -0
  11. data/lib/pimon/probe/cpu_freq.rb +14 -0
  12. data/lib/pimon/probe/cpu_usage.rb +11 -8
  13. data/lib/pimon/probe/disk_usage.rb +11 -8
  14. data/lib/pimon/probe/memory_usage.rb +15 -10
  15. data/lib/pimon/probe/swap_usage.rb +16 -10
  16. data/lib/pimon/probe/system_memory.rb +16 -16
  17. data/lib/pimon/probe/temperature.rb +11 -13
  18. data/lib/pimon/probe/uptime.rb +37 -9
  19. data/lib/pimon/public/index.js +60 -120
  20. data/lib/pimon/public/normalize.css +427 -0
  21. data/lib/pimon/public/piecon.js +194 -0
  22. data/lib/pimon/public/style.css +13 -0
  23. data/lib/pimon/stats_collector.rb +66 -66
  24. data/lib/pimon/version.rb +1 -1
  25. data/lib/pimon/views/index.haml +17 -7
  26. data/pimon.gemspec +26 -25
  27. data/spec/{pimon_spec.rb → pimon/app_spec.rb} +9 -6
  28. data/spec/pimon/config_spec.rb +33 -0
  29. data/spec/pimon/stats_collector_spec.rb +13 -0
  30. data/spec/spec_helper.rb +9 -2
  31. metadata +195 -219
  32. data/.gitignore +0 -10
  33. data/.travis.yml +0 -6
  34. data/Gemfile +0 -20
  35. data/Gemfile.lock +0 -87
  36. data/README.md +0 -68
  37. data/Rakefile +0 -13
  38. data/WTFPL-LICENSE +0 -13
  39. data/bin/free.c +0 -12
  40. data/bin/makefile +0 -2
  41. data/bin/random.c +0 -21
  42. data/bin/random.h +0 -1
  43. data/bin/vmstat.c +0 -12
  44. data/lib/pimon/hash_extensions.rb +0 -12
  45. data/lib/pimon/pimon_config.rb +0 -32
  46. data/lib/pimon/probe/probe.rb +0 -13
  47. data/lib/pimon/probe/time_check.rb +0 -11
  48. data/lib/pimon/public/piecon.min.js +0 -5
  49. data/lib/pimon/stats.rb +0 -25
  50. data/spec/pimon_config_spec.rb +0 -17
  51. data/spec/stats_collector_spec.rb +0 -67
@@ -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 |pid_file|
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 "error: you must supply an action"
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 "Using default configuration"
78
+ puts 'Using default configuration'
80
79
  end
81
-
82
- server = Rack::Server.new(:config => config, :daemonize => options[:daemonize], :pid => pid_file, :Port => port, :server => 'thin', :Host => interface)
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 = `cat #{pid_file}`.to_i
87
- Process.kill("KILL", pid)
88
- File.delete(pid_file) if File.exists?(pid_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
- require 'pimon/version'
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
@@ -1,4 +1,12 @@
1
- $: << "#{File.dirname(__FILE__)}/.."
2
- require 'lib/pimon'
1
+ if ENV['RACK_ENV'] == 'development'
2
+ require 'rubygems'
3
+ require 'bundler'
3
4
 
4
- run Pimon
5
+ Bundler.require
6
+ end
7
+
8
+ require_relative '../lib/pimon'
9
+
10
+ $PROGRAM_NAME = 'pimon'
11
+
12
+ run Pimon::App
@@ -1,14 +1,8 @@
1
- chart:
2
- cpu:
3
- color: '#D2691E'
4
- disk:
5
- color: '#CDC673'
6
- mem:
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
- number_of_stats: 6
14
- time_period_in_secs: 30
8
+ time_period_in_secs: 10
@@ -1,15 +1,9 @@
1
- chart:
2
- cpu:
3
- color: '#D2691E'
4
- disk:
5
- color: '#CDC673'
6
- mem:
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
@@ -8,5 +8,4 @@ chart:
8
8
  swap:
9
9
  color: '#3CB371'
10
10
  stats_collector:
11
- number_of_stats: 6
12
11
  time_period_in_min: 10
@@ -1,71 +1,4 @@
1
- $: << File.dirname(__FILE__)
1
+ require 'pimon/app'
2
2
 
3
- if File.file?('Gemfile')
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
@@ -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
@@ -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
@@ -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
- require 'pimon/probe/probe'
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
- class Probe::CpuUsage < Probe
4
- def self.check
5
- 100 - `vmstat 1 2`.split(/\n/)[3].split(" ")[14].to_i
6
- end
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
- require 'pimon/probe/probe'
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
- class Probe::DiskUsage < Probe
4
- def self.check
5
- `df`.split(/\n/)[1].split(" ")[4].to_i
6
- end
7
-
8
- def self.symbol
9
- :disk
9
+ def self.unit
10
+ '%'
11
+ end
12
+ end
10
13
  end
11
14
  end