city-watch 0.3.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 (46) hide show
  1. data/.DS_Store +0 -0
  2. data/.gitignore +1 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +46 -0
  5. data/README +15 -0
  6. data/Rakefile +11 -0
  7. data/bin/city_watch +19 -0
  8. data/bin/watch_collector +20 -0
  9. data/bin/watch_commander +20 -0
  10. data/city_watch.gemspec +29 -0
  11. data/config/city_watch.yml +1 -0
  12. data/config/watch_collector.yml +4 -0
  13. data/config/watch_commander.yml +4 -0
  14. data/lib/city_watch/agent.rb +3 -0
  15. data/lib/city_watch/collector/receive.rb +29 -0
  16. data/lib/city_watch/collector.rb +9 -0
  17. data/lib/city_watch/commander/home.rb +16 -0
  18. data/lib/city_watch/commander/server.rb +0 -0
  19. data/lib/city_watch/commander.rb +10 -0
  20. data/lib/city_watch/commands/df.rb +26 -0
  21. data/lib/city_watch/commands/iostat.rb +0 -0
  22. data/lib/city_watch/commands/mpstat.rb +27 -0
  23. data/lib/city_watch/commands/netstat.rb +31 -0
  24. data/lib/city_watch/commands/ps.rb +31 -0
  25. data/lib/city_watch/commands.rb +29 -0
  26. data/lib/city_watch/util/collector.rb +29 -0
  27. data/lib/city_watch/util/run_command.rb +86 -0
  28. data/lib/city_watch/util/watchman.rb +16 -0
  29. data/lib/city_watch/watchmen/cpu_usage.rb +12 -0
  30. data/lib/city_watch/watchmen/disk_usage.rb +10 -0
  31. data/lib/city_watch/watchmen/memory_profiler.rb +0 -0
  32. data/lib/city_watch/watchmen/network_throughput.rb +0 -0
  33. data/lib/city_watch/watchmen/nginx.rb +18 -0
  34. data/lib/city_watch/watchmen/processes.rb +0 -0
  35. data/lib/city_watch/watchmen/processor_stats.rb +0 -0
  36. data/lib/city_watch/watchmen/redis.rb +0 -0
  37. data/lib/city_watch/watchmen/ruby_gc.rb +0 -0
  38. data/lib/city_watch/watchmen/server_load.rb +0 -0
  39. data/lib/city_watch/watchmen/sysinfo.rb +11 -0
  40. data/lib/city_watch/watchmen/unicorns.rb +18 -0
  41. data/lib/city_watch/watchmen.rb +30 -0
  42. data/lib/city_watch.rb +70 -0
  43. data/lib/version.rb +3 -0
  44. data/watch_collector.ru +13 -0
  45. data/watch_commander.ru +13 -0
  46. metadata +177 -0
