├── sns_sample_event.js ├── README.md └── handler.js /sns_sample_event.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Records:[ 3 | { 4 | "EventSource": "aws:sns", 5 | "EventVersion": "1.0", 6 | "EventSubscriptionArn": "arn:aws:sns:EXAMPLE", 7 | "Sns": { 8 | "Type": "Notification", 9 | "MessageId": "xxxxx-xxx-xxx-xxxxxxxx", 10 | "TopicArn": "arn:aws:sns:EXAMPLE", 11 | "Subject": "ALARM: 'Elasticache-FreeableMemory-CRITICAL' in APAC - Tokyo", 12 | "Message": " {'AlarmName':'Elasticache-FreeableMemory-INFO','AlarmDescription':'Elasticache-FreeableMemory-INFO','AWSAccountId':'1234567890','NewStateValue':'ALARM','NewStateReason':'Threshold Crossed: 1 datapoint (8.60604416E8) was less than or equal to the threshold (1.0E9).','StateChangeTime':'1970-01-01T00:00:00.000+0000','Region':'APAC - Tokyo','OldStateValue':'OK','Trigger':{'MetricName':'FreeableMemory','Namespace':'AWS/ElastiCache','Statistic':'AVERAGE','Unit':null,'Dimensions':[],'Period':60,'EvaluationPeriods':1,'ComparisonOperator':'LessThanOrEqualToThreshold','Threshold':1.0E9}}", 13 | "Timestamp": "1970-01-01T00:00:00.000Z", 14 | "SignatureVersion": "1", 15 | "Signature": "EXAMPLE", 16 | "SigningCertUrl": "EXAMPLE", 17 | "UnsubscribeUrl": "EXAMPLE", 18 | "MessageAttributes": { 19 | "Test": { 20 | "Type": "String", 21 | "Value": "TestString" 22 | }, 23 | "TestBinary": { 24 | "Type": "Binary", 25 | "Value": "TestBinary" 26 | } 27 | } 28 | } 29 | } 30 | ] 31 | }; 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lambda-cloudwatch-slack 2 | Amazon Lambda to receive alerts from CloudWatch and post to Slack. 3 | 4 | ## What is This? 5 | It's an Amazon lambda script that receives data from Amazon CloudWatch via, then posts that result over to Slack. 6 | Just configure the javascript file and set it in Lambda, then you are good to go. 7 | 8 | ## How to Use 9 | ### Alarm configuration 10 | In `handler.js`, you will find `ALARM_CONFIG`, which is the config for your alarms. 11 | You can set different configs for different alarm conditions, depending on the 12 | *subject of* the CloudWatch notification. 13 | 14 | | name | description | 15 | |:-----------|:------------| 16 | | condition | The script will match the CloudWatch's subject for this value | 17 | | channel | Which channel to post to | 18 | | mention | any mentions you will want to direct it at | 19 | | color | color of the sidebar when posted in slack | 20 | | severity | Optional text indicating the severity, just displayed in the message | 21 | 22 | ### Slack configuration 23 | In `handler.js`, you will find `SLACK_CONFIG`, which is the config for you Slack. 24 | Set the correct values in this. 25 | 26 | | name | description | 27 | |:-----------|:------------| 28 | | path | The path of your webhook URL. | 29 | 30 | 31 | If you have trouble finding the above, 32 | Go here to set up your *Incoming Webbhook* integration for Slack, 33 | https://api.slack.com/incoming-webhooks 34 | Then find your *Webhook URL*. The configs will be: 35 | ``` 36 | https://hooks.slack.com/{path} 37 | ``` 38 | 39 | ### Amazon CloudWatch configuration 40 | Set whatever CloudWatch you want in your CloudWatch settings. 41 | Be sure to remember the SNS topic you send the alarms to. 42 | 43 | ### Amazon Lambda configuration 44 | 1. In the Lambda console panel, create a new Lambda function. Set the name to be whatever you want it to be. 45 | 2. For the code of the Lambda function, copy and paste the `handler.js` file. 46 | 3. After you have created the function, select *add event sources* for the Lambda function. 47 | 4. In the event sources, select *SNS* and select the topic for which you've created on CloudWatch. 48 | 49 | That is all. You should be receiving CloudWatch alerts on your Slack. 50 | 51 | ## Testing, Debugging 52 | When you want to debug/test your Lambda function, try using my `lambda-local` NPM. 53 | It's a command-line tool that let's you execute Lambda functions on your local machine. 54 | https://github.com/ashiina/lambda-local 55 | 56 | ## License 57 | This library is released under the MIT license. 58 | -------------------------------------------------------------------------------- /handler.js: -------------------------------------------------------------------------------- 1 | console.log('[Amazon CloudWatch Notification]'); 2 | 3 | /* 4 | configuration for each condition. 5 | add any conditions here 6 | */ 7 | var ALARM_CONFIG = [ 8 | { 9 | condition: "INFO", 10 | channel: "#test", 11 | mention: " ", 12 | color: "#FF9F21", 13 | severity: "INFO" 14 | }, 15 | { 16 | condition: "CRITICAL", 17 | channel: "#general", 18 | mention: "<@channel> ", 19 | color: "#F35A00", 20 | severity: "CRITICAL" 21 | } 22 | ]; 23 | 24 | var SLACK_CONFIG = { 25 | path: "YOUR_PATH", 26 | }; 27 | 28 | var http = require ('https'); 29 | var querystring = require ('querystring'); 30 | exports.handler = function(event, context) { 31 | console.log(event.Records[0]); 32 | 33 | // parse information 34 | var message = event.Records[0].Sns.Message; 35 | var subject = event.Records[0].Sns.Subject; 36 | var timestamp = event.Records[0].Sns.Timestamp; 37 | 38 | // vars for final message 39 | var channel; 40 | var severity; 41 | var color; 42 | 43 | // create post message 44 | var alarmMessage = " *[Amazon CloudWatch Notification]* \n"+ 45 | "Subject: "+subject+"\n"+ 46 | "Message: "+message+"\n"+ 47 | "Timestamp: "+timestamp; 48 | 49 | // check subject for condition 50 | for (var i=0; i < ALARM_CONFIG.length; i++) { 51 | var row = ALARM_CONFIG[i]; 52 | console.log(row); 53 | if (subject.match(row.condition)) { 54 | console.log("Matched condition: "+row.condition); 55 | 56 | alarmMessage = row.mention+" "+alarmMessage+" "; 57 | channel = row.channel; 58 | severity = row.severity; 59 | color = row.color; 60 | break; 61 | } 62 | } 63 | 64 | if (!channel) { 65 | console.log("Could not find condition."); 66 | context.done('error', "Invalid condition"); 67 | } 68 | 69 | var payloadStr = JSON.stringify({ 70 | "attachments": [ 71 | { 72 | "fallback": alarmMessage, 73 | "text": alarmMessage, 74 | "mrkdwn_in": ["text"], 75 | "username": "AWS-CloudWatch-Lambda-bot", 76 | "fields": [ 77 | { 78 | "title": "Severity", 79 | "value": severity, 80 | "short": true 81 | } 82 | ], 83 | "color": color 84 | } 85 | ], 86 | "channel":channel 87 | }); 88 | var postData = querystring.stringify({ 89 | "payload": payloadStr 90 | }); 91 | console.log(postData); 92 | var options = { 93 | hostname: "hooks.slack.com", 94 | port: 443, 95 | path: SLACK_CONFIG.path, 96 | method: 'POST', 97 | headers: { 98 | 'Content-Type': 'application/x-www-form-urlencoded', 99 | 'Content-Length': postData.length 100 | } 101 | }; 102 | 103 | var req = http.request(options, function(res) { 104 | console.log("Got response: " + res.statusCode); 105 | res.on("data", function(chunk) { 106 | console.log('BODY: '+chunk); 107 | context.done(null, 'done!'); 108 | }); 109 | }).on('error', function(e) { 110 | context.done('error', e); 111 | }); 112 | req.write(postData); 113 | req.end(); 114 | }; 115 | --------------------------------------------------------------------------------