pimon 0.1.11 → 0.2.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.
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