Skip to content

Instantly share code, notes, and snippets.

@anders0l
Forked from jeka-kiselyov/index.js
Created October 4, 2018 09:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anders0l/7b51ac97fe4c8e087d2af9e35374e19c to your computer and use it in GitHub Desktop.
Save anders0l/7b51ac97fe4c8e087d2af9e35374e19c to your computer and use it in GitHub Desktop.
CloudWatch to AWS Lambda to Slack Channel Alerts and Charts. Posts CloudWatch Alerts via SNS topic via Lambda function to Slack channel. And draws charts for CPUUtilization metrics(both for EC2 abd RDS).
////// Save as index.js and upload it to Lambda as zip archive with node_modules directory. After:
////// npm install aws-cloudwatch-chart
////// npm install request
////// no need to upload aws-sdk module
////// Don't forget to change API keys here.
////// License: MIT
////// Docs:
////// https://github.com/jeka-kiselyov/aws-cloudwatch-chart
////// http://docs.aws.amazon.com/sns/latest/dg/sns-lambda.html
////// http://docs.aws.amazon.com/lambda/latest/dg/walkthrough-s3-events-adminuser-create-test-function-create-function.html
//////
exports.handler = function(event, context) {
var request = require('request');
var fs = require('fs');
var AwsCloudWatchChart = require('aws-cloudwatch-chart');
var config = {};
config.slack = {
token: 'xoxp-4234234-234234-234234234-257abf',
channel: '#aws',
initialComment: "EC2 CPU Usage %from_time% to %to_time% UTC",
fileTitle: "EC2 CPU Usage %from_time% to %to_time% UTC"
};
config.aws = {
accessKeyId: "ASDASDSADSADASD",
secretAccessKey: "dsfsdfsdf/REWR/fdsdf/DFDSf34",
region: "us-east-1"
};
config.timeOffset = 1440;
config.timePeriod = 60;
config.graphSamples = 20;
config.width = 1000;
config.height = 250;
if (typeof(event.Records) === 'undefined' || typeof(event.Records[0]) === 'undefined' || typeof(event.Records[0].Sns) === 'undefined')
context.fail ('ERROR: requires SNS message');
if (typeof(event.Records[0].Sns.Message) !== 'undefined' && typeof(event.Records[0].Sns.Message.Trigger) === 'undefined')
event.Records[0].Sns.Message = JSON.parse(event.Records[0].Sns.Message);
config.slack.initialComment = event.Records[0].Sns.Subject + "\n" + event.Records[0].Sns.Message.AlarmDescription;
config.metrics = [];
console.log('event.Records[0].Sns.Message:');
console.log(event.Records[0].Sns.Message);
if (typeof(event.Records[0].Sns.Message.Trigger) !== 'undefined' && typeof(event.Records[0].Sns.Message.Trigger.Dimensions) !== 'undefined')
{
if (event.Records[0].Sns.Message.Trigger.Namespace == 'AWS/EC2' && event.Records[0].Sns.Message.Trigger.MetricName == 'CPUUtilization')
{
config.metrics.push({
InstanceId: event.Records[0].Sns.Message.Trigger.Dimensions[0].value,
title: event.Records[0].Sns.Message.Trigger.Dimensions[0].value+" EC2 Max CPU Usage",
Namespace: event.Records[0].Sns.Message.Trigger.Namespace,
MetricName: event.Records[0].Sns.Message.Trigger.MetricName,
StatisticValues: "Maximum",
Unit: "Percent",
color: "af9cf4",
thickness: 2,
dashed: false
});
} else if (event.Records[0].Sns.Message.Trigger.Namespace == 'AWS/RDS' && event.Records[0].Sns.Message.Trigger.MetricName == 'CPUUtilization') {
config.metrics.push({
DBInstanceIdentifier: event.Records[0].Sns.Message.Trigger.Dimensions[0].value,
title: event.Records[0].Sns.Message.Trigger.Dimensions[0].value+" DB Max CPU Usage",
Namespace: event.Records[0].Sns.Message.Trigger.Namespace,
MetricName: event.Records[0].Sns.Message.Trigger.MetricName,
StatisticValues: "Maximum",
Unit: "Percent",
color: "9caff4",
thickness: 2,
dashed: false
});
} else if (event.Records[0].Sns.Message.Trigger.Namespace == 'AWS/EC2' && event.Records[0].Sns.Message.Trigger.MetricName == 'CPUCreditBalance') {
config.metrics.push({
InstanceId: event.Records[0].Sns.Message.Trigger.Dimensions[0].value,
title: event.Records[0].Sns.Message.Trigger.Dimensions[0].value+" CPU Credit Balance",
Namespace: event.Records[0].Sns.Message.Trigger.Namespace,
MetricName: event.Records[0].Sns.Message.Trigger.MetricName,
StatisticValues: "Maximum",
Unit: "Count",
color: "9caff4",
thickness: 2,
dashed: false
});
}
}
var postSlackMessage = function(text, imageURL, callback)
{
var apiURL = "https://slack.com/api/chat.postMessage?token=" + encodeURIComponent(config.slack.token) +
"&text=" + encodeURIComponent("ALERT\n"+imageURL) +
"&username=" + encodeURIComponent('AWS') +
"&as_user=" + encodeURIComponent('false') +
"&icon_emoji=" + encodeURIComponent(':bell:') +
"&attachments=" + encodeURIComponent('[{"fallback": '+JSON.stringify(text)+',"text": '+JSON.stringify(text)+', "color": "danger"}]') +
"&channel=" + encodeURIComponent(config.slack.channel);
var req = request.post(apiURL, callback);
}
if (config.metrics.length < 1)
{
/// post
postSlackMessage(config.slack.initialComment, '', function() {
context.done(null, 'Not AWS/EC2 CPUUtilization metric');
});
} else {
var acs = new AwsCloudWatchChart(config);
console.log('Start');
acs.getChart().then(function(chart){
console.log('Got chart URL');
console.log(chart.getURL());
chart.get().then(function(image){
console.log('Got chart image');
var fileTitle = config.slack.fileTitle.
split('%from_time%').join(acs.getFromTimeString()).
split('%to_time%').join(acs.getToTimeString());
var initialComment = config.slack.initialComment.
split('%from_time%').join(acs.getFromTimeString()).
split('%to_time%').join(acs.getToTimeString());
var apiURL = "https://slack.com/api/files.upload?token=" + encodeURIComponent(config.slack.token) +
"&filename=" + encodeURIComponent("image.png") +
"&title=" + encodeURIComponent(fileTitle) +
"&initial_comment=" + encodeURIComponent(initialComment);
console.log('Sending file to Slack...');
var callback = function (err, response, body) {
var data = JSON.parse(body);
var text = config.slack.initialComment;
postSlackMessage(text, data.file.url, function() {
context.done(null, "Done");
});
}
var req = request.post(apiURL, callback);
var form = req.form();
form.append('file', new Buffer(image), {contentType: 'image/png', filename: 'x.png', name: 'x.png'});
});
});
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment