aws-alert-monitor 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +5 -0
- data/README.md +30 -1
- data/lib/aws-alert-monitor.rb +7 -0
- data/lib/aws-alert-monitor/alert.rb +19 -23
- data/lib/aws-alert-monitor/emailer.rb +33 -0
- data/lib/aws-alert-monitor/event.rb +32 -0
- data/lib/aws-alert-monitor/event_classifier.rb +35 -0
- data/lib/aws-alert-monitor/events.rb +3 -0
- data/lib/aws-alert-monitor/events/auto_scaling_notification.rb +23 -0
- data/lib/aws-alert-monitor/events/cloud_watch_alarm.rb +48 -0
- data/lib/aws-alert-monitor/events/unknown.rb +21 -0
- data/lib/aws-alert-monitor/version.rb +1 -1
- data/spec/alert_spec.rb +42 -13
- data/spec/emailer_spec.rb +29 -0
- data/spec/event_classifier_spec.rb +36 -0
- data/spec/event_spec.rb +29 -0
- data/spec/events/auto_scaling_notification_spec.rb +33 -0
- data/spec/events/cloud_watch_alarm_spec.rb +30 -0
- data/spec/events/unknown_spec.rb +28 -0
- data/spec/fixtures/asg_instance_launch.json +12 -0
- data/spec/fixtures/cloud_watch_alarm.json +12 -0
- data/spec/helpers/fixtures.rb +8 -0
- data/spec/spec_helper.rb +4 -0
- metadata +35 -10
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -5,8 +5,9 @@
|
|
5
5
|
AWS Alert Monitor listenting to an SQS queue for alarms and sends email via SES based on rules applied in ~/.aws-alert-monitor.yml to those alerts.
|
6
6
|
|
7
7
|
## Installation
|
8
|
-
|
8
|
+
```
|
9
9
|
gem install aws-alert-monitor
|
10
|
+
```
|
10
11
|
|
11
12
|
## Usage
|
12
13
|
|
@@ -37,6 +38,34 @@ app2:
|
|
37
38
|
destination: user@escalation.com
|
38
39
|
```
|
39
40
|
|
41
|
+
### Supported Event Types
|
42
|
+
Currently, this gem supports the following event types:
|
43
|
+
|
44
|
+
#### Auto Scaling
|
45
|
+
* autoscaling:EC2_INSTANCE_LAUNCH
|
46
|
+
* autoscaling:EC2_INSTANCE_LAUNCH_ERROR
|
47
|
+
* autoscaling:EC2_INSTANCE_TERMINATE
|
48
|
+
* autoscaling:EC2_INSTANCE_TERMINATE_ERROR
|
49
|
+
|
50
|
+
#### CloudWatch
|
51
|
+
Cloud watch support is somewhat generic. The event pattern is:
|
52
|
+
```
|
53
|
+
cloudwatch:$metric_namespace-$metric_name
|
54
|
+
```
|
55
|
+
|
56
|
+
For example:
|
57
|
+
```
|
58
|
+
cloudwatch:AWS/SQS-ApproximateNumberOfMessagesVisible
|
59
|
+
```
|
60
|
+
|
61
|
+
#### Unknown
|
62
|
+
If a message does not match one of the above types, then it will be classified as unknown.
|
63
|
+
|
64
|
+
You can control the notification of these messages with:
|
65
|
+
```
|
66
|
+
unknown
|
67
|
+
```
|
68
|
+
|
40
69
|
## Contributing
|
41
70
|
|
42
71
|
1. Fork it
|
data/lib/aws-alert-monitor.rb
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
require "aws-alert-monitor/alert"
|
2
2
|
require "aws-alert-monitor/aws"
|
3
3
|
require "aws-alert-monitor/config"
|
4
|
+
require "aws-alert-monitor/emailer"
|
5
|
+
require "aws-alert-monitor/event"
|
6
|
+
require "aws-alert-monitor/event_classifier"
|
7
|
+
require "aws-alert-monitor/events"
|
8
|
+
require "aws-alert-monitor/events/auto_scaling_notification"
|
9
|
+
require "aws-alert-monitor/events/cloud_watch_alarm"
|
10
|
+
require "aws-alert-monitor/events/unknown"
|
4
11
|
require "aws-alert-monitor/logger"
|
5
12
|
require "aws-alert-monitor/parser"
|
6
13
|
require "aws-alert-monitor/version"
|
@@ -13,7 +13,7 @@ module AwsAlertMonitor
|
|
13
13
|
@events = args[:events]
|
14
14
|
@message = args[:message]
|
15
15
|
|
16
|
-
unless process_message
|
16
|
+
unless process_message
|
17
17
|
@logger.error "Unable to process message."
|
18
18
|
return false
|
19
19
|
end
|
@@ -32,47 +32,43 @@ module AwsAlertMonitor
|
|
32
32
|
|
33
33
|
if @message_destination
|
34
34
|
@logger.info "Sending alert to #{@message_destination}."
|
35
|
-
|
35
|
+
send_email
|
36
36
|
else
|
37
37
|
@logger.info "Destination not set, no message sent."
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
def email_options
|
42
|
-
{
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
:body => {
|
48
|
-
:text => {
|
49
|
-
:data => @message_data
|
50
|
-
}
|
51
|
-
}
|
52
|
-
}
|
42
|
+
{
|
43
|
+
'body' => @message_data,
|
44
|
+
'from' => @message_source,
|
45
|
+
'subject' => @message_subject,
|
46
|
+
'to' => Array(@message_destination)
|
53
47
|
}
|
54
48
|
end
|
55
49
|
|
56
|
-
def
|
50
|
+
def event_classifier
|
51
|
+
AwsAlertMonitor::EventClassifier.new @message
|
52
|
+
end
|
53
|
+
|
54
|
+
def process_message
|
57
55
|
begin
|
58
|
-
|
59
|
-
message_details = JSON.parse message_body['Message']
|
56
|
+
event = event_classifier.event
|
60
57
|
rescue JSON::ParserError => e
|
61
58
|
@logger.error e.message
|
62
59
|
return false
|
63
60
|
end
|
64
61
|
|
65
|
-
@
|
66
|
-
@
|
67
|
-
@
|
68
|
-
@message_subject = message_body['Subject']
|
69
|
-
@message_data = "#{@name} received alert: \n\n #{@message_description} \n\n #{@message_cause}"
|
62
|
+
@message_event = event.type
|
63
|
+
@message_subject = event.subject
|
64
|
+
@message_data = "#{@name} #{event.body}"
|
70
65
|
|
71
66
|
true
|
72
67
|
end
|
73
68
|
|
74
|
-
def
|
75
|
-
|
69
|
+
def send_email
|
70
|
+
AwsAlertMonitor::Emailer.new(email_options).send_email
|
76
71
|
end
|
72
|
+
|
77
73
|
end
|
78
74
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module AwsAlertMonitor
|
2
|
+
|
3
|
+
class Emailer
|
4
|
+
|
5
|
+
def initialize(args)
|
6
|
+
@body = args['body']
|
7
|
+
@emailer = args['emailer']
|
8
|
+
@from = args['from']
|
9
|
+
@subject = args['subject']
|
10
|
+
@to = Array(args['to'])
|
11
|
+
end
|
12
|
+
|
13
|
+
def send_email
|
14
|
+
emailer.send_email email_options
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def email_options
|
19
|
+
{
|
20
|
+
:source => @from,
|
21
|
+
:destination => { :to_addresses => @to },
|
22
|
+
:message => { :subject => { :data => @subject },
|
23
|
+
:body => { :text => { :data => @body } } }
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def emailer
|
28
|
+
@emailer ||= AwsAlertMonitor::AWS::SES.new
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module AwsAlertMonitor
|
2
|
+
|
3
|
+
class Event
|
4
|
+
|
5
|
+
attr_reader :message_data
|
6
|
+
attr_reader :raw_data
|
7
|
+
|
8
|
+
def initialize(message)
|
9
|
+
@raw_data = JSON.parse(message)
|
10
|
+
@message_data = determine_message_data
|
11
|
+
end
|
12
|
+
|
13
|
+
def body
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
|
17
|
+
def subject
|
18
|
+
@raw_data['Subject']
|
19
|
+
end
|
20
|
+
|
21
|
+
def type
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def determine_message_data
|
27
|
+
JSON.parse(@raw_data.fetch('Message', '{}'))
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module AwsAlertMonitor
|
2
|
+
|
3
|
+
class EventClassifier
|
4
|
+
|
5
|
+
def initialize(message)
|
6
|
+
@message = message
|
7
|
+
end
|
8
|
+
|
9
|
+
def event
|
10
|
+
event_subjects_classes.each do |subject, klass|
|
11
|
+
return klass.new(@message) if generic_event_subject =~ subject
|
12
|
+
end
|
13
|
+
|
14
|
+
unknown_event_class.new @message
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def event_subjects_classes
|
19
|
+
{
|
20
|
+
/\AAuto Scaling: / => AwsAlertMonitor::Events::AutoScalingNotification,
|
21
|
+
/\AALARM: / => AwsAlertMonitor::Events::CloudWatchAlarm
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def generic_event_subject
|
26
|
+
AwsAlertMonitor::Event.new(@message).subject
|
27
|
+
end
|
28
|
+
|
29
|
+
def unknown_event_class
|
30
|
+
AwsAlertMonitor::Events::Unknown
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module AwsAlertMonitor
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class AutoScalingNotification < Event
|
5
|
+
|
6
|
+
def body
|
7
|
+
cause = message_data['Cause']
|
8
|
+
description = message_data['Description']
|
9
|
+
"received an alert: \n\n #{description} \n\n #{cause}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def subject
|
13
|
+
"Alert: #{raw_data['Subject']}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def type
|
17
|
+
message_data['Event']
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module AwsAlertMonitor
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class CloudWatchAlarm < Event
|
5
|
+
|
6
|
+
def body
|
7
|
+
message = "received an alert: \n\n #{alarm_description} \n\n"
|
8
|
+
message << " #{alarm_new_state_reason} \n\n"
|
9
|
+
message << " At #{alarm_state_change_time}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def subject
|
13
|
+
"Alert: #{alarm_name}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def type
|
17
|
+
"cloudwatch:#{metric_namespace}-#{metric_name}"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def alarm_description
|
22
|
+
message_data['AlarmDescription']
|
23
|
+
end
|
24
|
+
|
25
|
+
def alarm_name
|
26
|
+
message_data['AlarmName']
|
27
|
+
end
|
28
|
+
|
29
|
+
def alarm_new_state_reason
|
30
|
+
message_data['NewStateReason']
|
31
|
+
end
|
32
|
+
|
33
|
+
def alarm_state_change_time
|
34
|
+
message_data['StateChangeTime']
|
35
|
+
end
|
36
|
+
|
37
|
+
def metric_name
|
38
|
+
message_data['Trigger']['MetricName']
|
39
|
+
end
|
40
|
+
|
41
|
+
def metric_namespace
|
42
|
+
message_data['Trigger']['Namespace']
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module AwsAlertMonitor
|
2
|
+
module Events
|
3
|
+
|
4
|
+
class Unknown < Event
|
5
|
+
|
6
|
+
def body
|
7
|
+
"received an alert: \n\n #{raw_data.to_s}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def subject
|
11
|
+
"Alert: unknown type"
|
12
|
+
end
|
13
|
+
|
14
|
+
def type
|
15
|
+
'unknown'
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/spec/alert_spec.rb
CHANGED
@@ -2,33 +2,62 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe AwsAlertMonitor::Alert do
|
4
4
|
before do
|
5
|
-
@message =
|
6
|
-
@options = {:name
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
5
|
+
@message = fixture_file 'asg_instance_launch.json'
|
6
|
+
@options = { :name => 'test app',
|
7
|
+
:message => @message,
|
8
|
+
:events => {
|
9
|
+
'autoscaling:EC2_INSTANCE_LAUNCH' => {
|
10
|
+
'email' => {
|
11
|
+
'source' => 'bob_weaver@intuit.com',
|
12
|
+
'destination' => 'brett_weaver@intuit.com'
|
13
|
+
} } }
|
14
|
+
}
|
15
|
+
|
16
|
+
@logger_stub = stub 'logger', :debug => true,
|
17
|
+
:info => true,
|
18
|
+
:error => true
|
19
|
+
@config_stub = stub 'config', :logger => @logger_stub
|
20
|
+
@emailer_mock = mock 'emailer'
|
21
|
+
|
22
|
+
@data = { 'body' => "test app received alert: foo",
|
23
|
+
'from' => 'bob_weaver@intuit.com',
|
24
|
+
'subject' => "Alert: Auto Scaling: launch for bar",
|
25
|
+
'to' => ['brett_weaver@intuit.com'] }
|
13
26
|
AwsAlertMonitor::Config.stub :new => @config_stub
|
14
27
|
@alert = AwsAlertMonitor::Alert.new :config => @config_stub
|
15
28
|
end
|
16
29
|
|
17
30
|
it "should process the given message against known events" do
|
18
|
-
@
|
19
|
-
|
31
|
+
@event_stub = stub 'event', :body => "received alert: foo",
|
32
|
+
:subject => "Alert: Auto Scaling: launch for bar",
|
33
|
+
:type => 'autoscaling:EC2_INSTANCE_LAUNCH'
|
34
|
+
@classifier_stub = stub 'classifier', :event => @event_stub
|
35
|
+
AwsAlertMonitor::EventClassifier.should_receive(:new).
|
36
|
+
with(@message).
|
37
|
+
and_return(@classifier_stub)
|
38
|
+
AwsAlertMonitor::Emailer.should_receive(:new).
|
39
|
+
with(@data).
|
40
|
+
and_return(@emailer_mock)
|
41
|
+
@emailer_mock.should_receive :send_email
|
20
42
|
@alert.process @options
|
21
43
|
end
|
22
44
|
|
23
45
|
it "should return false if the given message is invalid JSON" do
|
24
|
-
@
|
46
|
+
@emailer_mock.should_not_receive(:send_email)
|
25
47
|
@options[:message] = 'invalid stuff'
|
26
48
|
@alert.process(@options).should be_false
|
27
49
|
end
|
28
50
|
|
29
51
|
it "should not send the message if the destination is nil" do
|
30
|
-
@
|
31
|
-
@options = {:name
|
52
|
+
@emailer_mock.should_not_receive(:send_email)
|
53
|
+
@options = { :name => 'test app',
|
54
|
+
:message => @message,
|
55
|
+
:events => {
|
56
|
+
'autoscaling:EC2_INSTANCE_LAUNCH' => {
|
57
|
+
'email' => { 'source' => 'brett_weaver@intuit.com' }
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
32
61
|
@alert.process(@options).should be_true
|
33
62
|
end
|
34
63
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AwsAlertMonitor::Emailer do
|
4
|
+
|
5
|
+
describe 'send_email' do
|
6
|
+
let(:ses_mock) { mock 'ses' }
|
7
|
+
let(:args) do
|
8
|
+
{ 'body' => 'foo bar',
|
9
|
+
'emailer' => ses_mock,
|
10
|
+
'from' => 'root@example.com',
|
11
|
+
'subject' => 'my subject',
|
12
|
+
'to' => ['bob@example.com', 'joe@example.com'] }
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'sends the email with the correct info' do
|
16
|
+
data = { :source => args['from'],
|
17
|
+
:destination => { :to_addresses => args['to'] },
|
18
|
+
:message => {
|
19
|
+
:subject => { :data => args['subject'] },
|
20
|
+
:body => { :text => { :data => args['body']}} }
|
21
|
+
}
|
22
|
+
ses_mock.should_receive(:send_email).with(data)
|
23
|
+
|
24
|
+
AwsAlertMonitor::Emailer.new(args).send_email
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AwsAlertMonitor::EventClassifier do
|
4
|
+
|
5
|
+
describe 'event' do
|
6
|
+
|
7
|
+
context 'auto scaling notification' do
|
8
|
+
let(:message) { fixture_file('asg_instance_launch.json') }
|
9
|
+
let(:classifier) { AwsAlertMonitor::EventClassifier.new message }
|
10
|
+
|
11
|
+
it 'returns the appropriate event object' do
|
12
|
+
classifier.event.type.should == 'autoscaling:EC2_INSTANCE_LAUNCH'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'cloud watch alarm' do
|
17
|
+
let(:message) { fixture_file('cloud_watch_alarm.json') }
|
18
|
+
let(:classifier) { AwsAlertMonitor::EventClassifier.new message }
|
19
|
+
|
20
|
+
it 'returns the appropriate event object' do
|
21
|
+
classifier.event.type.should == 'cloudwatch:AWS/SQS-ApproximateNumberOfMessagesVisible'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'unknown' do
|
26
|
+
let(:message) { '{ "foo": "bar" }'}
|
27
|
+
let(:classifier) { AwsAlertMonitor::EventClassifier.new message }
|
28
|
+
|
29
|
+
it 'returns the appropriate event object' do
|
30
|
+
classifier.event.type.should == 'unknown'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/spec/event_spec.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AwsAlertMonitor::Event do
|
4
|
+
let(:event) do
|
5
|
+
data = '{ "foo": "bar", "Message": "{ \"a\": \"b\" }", "Subject": "foo subject"}'
|
6
|
+
AwsAlertMonitor::Event.new data
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'raw_data' do
|
10
|
+
it 'provides the raw parsed data' do
|
11
|
+
event.raw_data.should == { 'foo' => 'bar',
|
12
|
+
'Message' => '{ "a": "b" }',
|
13
|
+
'Subject' => 'foo subject' }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'subject' do
|
18
|
+
it 'provides the subject' do
|
19
|
+
event.subject.should == 'foo subject'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'message_data' do
|
24
|
+
it 'provides the message data' do
|
25
|
+
event.message_data.should == { 'a' => 'b' }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AwsAlertMonitor::Events::AutoScalingNotification do
|
4
|
+
|
5
|
+
let(:message) { fixture_file('asg_instance_launch.json') }
|
6
|
+
let(:event) { AwsAlertMonitor::Events::AutoScalingNotification.new message }
|
7
|
+
|
8
|
+
describe 'body' do
|
9
|
+
it 'returns the body' do
|
10
|
+
data = "received an alert: \n\n "
|
11
|
+
data << "Launching a new EC2 instance: i-d6a2cb8f \n\n "
|
12
|
+
data << "At 2012-11-29T16:39:05Z an instance was started in response to a"
|
13
|
+
data << " difference between desired and actual capacity,"
|
14
|
+
data << " increasing the capacity from 0 to 1."
|
15
|
+
event.body.should == data
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'subject' do
|
20
|
+
it 'returns the subject' do
|
21
|
+
data = 'Alert: Auto Scaling: launch for group '
|
22
|
+
data << '"lc-pod-2-qa-1-app-1-Instances-XCYGCEQC0H02"'
|
23
|
+
event.subject.should == data
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'type' do
|
28
|
+
it 'returns the type' do
|
29
|
+
event.type.should == 'autoscaling:EC2_INSTANCE_LAUNCH'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AwsAlertMonitor::Events::CloudWatchAlarm do
|
4
|
+
|
5
|
+
let(:message) { fixture_file('cloud_watch_alarm.json') }
|
6
|
+
let(:event) { AwsAlertMonitor::Events::CloudWatchAlarm.new message }
|
7
|
+
|
8
|
+
describe 'body' do
|
9
|
+
it 'returns the body' do
|
10
|
+
data = "received an alert: \n\n "
|
11
|
+
data << "Queue depth alarm for LC notification queue \n\n "
|
12
|
+
data << "Threshold Crossed: 1 datapoint (3.0) was greater than the threshold (2.0). \n\n "
|
13
|
+
data << "At 2013-01-30T22:00:50.630+0000"
|
14
|
+
event.body.should == data
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'subject' do
|
19
|
+
it 'returns the subject' do
|
20
|
+
event.subject.should == 'Alert: lc-pod-2-dev-1-alarm-1-QueueDepthAlarm-706AQ69BSSN1'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'type' do
|
25
|
+
it 'returns the type' do
|
26
|
+
event.type.should == 'cloudwatch:AWS/SQS-ApproximateNumberOfMessagesVisible'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AwsAlertMonitor::Events::Unknown do
|
4
|
+
|
5
|
+
let(:message) { '{"foo": "bar"}' }
|
6
|
+
let(:event) { AwsAlertMonitor::Events::Unknown.new message }
|
7
|
+
|
8
|
+
describe 'body' do
|
9
|
+
it 'returns the body' do
|
10
|
+
data = "received an alert: \n\n "
|
11
|
+
data << JSON.parse(message).to_s
|
12
|
+
event.body.should == data
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'subject' do
|
17
|
+
it 'returns the subject' do
|
18
|
+
event.subject.should == 'Alert: unknown type'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'type' do
|
23
|
+
it 'returns the type' do
|
24
|
+
event.type.should == 'unknown'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"Type": "Notification",
|
3
|
+
"MessageId": "3c784ce1-22ec-5eec-9040-05d0b0c63fb8",
|
4
|
+
"TopicArn": "arn:aws:sns:us-west-1:187130254137:lc-pod-2-qa-1-app-1-SnsTopic-A2LI3FXD37V1",
|
5
|
+
"Subject": "Auto Scaling: launch for group \"lc-pod-2-qa-1-app-1-Instances-XCYGCEQC0H02\"",
|
6
|
+
"Message": "{\"StatusCode\":\"InProgress\",\"Service\":\"AWS Auto Scaling\",\"AutoScalingGroupName\":\"lc-pod-2-qa-1-app-1-Instances-XCYGCEQC0H02\",\"Description\":\"Launching a new EC2 instance: i-d6a2cb8f\",\"ActivityId\":\"840ac52b-36a7-419f-8378-f29bc8d477e8\",\"Event\":\"autoscaling:EC2_INSTANCE_LAUNCH\",\"Details\":{},\"AutoScalingGroupARN\":\"arn:aws:autoscaling:us-west-1:187130254137:autoScalingGroup:c96912e4-0633-4e9b-8060-f0a92b1f4fb1:autoScalingGroupName/lc-pod-2-qa-1-app-1-Instances-XCYGCEQC0H02\",\"Progress\":50,\"Time\":\"2012-11-29T16:40:10.204Z\",\"AccountId\":\"187130254137\",\"RequestId\":\"840ac52b-36a7-419f-8378-f29bc8d477e8\",\"StatusMessage\":\"\",\"EndTime\":\"2012-11-29T16:40:10.204Z\",\"EC2InstanceId\":\"i-d6a2cb8f\",\"StartTime\":\"2012-11-29T16:39:05.602Z\",\"Cause\":\"At 2012-11-29T16:39:05Z an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 0 to 1.\"}",
|
7
|
+
"Timestamp": "2012-11-29T16:40:10.246Z",
|
8
|
+
"SignatureVersion": "1",
|
9
|
+
"Signature": "vVWFMUbWyfBSfo8vPCBDdrdXB1ocGZz+n4cO4FEIoczOTHgrcNY8tqYLojlTQuQZCdk7f5qPI1XJxfGS1NIs2LmsBq6oEow2qXrBQlvUXxUDMIvoWoqj6a+yjM4ICbmStdlcFVREW/0u/YO7l/se5q6KUqol4q6Vb+c+xohwR78=",
|
10
|
+
"SigningCertURL": "https://sns.us-west-1.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem",
|
11
|
+
"UnsubscribeURL": "https://sns.us-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-west-1:187130254137:lc-pod-2-qa-1-app-1-SnsTopic-A2LI3FXD37V1:1e723d7a-abf4-46a7-b73e-d6d3d3a90959"
|
12
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"Type" : "Notification",
|
3
|
+
"MessageId" : "0d03bb25-7963-586d-a3f8-f2a6e3313939",
|
4
|
+
"TopicArn" : "arn:aws:sns:us-west-1:187130254137:lc-pod-2-dev-1-sns-1-SnsTopic-DGIM8J5SCVDG",
|
5
|
+
"Subject" : "ALARM: \"lc-pod-2-dev-1-alarm-1-QueueDepthAlarm-706AQ69BSSN1\" in US - N.California",
|
6
|
+
"Message" : "{\"AlarmName\":\"lc-pod-2-dev-1-alarm-1-QueueDepthAlarm-706AQ69BSSN1\",\"AlarmDescription\":\"Queue depth alarm for LC notification queue\",\"AWSAccountId\":\"187130254137\",\"NewStateValue\":\"ALARM\",\"NewStateReason\":\"Threshold Crossed: 1 datapoint (3.0) was greater than the threshold (2.0).\",\"StateChangeTime\":\"2013-01-30T22:00:50.630+0000\",\"Region\":\"US - N.California\",\"OldStateValue\":\"OK\",\"Trigger\":{\"MetricName\":\"ApproximateNumberOfMessagesVisible\",\"Namespace\":\"AWS/SQS\",\"Statistic\":\"SUM\",\"Unit\":null,\"Dimensions\":[{\"name\":\"QueueName\",\"value\":\"lc-pod-2-dev-1-queue-1-Queue-C32KYYWGN6DB\"}],\"Period\":300,\"EvaluationPeriods\":1,\"ComparisonOperator\":\"GreaterThanThreshold\",\"Threshold\":2.0}}",
|
7
|
+
"Timestamp" : "2013-01-30T22:00:50.696Z",
|
8
|
+
"SignatureVersion" : "1",
|
9
|
+
"Signature" : "o/vsl17zKfS66pxv8r01L1uTdEcJucoE5IOIm/p+PlevVx9DY9QoBr8Yg0JQy9H3LRNHqM+Lp8z9L91H5Fw5FHn0lRS3n1m0i6C7pjqXWvmXl8SFHka2xyL72oTolKuCI5yzW3n4KC0gVyZgJj2nKO3CBR0uGoFGbqLX2tleoaI=",
|
10
|
+
"SigningCertURL" : "https://sns.us-west-1.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem",
|
11
|
+
"UnsubscribeURL" : "https://sns.us-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-west-1:187130254137:lc-pod-2-dev-1-sns-1-SnsTopic-DGIM8J5SCVDG:01eb3494-4be6-4b06-b3b2-a59a0d19d1ad"
|
12
|
+
}
|
data/spec/spec_helper.rb
CHANGED
@@ -2,7 +2,11 @@ require 'rubygems'
|
|
2
2
|
require 'bundler/setup'
|
3
3
|
|
4
4
|
require 'aws-alert-monitor'
|
5
|
+
Dir[File.expand_path(File.join(File.dirname(__FILE__),'helpers', '*.rb'))].each do |f|
|
6
|
+
require f
|
7
|
+
end
|
5
8
|
|
6
9
|
RSpec.configure do |config|
|
7
10
|
#spec config
|
11
|
+
config.include Fixtures
|
8
12
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-alert-monitor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &70342338349940 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70342338349940
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &70342338349440 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 2.11.0
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70342338349440
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: aws-sdk
|
38
|
-
requirement: &
|
38
|
+
requirement: &70342338348420 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: 1.7.1
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70342338348420
|
47
47
|
description: I watch an SQS queue and escalate alert messages.
|
48
48
|
email:
|
49
49
|
- brett@weav.net
|
@@ -69,6 +69,13 @@ files:
|
|
69
69
|
- lib/aws-alert-monitor/aws/sqs.rb
|
70
70
|
- lib/aws-alert-monitor/cli.rb
|
71
71
|
- lib/aws-alert-monitor/config.rb
|
72
|
+
- lib/aws-alert-monitor/emailer.rb
|
73
|
+
- lib/aws-alert-monitor/event.rb
|
74
|
+
- lib/aws-alert-monitor/event_classifier.rb
|
75
|
+
- lib/aws-alert-monitor/events.rb
|
76
|
+
- lib/aws-alert-monitor/events/auto_scaling_notification.rb
|
77
|
+
- lib/aws-alert-monitor/events/cloud_watch_alarm.rb
|
78
|
+
- lib/aws-alert-monitor/events/unknown.rb
|
72
79
|
- lib/aws-alert-monitor/logger.rb
|
73
80
|
- lib/aws-alert-monitor/parser.rb
|
74
81
|
- lib/aws-alert-monitor/version.rb
|
@@ -76,6 +83,15 @@ files:
|
|
76
83
|
- spec/aws/ses_spec.rb
|
77
84
|
- spec/aws/sqs_spec.rb
|
78
85
|
- spec/config_spec.rb
|
86
|
+
- spec/emailer_spec.rb
|
87
|
+
- spec/event_classifier_spec.rb
|
88
|
+
- spec/event_spec.rb
|
89
|
+
- spec/events/auto_scaling_notification_spec.rb
|
90
|
+
- spec/events/cloud_watch_alarm_spec.rb
|
91
|
+
- spec/events/unknown_spec.rb
|
92
|
+
- spec/fixtures/asg_instance_launch.json
|
93
|
+
- spec/fixtures/cloud_watch_alarm.json
|
94
|
+
- spec/helpers/fixtures.rb
|
79
95
|
- spec/parser_spec.rb
|
80
96
|
- spec/spec_helper.rb
|
81
97
|
homepage: ''
|
@@ -92,7 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
108
|
version: '0'
|
93
109
|
segments:
|
94
110
|
- 0
|
95
|
-
hash:
|
111
|
+
hash: 2565205929421564978
|
96
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
113
|
none: false
|
98
114
|
requirements:
|
@@ -101,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
117
|
version: '0'
|
102
118
|
segments:
|
103
119
|
- 0
|
104
|
-
hash:
|
120
|
+
hash: 2565205929421564978
|
105
121
|
requirements: []
|
106
122
|
rubyforge_project:
|
107
123
|
rubygems_version: 1.8.16
|
@@ -113,5 +129,14 @@ test_files:
|
|
113
129
|
- spec/aws/ses_spec.rb
|
114
130
|
- spec/aws/sqs_spec.rb
|
115
131
|
- spec/config_spec.rb
|
132
|
+
- spec/emailer_spec.rb
|
133
|
+
- spec/event_classifier_spec.rb
|
134
|
+
- spec/event_spec.rb
|
135
|
+
- spec/events/auto_scaling_notification_spec.rb
|
136
|
+
- spec/events/cloud_watch_alarm_spec.rb
|
137
|
+
- spec/events/unknown_spec.rb
|
138
|
+
- spec/fixtures/asg_instance_launch.json
|
139
|
+
- spec/fixtures/cloud_watch_alarm.json
|
140
|
+
- spec/helpers/fixtures.rb
|
116
141
|
- spec/parser_spec.rb
|
117
142
|
- spec/spec_helper.rb
|