deckard 0.5.10 → 0.5.12

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -16,6 +16,8 @@ Features:
16
16
  * Simple setup via cron
17
17
  * Basic scheduling to silence alerts
18
18
  * Adjustable delay before firing check content requests
19
+ * Basic Chef "tag" lookup support
20
+ * Alert stats database for trending and analysis
19
21
 
20
22
  Usage:
21
23
 
@@ -90,4 +92,35 @@ HTTP content check format:
90
92
  }
91
93
 
92
94
 
93
- For all of these priority and schedule are optional fields in these documents, priority is 0, 1 and 2. 0 is log only, 1 is log and email and 2 is log, email and sms. The schedule is an array containing integers for the hours the alert should be silent. Check out the replication check definition above.
95
+ For all of these priority and schedule are optional fields in these documents, priority is 0, 1 and 2. 0 is log only, 1 is log and email and 2 is log, email and sms. The schedule is an array containing integers for the hours the alert should be silent. Check out the replication check definition above.
96
+
97
+
98
+ For Chef "tag" support you need to install a view in your chef database and configure the url to it in your Deckard config file.
99
+
100
+ function(doc) {
101
+ if (doc.chef_type != 'node') return;
102
+
103
+ emit(doc.automatic.ec2 ? doc.automatic.ec2.public_hostname : doc.automatic.fqdn, doc.normal.tags[0]);
104
+ }
105
+
106
+
107
+ Regarding alert stats, just create a stats database and puts it's name in the config file. When alerts happen you should begin to see documents get added. By itself it isn't all that helpful, analysis is the key. Here is a basic "counts" design document to get you started, it will give you stats about the different kinds of alerts you are having.
108
+
109
+ {
110
+ "_id": "_design/counts",
111
+ "language": "javascript",
112
+ "views": {
113
+ "by_type": {
114
+ "map": "function(doc) {\n emit(doc.type, 1);\n}",
115
+ "reduce": "_count"
116
+ },
117
+ "by_url": {
118
+ "map": "function(doc) {\n emit(doc.url, 1);\n}",
119
+ "reduce": "_count"
120
+ },
121
+ "by_error": {
122
+ "map": "function(doc) {\n emit(doc.error, 1);\n}",
123
+ "reduce": "_count"
124
+ }
125
+ }
126
+ }
@@ -31,3 +31,6 @@ rep_check:
31
31
  notifo:
32
32
  user: "username"
33
33
  apikey: "password"
34
+
35
+ stats:
36
+ db: "monitor_stats"
@@ -31,3 +31,10 @@ rep_check:
31
31
  notifo:
32
32
  user: "username"
33
33
  apikey: "password"
34
+
35
+ stats:
36
+ db: "monitor_stats"
37
+
38
+ chef:
39
+ enabled: true
40
+ url:"http://localhost:5984/chef/_design/nodes/_view/hostnames"
@@ -22,7 +22,9 @@ require 'deckard/config'
22
22
  require 'deckard/log'
23
23
  require 'deckard/ec2'
24
24
  require 'deckard/monitoring'
25
+ require 'deckard/stats'
25
26
  require 'deckard/util'
27
+ require 'deckard/chef'
26
28
 
27
29
 
28
30
  class Deckard
@@ -0,0 +1,31 @@
1
+ class Deckard
2
+ class Chef
3
+
4
+ def self.get_node_info(url)
5
+
6
+ info = false
7
+
8
+ if Deckard::Config.chef_enabled
9
+
10
+ chef_url = Deckard::Config.chef_url
11
+
12
+ begin
13
+ chef_nodes_json = RestClient.get(chef_url)
14
+ chef_nodes = JSON.parse(chef_nodes_json)
15
+
16
+ chef_nodes["rows"].each do |row|
17
+ if row["key"] == URI.parse(url).host
18
+ info = row["value"]
19
+ end
20
+ end
21
+
22
+ rescue Exception => e
23
+ Deckard::Log.error("Could not get chef tag for alert on #{url} due to #{e}")
24
+ end
25
+ end
26
+
27
+ info
28
+ end
29
+
30
+ end
31
+ end
@@ -1,6 +1,13 @@
1
1
  class Deckard
2
2
  class Config
3
- monitor_config = YAML.load(File.open(ARGV[1]))
3
+
4
+ if ARGV[0]
5
+ monitor_config = YAML.load(File.open(ARGV[1]))
6
+ else
7
+ puts "No config file specified"
8
+ abort
9
+ end
10
+
4
11
  extend Mixlib::Config
5
12
  configure do |c|
6
13
  c[:email_to] = monitor_config["defaults"]["email_to"]
@@ -31,6 +38,12 @@ class Deckard
31
38
 
32
39
  c[:notifo_user] = monitor_config["notifo"]["user"]
33
40
  c[:notifo_apikey] = monitor_config["notifo"]["apikey"]
41
+
42
+ c[:stats_db] = monitor_config["stats"]["db"]
43
+
44
+ c[:chef_url] = monitor_config["chef"]["url"]
45
+ c[:chef_enabled] = monitor_config["chef"]["enabled"]
46
+
34
47
  end
35
48
  end
36
49
  end
