我创建了一个 lambda 函数,将 codebuild cloudwatch 日志发送到 slack。它工作正常,但每次在代码构建运行时生成日志时,它都会像垃圾邮件一样将消息扔到松弛状态。
我只想在代码构建完成后发送一次。
我不确定如何添加触发器,因为在 lambda 中我使用 cloudwatch 触发器来让 lambda 工作。
Nodejs Lambda 函数
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;
@abdullah 的回答应该可以解决您的问题。但是我会发布另一种方法
您可以简单地在您的构建项目上启用通知。您可以在构建状态或构建阶段配置您想要的事件,并将此通知的目标配置为 sns。
在您的 sns 中订阅 lambda,仅此而已。
您不必创建自定义事件规则或任何只需在您的代码构建项目上配置事件通知规则。
如何配置通知:
注意: 我的回答假设你的 lambda 正在做你打算做的事。
第一步
您应该更改 AWS CloudWatch Events 规则的触发器以实现此目的。您应该使用
AWS CodeBuild Build State Change
事件,而不是使用 AWS CloudWatch 日志事件。
下面是一个例子:
{
"source": [
"aws.codebuild"
],
"detail-type": [
"CodeBuild Build State Change"
],
"detail": {
"project-name": [
"[PROJECT_NAME]"
],
"build-status": [
"SUCCEEDED",
"FAILED",
"STOPPED",
"TIMED_OUT"
]
}
}
当 AWS CodeBuild 项目构建完成并具有上述 4 种状态中的任何一种时,这将触发 AWS Lambda 函数。它还将在事件负载中发送 AWS CodeBuild 项目构建 ID。
第二步
您需要相应地更新您的 AWS Lambda 函数代码,以使用在事件负载中收到的 AWS CodeBuild 项目构建 ID 来获取 AWS CloudWatch 日志。 AWS CodeBuild 项目构建的 AWS CloudWatch 日志组名称和流可能如下所示
/aws/codebuild/[PROJECT_NAME]/[BUILD_ID]
。这取决于您如何在 AWS CodeBuild 项目上配置它。
下面是 AWS Lambda 函数在 Python 中的示例代码:
import boto3
import requests
import os
import json
def lambda_handler(event, context):
build_id = event['detail']['build-id']
logs_client = boto3.client('logs')
log_group_name = '/aws/codebuild/{0}'.format(event['detail']['project-name'])
log_stream_name = '{0}/{1}'.format(event['detail']['project-name'], build_id)
response = logs_client.get_log_events(
logGroupName=log_group_name,
logStreamName=log_stream_name,
startFromHead=True,
limit=100
)
message = {
'text': 'Logs for build {0}:\n'.format(build_id)
}
for event in response['events']:
message['text'] += event['message'] + '\n'
slack_webhook_url = os.environ['SLACK_WEBHOOK_URL']
response = requests.post(slack_webhook_url, json=message)
if response.status_code == 200:
return {
'statusCode': 200,
'body': 'Message is sent to Slack successfully.'
}
else:
return {
'statusCode': response.status_code,
'body': 'Failed to send message to Slack.'
}
这是 Slack 关于 Webhook URL 的文档:Sending messages using Incoming Webhooks
备注:
[PROJECT_NAME]
是 AWS CodeBuild 项目的名称[BUILD_ID]
是特定构建的 AWS CodeBuild 项目的构建 ID。[SLACK_WEBHOOK_URL]
是 Slack Webhook URL。