AWS 电子邮件错误是否可以通过多个 Lambda 函数记录到 CloudWatch?

Can AWS email errors logged to CloudWatch by multiple Lambda functions?

我在 AWS Lambda 中有许多函数,由 CloudWatch Rules 在各种定期计划中调用。如果他们的节点 JavaScript 遇到错误,则会记录到 CloudWatch 日志组。

这两个投诉中的一个或两个可以通过这些工具解决,还是应该使用其他工具?

TL;DR this 是您可能正在寻找的解决方案架构。

(来源:亚马逊)

Can my multiple Lambda functions be configured to log to a single, shared Log Group?

没有。然而,即使您可以将所有 lambda 日志记录到一个日志组,这也是非常不可取的。

但是,您可以将多个日志组流式传输到一个目标中。例如,这通常用于 centralized logging 解决方案。

would I need to create a pair of Metrics and Alarms for each Lambda function?

这可能是最直接的方法。使用 CloudFormation(或相关工具、AWS CDK、Terraform 等),您可以通过创建 lambda 函数来自动执行此设置。

The received email is generic. Can it include the error message?

不容易。 CloudWatch 警报事件源不会包含对导致计数指标进入警报的日志的任何引用,因此这不会起作用。通常,当您收到此类警报时,您会使用其他服务来查找错误(例如 xray、cloudwatch 日志等)。例如,您的消息可能只包含一个 link 到 CloudWatch metric/alarm。在 CloudWatch 中,应该有一个 'view logs' 按钮提供指标时间范围的日志。请参阅:从指标转向日志

如果您确实需要将错误包含在通知中,则需要不同的解决方案架构。例如,您可以 stream 您的 CloudWatch 事件到 Lambda 函数,该函数将处理事件并发送通知,包括来自流的错误消息。

参见:使用订阅实时处理日志数据 如何使用 CloudWatch 获得有关特定 Lambda 函数错误模式的通知 其中包含有关在通知中获取错误消息的完整指南。

或者,您可能需要考虑其他监控解决方案,例如sentry, rollbar, NewRelic、DataDog 等

this answer 部分告知了一个类似的问题,以及 trial/error 和谁知道其他谷歌搜索,我最终放弃了 AWS Metrics 和 AWS Alarms,而是使用了一个新的 Lambda由任意数量的 select 日志组触发的函数。我保留了 SNS 功能,如果您拥有自己的电子邮件域,这将非常容易设置。

创建新的 Lambda 函数后,会显示搜索蓝图的选项,搜索 log 会产生(以及其他选项)cloudwatch-logs-process-data 蓝图。它也可以从头开始创建,因为它的代码只是这样:

const zlib = require('zlib');

exports.handler = async (event, context) => {
    const payload = Buffer.from(event.awslogs.data, 'base64');
    const parsed = JSON.parse(zlib.gunzipSync(payload).toString('utf8'));
    console.log('Decoded payload:', JSON.stringify(parsed));
    return `Successfully processed ${parsed.logEvents.length} log events.`;
};

然后我选择它作为多个触发器我希望监视的日志组,将它们的过滤器模式设置为单词 ERROR,并将它们的过滤器名称设置为我想要的电子邮件主题。

使用蓝图中的控制台日志,我创建了一个这种格式的测试事件:

{
  "awslogs": {
    "data": "LONG_STRING_OF_ENCODED_CHARACTERS_FROM_ABOVE_CONSOLE_LOG_HERE"
  }
}

我根据自己的喜好修改了蓝图代码:

const zlib = require('zlib');
const aws = require('aws-sdk');
const ses = new aws.SES({ region: '<some-region-1>' });

exports.handler = async function (event) {
    const payload = Buffer.from(event.awslogs.data, 'base64');
    const parsed = JSON.parse(zlib.gunzipSync(payload).toString('utf8'));

    const bodyText = JSON.stringify(parsed, null, 2).replace(/\n/g, ' \\n         ').replace(/\t/g, '\\n         ');
    console.log('bodyText:', bodyText);

    var params = {
        Source: '<some_email@example.com>',
        Destination: {
            ToAddresses: ['<some_email@example.com>'],
        },
        Message: {
            Subject: { Data: parsed.subscriptionFilters[0] },
            Body: {
                Text: { Data: bodyText },
            },
        },
    };
    return ses.sendEmail(params).promise();
};

它有效,如果 Lambda 函数记录错误,我会立即收到一封电子邮件(我的每月 AWS 账单也没有明显增加)。

更新后的通过 ses 发送电子邮件的 lambda 将运行良好。但是,必须使用必要的权限更新 Lambda 角色。见文章: https://aws.amazon.com/premiumsupport/knowledge-center/lambda-send-email-ses/

我已添加到默认 lambda 角色以使其正常工作的策略:

{
"Version": "2012-10-17",
"Statement": [
    {
        "Sid": "VisualEditor0",
        "Effect": "Allow",
        "Action": [
            "ses:SendEmail",
            "ses:SendRawEmail",
            "logs:CreateLogGroup"
        ],
        "Resource": [
            "arn:aws:logs:your-region-1:xxxaccountidxxxx:*",
            "arn:aws:ses:*:xxxaccountidxxxx:configuration-set/*",
            "arn:aws:ses:your-region-1:xxxaccountidxxxx:identity/your@email.com"
        ]
    },
    {
        "Sid": "VisualEditor1",
        "Effect": "Allow",
        "Action": [
            "ses:SendEmail",
            "logs:CreateLogStream",
            "logs:PutLogEvents"
        ],
        "Resource": [
            "arn:aws:ses:your-region-1:xxxaccountidxxxx:identity/your@email.com",
            "arn:aws:logs:your-region-1:xxxaccountidxxxx:log-group:/aws/lambda/yourlambdaname:*"
        ]
    }
]

}

否则报错:

code": "AccessDenied",
    "message": "User `arn:aws:sts::xxxx:assumed-role/zzz/yyyy' is not authorized to perform `ses:SendEmail' on resource `arn:aws:ses:us-east-1:xxxxx:identity/<your@email.com>'"