city-watch 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- city-watch (0.4.0)
4
+ city-watch (0.5.2)
5
5
  rack
6
6
  rack-mount
7
7
  redis
@@ -1 +1,2 @@
1
- :collector: "localhost:62001"
1
+ :debug: true
2
+ :watch_collector: "localhost:62001"
@@ -6,4 +6,6 @@ end
6
6
 
7
7
  ::Routes = CityWatch::Routes
8
8
 
9
+ require 'city_watch/util/collector'
10
+ require 'city_watch/watchmen'
9
11
  require 'city_watch/collector/receive'
@@ -1,25 +1,11 @@
1
- class ResendRequest
1
+ class WatchCollector
2
2
 
3
3
  def call(env)
4
4
 
5
5
  post_data = begin Yajl::Parser.new(:symbolize_keys => true).parse(env["rack.input"].read) || {} rescue {} end
6
6
  post_data[:received_at] = Time.now.to_s
7
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} : 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.merge({:received_at => post_data[:received_at]}))
8
+ Collector.process(post_data)
23
9
 
24
10
  [200,{"Content-Type" => "text/plain"},["Got it!"]]
25
11
  end
@@ -6,5 +6,6 @@ end
6
6
 
7
7
  ::Routes = CityWatch::Routes
8
8
 
9
+ require 'city_watch/watchmen'
9
10
  require 'city_watch/commander/server'
10
11
  require 'city_watch/commander/home'
@@ -5,7 +5,25 @@ class Server
5
5
  parms = Rack::Request.new(env).params.merge(env["rack.routing_args"]).inject({}){|acc,(k,v)| acc[k.to_sym] = v; acc}
6
6
  server = parms[:server]
7
7
 
8
- output = CityWatch.header << '<h1>' << server << "</h1><ul>"
8
+ output = CityWatch.header << '<h1>' << server << "</h1>"
9
+ Watchmen.each do |watchman|
10
+ flags = watchman.get_flags(server)
11
+ alerts = watchman.get_alerts(server,2)
12
+ if (flags && flags.keys.count > 0) || (alerts && alerts.count > 0)
13
+ output << "<h3>" << watchman.name.to_s << "</h3><ul>"
14
+ if flags && flags.keys.count > 0
15
+ output << "<li class=\"alert\"><strong>Flags:</strong> <pre><code>" << Yajl::Encoder.encode(flags,:pretty => true, :indent => " ") << "</code></pre></li>"
16
+ end
17
+ if alerts && alerts.count > 0
18
+ output << "<li class=\"alert\"><strong>Alerts:</strong></li>"
19
+ alerts.each do |alert|
20
+ output << "<li><pre><code>" << Yajl::Encoder.encode(Yajl::Parser.parse(alert),:pretty => true, :indent => " ") << "</code></pre></li>"
21
+ end
22
+ end
23
+ output << "</ul>"
24
+ end
25
+ end
26
+ output << "<ol>"
9
27
  CityWatch.redis.zrevrange("#{CityWatch.config[:prefix]}::#{server}::raw_stats",0,10).each do |update|
10
28
  dat = Yajl::Parser.new(:symbolize_keys => true).parse(update)
11
29
  output << "<li><h4>" << dat[:received_at] << "</h4><ul>"
@@ -14,7 +32,7 @@ class Server
14
32
  end
15
33
  output << "</ul></li>"
16
34
  end
17
- output << "</ul></body></html>"
35
+ output << "</ol></body></html>"
18
36
 
19
37
  [200,{"Content-Type" => "text/html"},[output]]
20
38
  end
@@ -26,4 +26,21 @@ module Collector
26
26
  end
27
27
  end
28
28
 