data/.DS_Store ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,46 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ city_watch (0.1.0)
5
+ rack
6
+ rack-mount
7
+ redis
8
+ rspec
9
+ sysinfo
10
+ unicorn
11
+ yajl-ruby
12
+
13
+ GEM
14
+ remote: http://rubygems.org/
15
+ specs:
16
+ diff-lcs (1.1.3)
17
+ drydock (0.6.9)
18
+ kgio (2.7.4)
19
+ rack (1.4.1)
20
+ rack-mount (0.8.3)
21
+ rack (>= 1.0.0)
22
+ raindrops (0.10.0)
23
+ redis (3.0.2)
24
+ rspec (2.12.0)
25
+ rspec-core (~> 2.12.0)
26
+ rspec-expectations (~> 2.12.0)
27
+ rspec-mocks (~> 2.12.0)
28
+ rspec-core (2.12.1)
29
+ rspec-expectations (2.12.0)
30
+ diff-lcs (~> 1.1.3)
31
+ rspec-mocks (2.12.0)
32
+ storable (0.8.9)
33
+ sysinfo (0.8.0)
34
+ drydock
35
+ storable
36
+ unicorn (4.5.0)
37
+ kgio (~> 2.6)
38
+ rack
39
+ raindrops (~> 0.7)
40
+ yajl-ruby (1.1.0)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ city_watch!
data/README ADDED
@@ -0,0 +1,15 @@
1
+ Watch servers, etc, whatever
2
+
3
+ https://github.com/delano/sysinfo/
4
+
5
+ Want to monitor:
6
+ Server Load
7
+ Disk Usage
8
+ Memory Profiler (usage)
9
+ CPU usage
10
+ Network Throughput
11
+ Nginx
12
+ Processes
13
+ Ruby GC
14
+ Redis
15
+ Processor stats (mpstat)
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc "Run specs"
7
+ task :spec do
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ t.pattern = './lib/spec/**/*_spec.rb'
10
+ end
11
+ end
data/bin/city_watch ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yajl'
4
+ require 'city_watch'
5
+ require 'city_watch/agent'
6
+
7
+ Commands.test if CityWatch.debug?
8
+
9
+ dat = {
10
+ :hostname => ::Socket.gethostname,
11
+ # :commands => Commands.data,
12
+ :watchmen => Watchmen.data
13
+ }
14
+
15
+ if CityWatch.config[:watch_collector]
16
+ Collector.send!(CityWatch.config[:watch_collector],dat)
17
+ else
18
+ puts Yajl::Encoder.encode(dat)
19
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yajl'
4
+ require 'city_watch'
5
+
6
+ puts "Starting watch collector..."
7
+
8
+ require 'unicorn/launcher'
9
+
10
+ ENV["RACK_ENV"] ||= CityWatch.config[:environment]
11
+ rackup_opts = Unicorn::Configurator::RACKUP
12
+ options = rackup_opts[:options]
13
+
14
+ CityWatch.unicorn_opts(rackup_opts)
15
+
16
+ app = Unicorn.builder("#{File.expand_path(File.dirname(__FILE__))}/../#{File.basename($0)}.ru", nil)
17
+ op = nil
18
+
19
+ Unicorn::Launcher.daemonize!(options) if rackup_opts[:daemonize]
20
+ Unicorn::HttpServer.new(app, options).start.join
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yajl'
4
+ require 'city_watch'
5
+
6
+ puts "Starting watch commander..."
7
+
8
+ require 'unicorn/launcher'
9
+
10
+ ENV["RACK_ENV"] ||= CityWatch.config[:environment]
11
+ rackup_opts = Unicorn::Configurator::RACKUP
12
+ options = rackup_opts[:options]
13
+
14
+ CityWatch.unicorn_opts(rackup_opts)
15
+
16
+ app = Unicorn.builder("#{File.expand_path(File.dirname(__FILE__))}/../#{File.basename($0)}.ru", nil)
17
+ op = nil
18
+
19
+ Unicorn::Launcher.daemonize!(options) if rackup_opts[:daemonize]
20
+ Unicorn::HttpServer.new(app, options).start.join
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.unshift File.expand_path("../lib", __FILE__)
3
+ require "version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "city-watch"
7
+ s.version = CityWatch::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["John Bragg"]
10
+ s.email = ["john@cozy.co"]
11
+ s.homepage = "http://cozy.co"
12
+ s.summary = %q{Server/process monitoring}
13
+ s.description = %q{}
14
+
15
+ s.rubyforge_project = "city-watch"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ s.required_ruby_version = '>= 1.9.2'
22
+ s.add_dependency "redis"
23
+ s.add_dependency "rspec"
24
+ s.add_dependency "rack"
25
+ s.add_dependency "rack-mount"
26
+ s.add_dependency "unicorn"
27
+ s.add_dependency "yajl-ruby"
28
+ s.add_dependency "sysinfo"
29
+ end
@@ -0,0 +1 @@
1
+ :collector: "localhost:62001"
@@ -0,0 +1,4 @@
1
+ :unicorn:
2
+ :port: 62001
3
+ :redis:
4
+ :db: 2
@@ -0,0 +1,4 @@
1
+ :unicorn:
2
+ :port: 62002
3
+ :redis:
4
+ :db: 2
@@ -0,0 +1,3 @@
1
+ require 'city_watch/util/collector'
2
+ require 'city_watch/commands'
3
+ require 'city_watch/watchmen'
@@ -0,0 +1,29 @@
1
+ class ResendRequest
2
+
3
+ def call(env)
4
+
5
+ post_data = begin Yajl::Parser.new(:symbolize_keys => true).parse(env["rack.input"].read) || {} rescue {} end
6
+ post_data[:received_at] = Time.now.to_s
7
+
8
+ CityWatch.redis.sadd "#{CityWatch.config[:prefix]}::known_hosts", post_data[:hostname]
9
+ CityWatch.redis.zadd "#{CityWatch.config[:prefix]}::#{post_data[:hostname]}::raw_stats", Time.now.to_i, Yajl::Encoder.encode(post_data)
10
+
11
+ summary = {}
12
+
13
+ post_data[:watchmen].each do |watchman,dat|
14
+ CityWatch.redis.zadd "#{CityWatch.config[:prefix]}::#{post_data[:hostname]}::#{watchman}", Time.now.to_i, Yajl::Encoder.encode(dat.merge({:received_at => post_data[:received_at]}))
15
+ if dat[:summary]
16
+ sum = dat[:summary].is_a?(Array) ? dat[:summary].inject({}) {|acc,k| acc[k.to_sym] = dat[k.to_sym]; acc}.merge({:received_at => post_data[:received_at]}) : dat[:summary]
17
+ CityWatch.redis.zadd "#{CityWatch.config[:prefix]}::#{post_data[:hostname]}::#{watchman}::summary", Time.now.to_i, Yajl::Encoder.encode(sum)
18
+ summary[watchman] = sum
19
+ end
20
+ end
21
+
22
+ CityWatch.redis.zadd "#{CityWatch.config[:prefix]}::#{post_data[:hostname]}::summary", Time.now.to_i, Yajl::Encoder.encode(summary)
23
+
24
+ [200,{"Content-Type" => "text/plain"},["Got it!"]]
25
+ end
26
+
27
+ Routes.add_route new, { :request_method => 'POST', :path_info => %r{^/receive} }, {}, :receive_data
28
+
29
+ end
@@ -0,0 +1,9 @@
1
+ require 'rack/mount'
2
+
3
+ module CityWatch
4
+ Routes = Rack::Mount::RouteSet.new
5
+ end
6
+
7
+ ::Routes = CityWatch::Routes
8
+
9
+ require 'city_watch/collector/receive'
@@ -0,0 +1,16 @@
1
+ class ResendRequest
2
+
3
+ def call(env)
4
+
5
+ output = "Known servers:\n\n"
6
+
7
+ CityWatch.redis.smembers("#{CityWatch.config[:prefix]}::known_hosts").each do |server|
8
+ output << "#{server}: ".ljust(20) << CityWatch.redis.zrevrange("#{CityWatch.config[:prefix]}::#{server}::summary",0,0).first << "\n"
9
+ end
10
+
11
+ [200,{"Content-Type" => "text/plain"},[output]]
12
+ end
13
+
14
+ Routes.add_route new, { :request_method => 'GET', :path_info => %r{^/} }, {}, :home
15
+
16
+ end
File without changes
@@ -0,0 +1,10 @@
1
+ require 'rack/mount'
2
+
3
+ module CityWatch
4
+ Routes = Rack::Mount::RouteSet.new
5
+ end
6
+
7
+ ::Routes = CityWatch::Routes
8
+
9
+ require 'city_watch/commander/home'
10
+ require 'city_watch/commander/server'
@@ -0,0 +1,26 @@
1
+ class DF
2
+
3
+ include RunCommand
4
+
5
+ command :df, :k => ""
6
+
7
+ def data
8
+ headers = false
9
+ output = []
10
+ command_output.split("\n").map {|line| line.split("\s") }.each do |line|
11
+ if !headers
12
+ headers = line.map {|hdr| hdr.downcase.to_sym}
13
+ headers.pop
14
+ next
15
+ end
16
+ next unless headers
17
+ pkt = {}
18
+ line.each_with_index do |itm,idx|
19
+ pkt[headers[idx]] = itm
20
+ end
21
+ output << pkt
22
+ end
23
+ output
24
+ end
25
+
26
+ end
File without changes
@@ -0,0 +1,27 @@
1
+ class MPstat
2
+
3
+ include RunCommand
4
+
5
+ command :mpstat, :interval => 5, :times => 2
6
+
7
+ def command_line_opts
8
+ "#{options[:interval]} #{options[:times]}"
9
+ end
10
+
11
+ def data
12
+ command_output.split("\n").map {|line| line.split("\s") }.inject([]) do |output,line|
13
+ if line[1] == "CPU"
14
+ headers = line.map {|hdr| hdr.gsub(/%/,'').to_sym}
15
+ next
16
+ end
17
+ next unless headers
18
+ pkt = {}
19
+ line.each_with_index do |itm,idx|
20
+ pkt[headers[idx]] = itm
21
+ end
22
+ output << pkt
23
+ output
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,31 @@
1
+ class Netstat
2
+
3
+ include RunCommand
4
+
5
+ command :netstat, :naplev => ""
6
+
7
+ def data
8
+ headers = false
9
+ output = {}
10
+ command_output.split("\n").each do |line|
11
+ if line[/^Active /,0]
12
+ type = line.split(" ")[1]
13
+ end
14
+ if line[/^Proto /,0]
15
+ fmt = line.split(/ \b/).map {|v| [v.strip.downcase.to_sym,v.length]}
16
+ fmt[fmt.size-1][1] = 99
17
+ next
18
+ end
19
+ next unless fmt
20
+ pkt = {}
21
+ fmt.each do |(name,length)|
22
+ val = line.slice!(0..length-1).strip
23
+ pkt[name] = val
24
+ end
25
+ output[type] ||= []
26
+ output[type] << pkt
27
+ end
28
+ output
29
+ end
30
+
31
+ end
@@ -0,0 +1,31 @@
1
+ class PS
2
+
3
+ include RunCommand
4
+
5
+ command :ps
6
+
7
+ def command_line_opts
8
+ "aux"
9
+ end
10
+
11
+ def data
12
+ headers = false
13
+ output = []
14
+ command_output.split("\n").map {|line| line.split("\s") }.each do |line|
15
+ if !headers
16
+ headers = line.map {|hdr| hdr.downcase.to_sym}
17
+ next
18
+ end
19
+ next unless headers
20
+ pkt = {}
21
+ cmd = line.slice!(10,line.size-1)
22
+ line << cmd.join(" ")
23
+ line.each_with_index do |itm,idx|
24
+ pkt[headers[idx]] = itm
25
+ end
26
+ output << pkt
27
+ end
28
+ output
29
+ end
30
+
31
+ end
@@ -0,0 +1,29 @@
1
+ module Commands
2
+
3
+ def self.test
4
+ @command_list.each do |cmd|
5
+ puts "Running #{cmd.name}:"
6
+ puts cmd.data.inspect
7
+ puts "Done."
8
+ end
9
+ end
10
+
11
+ def self.data
12
+ @command_list.inject({}) do |acc,cmd|
13
+ acc[cmd.name] = cmd.data
14
+ end
15
+ end
16
+
17
+ def self.register(cls)
18
+ @command_list ||= []
19
+ @command_list << cls
20
+ end
21
+
22
+ end
23
+
24
+ require 'city_watch/util/run_command'
25
+ require 'city_watch/commands/ps'
26
+ require 'city_watch/commands/df'
27
+ require 'city_watch/commands/mpstat'
28
+ # require 'city_watch/commands/netstat'
29
+ # require 'city_watch/commands/iostat'
@@ -0,0 +1,29 @@
1
+ module Collector
2
+
3
+ def self.send!(addr,dat)
4
+ require "yajl"
5
+ require 'net/http'
6
+ require 'net/https'
7
+ puts "Sending message to: http#{CityWatch.config[:secure] ? "s" : ""}://#{addr}/receive" if CityWatch.debug?
8
+ uri = URI.parse("http#{CityWatch.config[:secure] ? "s" : ""}://#{addr}/receive")
9
+ http = Net::HTTP.new(uri.host, uri.port)
10
+ if CityWatch.config[:secure]
11
+ http.use_ssl = true
12
+ http.ssl_version = :SSLv3
13
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
14
+ if File.exists?('/etc/ssl/certs') # Ubuntu
15
+ http.ca_path = '/etc/ssl/certs'
16
+ end
17
+ end
18
+ req = Net::HTTP::Post.new(uri.path)
19
+ req.body = Yajl::Encoder.encode(dat)
20
+ req["Content-Type"] = 'application/json'
21
+ case http.request(req)
22
+ when Net::HTTPSuccess
23
+ puts "Successfully sent to collector." if CityWatch.debug?
24
+ else
25
+ raise Exception
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,86 @@
1
+ module RunCommand
2
+
3
+ def command_output
4
+ unless !supported?
5
+ puts "Running `#{command_line}`..." if CityWatch.debug?
6
+ `#{command_line}`
7
+ else
8
+ puts "Command not present: #{options[:command]} (Skipping)" if CityWatch.debug?
9
+ ""
10
+ end
11
+ end
12
+
13
+ def supported?
14
+ `which #{options[:command]}` != ""
15
+ end
16
+
17
+ def command_line
18
+ @command ||= "#{options[:command]} #{command_line_opts}#{options[:grep] && " | fgrep #{options[:grep]}"}"
19
+ end
20
+
21
+ def command_line_opts
22
+ options.inject([]) do |acc,(k,v)|
23
+ acc << "-#{k} #{v}" unless [:command, :grep].include?(k)
24
+ acc
25
+ end.join(" ")
26
+ end
27
+
28
+ def options
29
+ @opts ||= self.class.options
30
+ end
31
+
32
+ def set_opts(opts={})
33
+ @opts = self.class.options.merge(opts)
34
+ @command = nil
35
+ end
36
+
37
+ def data
38
+ headers = false
39
+ output = []
40
+ command_output.split("\n").map {|line| v = line.split("\s"); v.shift; v }.each do |line|
41
+ if !headers
42
+ headers = line.map {|hdr| hdr.downcase.to_sym}
43
+ next
44
+ end
45
+ next unless headers
46
+ pkt = {}
47
+ line.each_with_index do |itm,idx|
48
+ pkt[headers[idx]] = itm
49
+ end
50
+ output << pkt
51
+ end
52
+ output
53
+ end
54
+
55
+ module ClassMethods
56
+
57
+ def set_opts(opts={})
58
+ @opts = options.merge(opts)
59
+ @command = nil
60
+ end
61
+
62
+ def options
63
+ @opts ||= {}
64
+ end
65
+
66
+ def command(cmd,opts={})
67
+ options[:command] = cmd
68
+ set_opts opts
69
+ end
70
+
71
+ def grep(str)
72
+ options[:grep] = str
73
+ end
74
+
75
+ def data
76
+ new.data
77
+ end
78
+
79
+ end
80
+
81
+ def self.included(base)
82
+ base.extend(ClassMethods)
83
+ Commands.register(base)
84
+ end
85
+
86
+ end
@@ -0,0 +1,16 @@
1
+ module Watchman
2
+
3
+ def data
4
+ {}
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ end
10
+
11
+ def self.included(base)
12
+ base.extend(ClassMethods)
13
+ Watchmen.register(base)
14
+ end
15
+
16
+ end
@@ -0,0 +1,12 @@
1
+ class CPUUsage
2
+
3
+ include Watchman
4
+
5
+ def self.data
6
+ out = MPstat.data.select do |line|
7
+ line[:command][/^Average:/]
8
+ end
9
+ out.length > 0 ? out.first.merge({:summary => [:usr, :idle, :sys]}) : {:nodata => true}
10
+ end
11
+
12
+ end
@@ -0,0 +1,10 @@
1
+ class DiskUsage
2
+
3
+ include Watchman
4
+
5
+ def self.data
6
+ dat = DF.data
7
+ {:partitions => dat, :summary => dat.select {|d| d[:mounted]=="/"}.first[:capacity]}
8
+ end
9
+
10
+ end
File without changes
File without changes
@@ -0,0 +1,18 @@
1
+ class Nginx
2
+
3
+ include Watchman
4
+
5
+ def self.data
6
+ out = PS.data.inject({:masters => [], :workers => []}) do |acc,line|
7
+ if line[:command][/^nginx: master/]
8
+ acc[:masters] << line
9
+ end
10
+ if line[:command][/^nginx: worker/]
11
+ acc[:workers] << line
12
+ end
13
+ acc
14
+ end
15
+ out.merge({:num_masters => out[:masters].count, :num_workers => out[:workers].count, :summary => [:num_masters, :num_workers]})
16
+ end
17
+
18
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,11 @@
1
+ class SystemInfo
2
+
3
+ include Watchman
4
+
5
+ require 'sysinfo'
6
+
7
+ def self.data
8
+ SysInfo.new.to_hash
9
+ end
10
+
11
+ end
@@ -0,0 +1,18 @@
1
+ class Unicorns
2
+
3
+ include Watchman
4
+
5
+ def self.data
6
+ out = PS.data.inject({:masters => [], :workers => []}) do |acc,line|
7
+ if line[:command][/^start master/]
8
+ acc[:masters] << line
9
+ end
10
+ if line[:command][/^start worker/]
11
+ acc[:workers] << line
12
+ end
13
+ acc
14
+ end
15
+ out.merge({:num_masters => out[:masters].count, :num_workers => out[:workers].count, :summary => [:num_masters, :num_workers]})
16
+ end
17
+
18
+ end
@@ -0,0 +1,30 @@
1
+ module Watchmen
2
+
3
+ def self.test
4
+ @watchmen.each do |cmd|
5
+ puts "Running #{cmd.name}:"
6
+ puts cmd.data
7
+ puts "Done."
8
+ end
9
+ end
10
+
11
+ def self.data
12
+ @watchmen.inject({}) do |acc,cmd|
13
+ acc[cmd.name] = cmd.data
14
+ acc
15
+ end
16
+ end
17
+
18
+ def self.register(cls)
19
+ @watchmen ||= []
20
+ @watchmen << cls
21
+ end
22
+
23
+ end
24
+
25
+ require 'city_watch/util/watchman'
26
+ require 'city_watch/watchmen/sysinfo'
27
+ require 'city_watch/watchmen/unicorns'
28
+ require 'city_watch/watchmen/nginx'
29
+ require 'city_watch/watchmen/cpu_usage'
30
+ require 'city_watch/watchmen/disk_usage'
data/lib/city_watch.rb ADDED
@@ -0,0 +1,70 @@
1
+ module CityWatch
2
+
3
+ def self.configure
4
+ require 'optparse'
5
+ options = {
6
+ :config_file => "/etc/#{File.basename($0)}.conf",
7
+ }
8
+ OptionParser.new do |opts|
9
+ opts.banner = "Usage: city_watch [options]"
10
+ opts.on("-c", "--config [FILE]", "Specify config file.") do |config|
11
+ options[:config_file] = config
12
+ end
13
+ end.parse!
14
+
15
+ if File.exists?(options[:config_file])
16
+ require 'yaml'
17
+ config.merge!(YAML.load(IO.read(options[:config_file])) || {})
18
+ end
19
+
20
+ puts config if debug?
21
+
22
+ end
23
+
24
+ def self.config
25
+ @config ||= {
26
+ :watch_collector => "localhost:62000",
27
+ :watch_commander => "localhost:62001",
28
+ :environment => "development",
29
+ :prefix => "CityWatch",
30
+ :redis => {}
31
+ }
32
+ end
33
+
34
+ def self.debug?
35
+ config[:debug] || false
36
+ end
37
+
38
+ def self.unicorn_opts(rackup_opts)
39
+ unless config[:unicorn]
40
+ if config[File.basename($0).to_sym]
41
+ config[:unicorn] = {:port => config[File.basename($0).to_sym].gsub(/.*:/,'')}
42
+ end
43
+ end
44
+ if config[:unicorn]
45
+ if config[:unicorn][:port]
46
+ rackup_opts[:port] = config[:unicorn][:port]
47
+ rackup_opts[:set_listener] = true
48
+ end
49
+ rackup_opts[:daemonize] = config[:unicorn][:config_file] || false
50
+ rackup_opts[:options][:config_file] = config[:unicorn][:config_file] if config[:unicorn][:config_file]
51
+ end
52
+ end
53
+
54
+ def self.redis
55
+ require 'redis'
56
+ @redis ||= ::Redis.new(config_opts(config[:redis], :path, :db, :password))
57
+ end
58
+
59
+ def self.config_opts(conf,*opts)
60
+ opts.inject({}) do |a,k|
61
+ a[k] = conf[k]
62
+ a
63
+ end
64
+ end
65
+
66
+
67
+
68
+ end
69
+
70
+ CityWatch.configure if ARGV[0]
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module CityWatch
2
+ VERSION = "0.3.0"
3
+ end
@@ -0,0 +1,13 @@
1
+ require 'city_watch/collector'
2
+
3
+ CityWatch::Routes.freeze
4
+
5
+ app = Rack::Builder.new do
6
+
7
+ Rack::Utils.key_space_limit = 123456789
8
+
9
+ run CityWatch::Routes
10
+
11
+ end
12
+
13
+ run app
@@ -0,0 +1,13 @@
1
+ require 'city_watch/commander'
2
+
3
+ CityWatch::Routes.freeze
4
+
5
+ app = Rack::Builder.new do
6
+
7
+ Rack::Utils.key_space_limit = 123456789
8
+
9
+ run CityWatch::Routes
10
+
11
+ end
12
+
13
+ run app
metadata ADDED
@@ -0,0 +1,177 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: city-watch
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.3.0
6
+ platform: ruby
7
+ authors:
8
+ - John Bragg
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2013-02-08 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: redis
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: rack
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :runtime
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: rack-mount
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :runtime
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: unicorn
61
+ prerelease: false
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ type: :runtime
69
+ version_requirements: *id005
70
+ - !ruby/object:Gem::Dependency
71
+ name: yajl-ruby
72
+ prerelease: false
73
+ requirement: &id006 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ type: :runtime
80
+ version_requirements: *id006
81
+ - !ruby/object:Gem::Dependency
82
+ name: sysinfo
83
+ prerelease: false
84
+ requirement: &id007 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "0"
90
+ type: :runtime
91
+ version_requirements: *id007
92
+ description: ""
93
+ email:
94
+ - john@cozy.co
95
+ executables:
96
+ - city_watch
97
+ - watch_collector
98
+ - watch_commander
99
+ extensions: []
100
+
101
+ extra_rdoc_files: []
102
+
103
+ files:
104
+ - .DS_Store
105
+ - .gitignore
106
+ - Gemfile
107
+ - Gemfile.lock
108
+ - README
109
+ - Rakefile
110
+ - bin/city_watch
111
+ - bin/watch_collector
112
+ - bin/watch_commander
113
+ - city_watch.gemspec
114
+ - config/city_watch.yml
115
+ - config/watch_collector.yml
116
+ - config/watch_commander.yml
117
+ - lib/city_watch.rb
118
+ - lib/city_watch/agent.rb
119
+ - lib/city_watch/collector.rb
120
+ - lib/city_watch/collector/receive.rb
121
+ - lib/city_watch/commander.rb
122
+ - lib/city_watch/commander/home.rb
123
+ - lib/city_watch/commander/server.rb
124
+ - lib/city_watch/commands.rb
125
+ - lib/city_watch/commands/df.rb
126
+ - lib/city_watch/commands/iostat.rb
127
+ - lib/city_watch/commands/mpstat.rb
128
+ - lib/city_watch/commands/netstat.rb
129
+ - lib/city_watch/commands/ps.rb
130
+ - lib/city_watch/util/collector.rb
131
+ - lib/city_watch/util/run_command.rb
132
+ - lib/city_watch/util/watchman.rb
133
+ - lib/city_watch/watchmen.rb
134
+ - lib/city_watch/watchmen/cpu_usage.rb
135
+ - lib/city_watch/watchmen/disk_usage.rb
136
+ - lib/city_watch/watchmen/memory_profiler.rb
137
+ - lib/city_watch/watchmen/network_throughput.rb
138
+ - lib/city_watch/watchmen/nginx.rb
139
+ - lib/city_watch/watchmen/processes.rb
140
+ - lib/city_watch/watchmen/processor_stats.rb
141
+ - lib/city_watch/watchmen/redis.rb
142
+ - lib/city_watch/watchmen/ruby_gc.rb
143
+ - lib/city_watch/watchmen/server_load.rb
144
+ - lib/city_watch/watchmen/sysinfo.rb
145
+ - lib/city_watch/watchmen/unicorns.rb
146
+ - lib/version.rb
147
+ - watch_collector.ru
148
+ - watch_commander.ru
149
+ homepage: http://cozy.co
150
+ licenses: []
151
+
152
+ post_install_message:
153
+ rdoc_options: []
154
+
155
+ require_paths:
156
+ - lib
157
+ required_ruby_version: !ruby/object:Gem::Requirement
158
+ none: false
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: 1.9.2
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ none: false
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: "0"
169
+ requirements: []
170
+
171
+ rubyforge_project: city-watch
172
+ rubygems_version: 1.8.24
173
+ signing_key:
174
+ specification_version: 3
175
+ summary: Server/process monitoring
176
+ test_files: []
177
+