@@ -11,10 +11,20 @@ class Deckard
11
11
  sleep(Deckard::Config.content_check_retry_interval)
12
12
  retry if (retries += 1) < retry_count
13
13
  if retries >= retry_count
14
- subject = "ALERT :: Check Content Failed on #{url}"
15
- body = "#{Time.now} :: #{e} :: #{url}"
14
+
15
+ node_info = Deckard::Chef.get_node_info(url)
16
+
17
+ if node_info
18
+ subject = "ALERT :: #{node_info} :: #{e}"
19
+ body = "#{Time.now} :: #{url}"
20
+ else
21
+ subject = "ALERT :: #{url} :: #{e}"
22
+ body = "#{Time.now} :: #{url} :: #{e}"
23
+ end
24
+
16
25
  log = subject + " -- " + body
17
26
  Deckard::Util.alert(priority, subject, body, log, schedule, url)
27
+ Deckard::Stats.alert(priority, e, url, "contentcheck")
18
28
  check = false
19
29
  end
20
30
  else
@@ -22,10 +32,20 @@ class Deckard
22
32
  if result.include?(content)
23
33
  Deckard::Log.info("PASS :: Found text \"#{content}\" on #{url}")
24
34
  else
25
- subject = "ALERT :: Check Content Failed on #{url}"
26
- body = "#{Time.now} :: Could not find text \"#{content}\" at #{url}"
35
+
36
+ node_info = Deckard::Chef.get_node_info(url)
37
+
38
+ if node_info
39
+ subject = "ALERT :: #{node_info} :: content missing"
40
+ body = "#{Time.now} :: Could not find text \"#{content}\" at #{url}"
41
+ else
42
+ subject = "ALERT :: #{url} :: content missing"
43
+ body = "#{Time.now} :: Could not find text \"#{content}\" at #{url}"
44
+ end
45
+
27
46
  log = subject + " -- " + body
28
47
  Deckard::Util.alert(priority, subject, body, log, schedule, url)
48
+ Deckard::Stats.alert(priority, "nocontent", url, "contentcheck")
29
49
  check = false
30
50
  end
31
51
  end
@@ -49,6 +69,7 @@ class Deckard
49
69
  body = "Master: #{master_url} => Slave: #{slave_url} : off by #{doc_count_diff}"
50
70
  log = subject + " -- " + body
51
71
  Deckard::Util.alert(priority, subject, body, log, schedule, master_url)
72
+ Deckard::Stats.alert(priority, "#{doc_count_diff}", url, "replication")
52
73
  else
53
74
  Deckard::Log.info("PASS :: Replication for #{name} is OK (#{doc_count_diff})")
54
75
  end
@@ -64,7 +85,8 @@ class Deckard
64
85
  body = "#{region} : #{elastic_ip} => #{primary_instance_id} / #{secondary_instance_id} attempting failover!"
65
86
  log = subject + " " + body
66
87
  Deckard::Util.alert(priority, subject, body, log, schedule, "http://#{elastic_ip}")
67
-
88
+ Deckard::Stats.alert(priority, "unknown", "http://#{elastic_ip}", "failover")
89
+
68
90
  instance_id = Deckard::Ec2.get_association(region, elastic_ip)
69
91
 
70
92
  if Deckard::Ec2.disassociate_address(region, elastic_ip)
@@ -0,0 +1,24 @@
1
+ class Deckard
2
+ class Stats
3
+
4
+ def self.alert(priority, error, url, type)
5
+ db_name = Deckard::Config.stats_db
6
+ db_user = Deckard::Config.db_user
7
+ db_password = Deckard::Config.db_password
8
+ db_host = Deckard::Config.db_host
9
+ db_port = Deckard::Config.db_port
10
+
11
+ db_url = "http://#{db_user}:#{db_password}@#{db_host}:#{db_port}/#{db_name}"
12
+
13
+ alert_info = {"priority" => priority, "error" => error, "url" => url, "timestamp" => Time.now.utc.iso8601, "type" => type}
14
+
15
+ begin
16
+ RestClient.post("#{db_url}", alert_info.to_json, "Content-Type" => "application/json")
17
+ Deckard::Log.info("Added stats for alert on #{url}")
18
+ rescue Exception => e
19
+ Deckard::Log.error("Could not add stats for alert on #{url} due to #{e}")
20
+ end
21
+ end
22
+
23
+ end
24
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deckard
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 5
9
- - 10
10
- version: 0.5.10
9
+ - 12
10
+ version: 0.5.12
11
11
  platform: ruby
12
12
  authors:
13
13
  - joe williams
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-13 00:00:00 -08:00
18
+ date: 2011-04-08 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -128,10 +128,12 @@ extra_rdoc_files:
128
128
  - README
129
129
  files:
130
130
  - bin/deckard
131
+ - lib/deckard/chef.rb
131
132
  - lib/deckard/config.rb
132
133
  - lib/deckard/ec2.rb
133
134
  - lib/deckard/log.rb
134
135
  - lib/deckard/monitoring.rb
136
+ - lib/deckard/stats.rb
135
137
  - lib/deckard/util.rb
136
138
  - lib/deckard.rb
137
139
  - config/deckard-test.yml