29
+ def self.process(data)
30
+ rcv_time = Time.now.to_i
31
+ host = data[:hostname]
32
+ CityWatch.redis.sadd "#{CityWatch.config[:prefix]}::known_hosts", host
33
+ CityWatch.redis.zadd "#{CityWatch.config[:prefix]}::#{host}::raw_stats", rcv_time, Yajl::Encoder.encode(data)
34
+
35
+ summary = {}
36
+
37
+ data[:watchmen].each do |watchman,dat|
38
+ if watch_obj = Watchmen.get(watchman)
39
+ status, summary[watchman] = watch_obj.process(dat,rcv_time,host)
40
+ end
41
+ end
42
+
43
+ CityWatch.redis.zadd "#{CityWatch.config[:prefix]}::#{host}::summary", rcv_time, Yajl::Encoder.encode(summary.merge({:received_at => data[:received_at]}))
44
+ end
45
+
29
46
  end
@@ -6,6 +6,135 @@ module Watchman
6
6
 
7
7
  module ClassMethods
8
8
 
9
+ def process(dat,rcv,host)
10
+ @host = host
11
+ @rcv_time = rcv
12
+ CityWatch.redis.zadd "#{CityWatch.config[:prefix]}::#{host}::#{self.name}", rcv_time, Yajl::Encoder.encode(dat.merge({:received_at => dat[:received_at]}))
13
+ if dat[:summary]
14
+ sum = dat[:summary].is_a?(Array) ? dat[:summary].inject({}) {|acc,k| acc[k.to_sym] = dat[k.to_sym]; acc} : dat[:summary]
15
+ CityWatch.redis.zadd "#{CityWatch.config[:prefix]}::#{host}::#{self.name}::summary", rcv_time, Yajl::Encoder.encode(sum)
16
+ end
17
+ run_rules(dat)
18
+ return 0, sum || nil
19
+ end
20
+
21
+ def host
22
+ @host || nil
23
+ end
24
+
25
+ def rcv_time
26
+ @rcv_time || Time.now.to_i
27
+ end
28
+
29
+ def add_rule(name,&block)
30
+ @rules ||= {}
31
+ @rules[name] = block
32
+ end
33
+
34
+ def run_rules(dat)
35
+ @rules.map do |(name,rule)|
36
+ rule.call(dat)
37
+ end if @rules
38
+ end
39
+
40
+ def send_alert(message,dat=nil)
41
+ CityWatch.redis.zadd "#{CityWatch.config[:prefix]}::#{host}::#{self.name}::alerts", rcv_time, Yajl::Encoder.encode({:message => message, :data => dat, :when => rcv_time})
42
+ end
43
+
44
+ def alerts
45
+ @alerts ||= []
46
+ if block_given?
47
+ @alerts.each do |a|
48
+ yield a
49
+ end
50
+ else
51
+ @alerts
52
+ end
53
+ nil
54
+ end
55
+
56
+ def get_alerts(host=host,num=5)
57
+ CityWatch.redis.zrevrange "#{CityWatch.config[:prefix]}::#{host}::#{self.name}::alerts", 0, num - 1
58
+ end
59
+
60
+ def send_alerts!
61
+ @alerts.map do |alert|
62
+ puts "Alert: #{alert.inspect}" #if CityWatch.debug?
63
+ end if @alerts
64
+ end
65
+
66
+ def set_flag(name)
67
+ unless get_flag(name)
68
+ flag_flapped name, :on
69
+ end
70
+ CityWatch.redis.setbit "#{CityWatch.config[:prefix]}::#{host}::#{self.name}::flags", flag_position(name), 1
71
+ end
72
+
73
+ def clear_flag(name)
74
+ if get_flag(name)
75
+ flag_flapped name, :off
76
+ end
77
+ CityWatch.redis.setbit "#{CityWatch.config[:prefix]}::#{host}::#{self.name}::flags", flag_position(name), 0
78
+ end
79
+
80
+ def flag_flapped(name,new_val)
81
+ # should have some event to watch for a flag switching position
82
+ puts "Flag flipped: #{name} -> #{new_val}" #if CityWatch.debug?
83
+ end
84
+
85
+ def get_flag(name,host=host)
86
+ @host = host
87
+ CityWatch.redis.getbit("#{CityWatch.config[:prefix]}::#{host}::#{self.name}::flags", flag_position(name)) ? true : false
88
+ end
89
+
90
+ def get_flags(host=host)
91
+ @host = host
92
+ out = {}
93
+ map = flag_map
94
+ map.each_index do |idx|
95
+ out[map[idx]] = get_flag(map[idx])
96
+ end
97
+ out
98
+ end
99
+
100
+ def flag_map_key
101
+ "#{CityWatch.config[:prefix]}::#{self.name}::flag_map"
102
+ end
103
+
104
+ def flag_map
105
+ CityWatch.redis.lrange flag_map_key, 0, -1
106
+ end
107
+
108
+ def flag_position(name)
109
+ if (map = flag_map) && map.include?(name.to_s)
110
+ map.index(name.to_s)
111
+ else
112
+ new_flag(name)
113
+ end
114
+ end
115
+
116
+ def new_flag(name)
117
+ CityWatch.redis.rpush(flag_map_key, name) - 1
118
+ end
119
+
120
+ def set_default(k,val)
121
+ opts[k] = val
122
+ end
123
+
124
+ def opts
125
+ @options ||= {}
126
+ end
127
+
128
+ def options(*args)
129
+ if args.count > 1
130
+ return args.map {|k| opts[k]}
131
+ else
132
+ return opts[args.first]
133
+ end
134
+ return nil
135
+ end
136
+ alias_method :option, :options
137
+
9
138
  end
