aws codebuild 完成后将整个 cloudwatch 日志发送到 slack

问题描述 投票:0回答:3

我创建了一个 lambda 函数,将 codebuild cloudwatch 日志发送到 slack。它可以正常工作,但每次在代码构建运行时都会生成日志。它像垃圾邮件一样向 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 Khawer 更新后我只能看到状态成功的少数日志,而不是所有日志。 codebuld 完成后,我需要获取整个 cloudwatch 日志。难道不能简单地将所有这些日志嵌入到一个文本文件中并将其发送到 slack 吗?

amazon-web-services aws-lambda amazon-cloudwatch aws-codepipeline aws-codebuild
3个回答
1
投票

@abdullah 的回答应该可以解决您的问题。但是我会发布另一种方法

您可以简单地在您的构建项目上启用通知。您可以在构建状态或构建阶段配置您想要的事件,并将此通知的目标配置为 sns。

在您的 sns 中订阅 lambda,仅此而已。

您不必创建自定义事件规则或任何只需在您的代码构建项目上配置事件通知规则。

如何配置通知:

  • 转到您的代码构建项目
  • 在顶部,点击通知
  • 输入通知规则名称,选择您想要的事件并选择目标

注意: 我的回答假设你的 lambda 正在做你打算做的事。


1
投票

第一步

您应该更改 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。

0
投票

从上面而不是松弛通知需要通过 SNS 电子邮件共享代码构建 cloudwatch 日志。任何示例代码。

© www.soinside.com 2019 - 2024. All rights reserved.