I have created a lambda function that send codebuild cloudwatch logs to slack. Its working but everytime the logs is generated while codebuild is running. It is throwing messages to slack like a spam.
I would want to send entire codebuild logs only once when the codebuild is finished.
I am not sure how to add trigger because in lambda I used cloudwatch trigger for lambda to work.
Nodejs Lambda function
const zlib = require("zlib");
const https = require("https");
const SLACK_ENDPOINT ="/services/000000000000000000000000000000000000"
const SLACK_BOT = "deploy-notifications";
function doRequest(content) {
// formatting the message according Slack API
const payload = {
username: SLACK_BOT,
blocks: [
{
type: "header",
text: {
type: "plain_text",
text: "Whoops, looks like something went wrong 😞🤕",
emoji: true,
},
},
{
type: "section",
fields: [
{
type: "mrkdwn",
text: "<!here> the API is running into an issue",
},
],
},
{
type: "section",
fields: [
{
type: "mrkdwn",
text: "*Environment: * Production",
},
],
},
{
type: "section",
fields: [
{
type: "mrkdwn",
text: "*Message:* _" + content.message + "_",
},
],
},
{
type: "section",
fields: [
{
type: "mrkdwn",
text: "*Stacktrace:*",
},
],
},
{
type: "section",
text: {
type: "mrkdwn",
text:
"```" +
JSON.stringify(content.original ? content.original : content) +
"```",
},
},
{
type: "divider",
},
],
};
const payloadStr = JSON.stringify(payload);
const options = {
hostname: "hooks.slack.com",
port: 443,
path: SLACK_ENDPOINT,
channel: "#deploy-notifications",
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(payloadStr),
},
};
const postReq = https.request(options, function (res) {
const chunks = [];
res.setEncoding("utf8");
res.on("data", function (chunk) {
return chunks.push(chunk);
});
res.on("end", function () {
if (res.statusCode < 400) {
console.log("sent!!!");
} else if (res.statusCode < 500) {
console.error(
"Error posting message to Slack API: " +
res.statusCode +
" - " +
res.statusMessage
);
} else {
console.error(
"Server error when processing message: " +
res.statusCode +
" - " +
res.statusMessage
);
}
});
return res;
});
postReq.write(payloadStr);
postReq.end();
}
function main(event, context) {
context.callbackWaitsForEmptyEventLoop = true;
// always returns the last event
const payload = Buffer.from(event.awslogs.data, "base64");
const log = JSON.parse(zlib.gunzipSync(payload).toString("utf8"));
// the log is an object that contains an array of events called `logEvents` and we need access it bypassing the index 0
doRequest(log.logEvents[0]);
const response = {
statusCode: 200,
body: JSON.stringify("Event sent to Slack!"),
};
return response;
}
exports.handler = main;
2
Answers
STEP 1
You should change your trigger for AWS CloudWatch Events / AWS EventBridge rule to achieve this. Instead of using AWS CloudWatch logs event, you should use
AWS CodeBuild Build State Change
event as detail-type andaws.codebuild
as source.Below is a sample for that:
This will trigger the AWS Lambda function when the AWS CodeBuild project build has finished with any of the above mentioned 4 states. It will also send AWS CodeBuild project build ID in event payload.
STEP 2
You need to update your AWS Lambda function code accordingly to fetch AWS CloudWatch logs using AWS CodeBuild project build id received in event payload. Your AWS CloudWatch log group name and stream for an AWS CodeBuild project build may look like this
/aws/codebuild/<PROJECT_NAME>/<BUILD_ID>
. It depends upon how you configured it on AWS CodeBuild project.Below is a sample code for AWS Lambda function for this in Python:
Here is the documentation by Slack regarding Webhook URL: Sending messages using Incoming Webhooks
Notes:
<PROJECT_NAME>
is the name of the AWS CodeBuild project<BUILD_ID>
is the build id of the AWS CodeBuild project for a specific build.<SLACK_WEBHOOK_URL>
is the Slack Webhook URL.@abdullah’s answer should solve your problem. However I will post an alternate approach
You can simply enable notifications on your build project. You can configure which event you want either on Build state or Build phase and configure target for this notification as sns.
In your sns subscribe to lambda and thats it.
You won’t have to create a custom event rule or anything just configure event notification rule on your codebuild project.
How to configure notification :
Note: My answer assumes your lambda is doing what you intend to do.