10
139
 
11
140
  def self.included(base)
@@ -20,14 +20,13 @@ module Watchmen
20
20
  @watchmen << cls
21
21
  end
22
22
 
23
- def self.add_rule(&block)
24
- @rules ||= []
25
- @rules << block
23
+ def self.get(name)
24
+ @watchmen.select {|w| w.name.to_s == name.to_s }.first
26
25
  end
27
26
 
28
- def self.run_rules(data)
29
- @rules.map do |rule|
30
- rule.call(data)
27
+ def self.each
28
+ @watchmen.each do |w|
29
+ yield w
31
30
  end
32
31
  end
33
32
 
@@ -2,10 +2,23 @@ class DiskUsage
2
2
 
3
3
  include Watchman
4
4
 
5
+ set_default :usage_threshold, 60
6
+
5
7
  def self.data
6
8
  dat = DF.data
7
9
  sum = dat.select {|d| d[:mounted]=="/"}.first
8
10
  {:partitions => dat, :summary => sum[:capacity] || sum["use%".to_sym]}
9
11
  end
10
12
 
13
+ add_rule(:root_usage_high) do |data|
14
+
15
+ if (usage = data[:summary].to_i) && usage > option(:usage_threshold)
16
+ send_alert "Root disk usage is over #{option(:usage_threshold)}% (#{usage}%)", data[:partitions].select {|d| d[:mounted]=="/"}.first
17
+ set_flag :root_disk_over_quota
18
+ else
19
+ clear_flag :root_disk_over_quota
20
+ end
21
+
22
+ end
23
+
11
24
  end
@@ -19,7 +19,7 @@ class Unicorns
19
19
  out.merge({:num_masters => out[:masters].count, :num_workers => out[:workers].count, :summary => [:num_masters, :num_workers]})
20
20
  end
21
21
 
22
- add_rule do |dat|
22
+ add_rule(:high_memory_usage) do |dat|
23
23
 
24
24
  end
25
25
 
@@ -1,3 +1,3 @@
1
1
  module CityWatch
2
- VERSION = "0.5.2"
2
+ VERSION = "0.5.3"
3
3
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: city-watch
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.5.2
5
+ version: 0.5.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - John Bragg
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2013-02-10 00:00:00 Z
13
+ date: 2013-02-11 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: redis