【问题标题】:How to debug aws lambda functions written in node js如何调试用节点 js 编写的 aws lambda 函数
【发布时间】:2021-06-16 02:27:03
【问题描述】:

几个月来,我们一直在 Node JS 中开发 AWS Lambda 函数。我们可以像在 Visual Studio 中使用 .Net C# 代码那样调试,即单步调试 Node JS 代码吗?

【问题讨论】:

  • 澄清一下,我们的 AWS Lambda 函数存储在 S3 存储桶中,并通过 API 网关调用。我们使用无服务器框架进行开发和部署。

标签: node.js amazon-web-services debugging aws-lambda


【解决方案1】:

默认情况下,许多 Lambda 函数不提供基于 IDE 的开发工具。有一些插件,例如 AWS 在其博客 https://aws.amazon.com/blogs/developer/aws-lambda-support-in-visual-studio/ 上介绍的 Visual Studio 支持,但这些插件将具有不同级别的功能集和支持。

为了使用分步调试来测试 Lambda,您需要关注两个领域 - 运行它的硬件以及调用 Lambda 函数的方式。硬件难以模拟,因为 AWS 对运行 lambda 函数的机器实例的详细信息保密。因此,在模拟硬件方面,您只需要保持对您的语言和操作系统合理的范围 - 确保安装了正确的运行时(例如,当您安装 NodeJS 4.X '正在使用版本 6 运行时),确保您没有超出存储要求(Lambda 的 AMI 在 /tmp 中获得 500 MB 的临时存储空间),并确保您在运行之前没有在本地保存任何状态代码。

一旦您确定了您的机器要求(或决定传递它们,因为您的代码不执行任何特定于硬件的工作),那么您将需要编写一个测试工具来调用您的 AWS Lambda 函数。此测试工具可作为调试器的入口点,虽然它对于 AWS 调用 Lambda 的方式很可能不是 100% 准确(例如,context 参数包含有关您当前 Lambda 调用的信息,这些信息本质上将不同的执行),它使您可以调用所有标准编码支持工具。

注意:以下简单的测试工具是为 Node.JS 编写的,但您可以将这些概念调整到执行 Lambda 的运行时

AWS Lambda (Node.js) 的简单测试工具

我们要做的第一件事是创建一个新文件 - debug.js - 并导入处理函数原型。假设您已经在 handler.js 中定义了您的处理程序,并将其命名为 handler,您可以按以下方式进行操作:

var handler = require('./handler.js').handler;

接下来,我们需要调用处理函数。正如我上面提到的,每个参数都有不同的用途。处理程序的第一个参数 -event - 包含导致调用的事件的详细信息。 注意:这也包括你的函数参数。正如我们所讨论的,第二个参数包含有关您的函数运行的上下文的信息。还有第三个参数 callback,可用于在您的 Lambda 执行完成时调用回调。在此处查看 AWS 文档:http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html

因此,为了我们的目的,对于一个简单的测试工具,我们只需要通过 event 参数发送参数。我们暂时不考虑 contextcallback 参数(稍作修改,下面会详细介绍),但是如果您想在此处提供函数所依赖的额外数据,那很好 - 只需确保它没有不会与放置在 AWS 中的任何自动化数据冲突。所以我们定义了参数hash,并调用了函数,在debug.js中使用如下代码:

var parameters = {
    "key1":"val1",
    "object" :{},
    // other keys as necessary
};

handler(parameters, {succeed:function(result){
    console.log("success: ", JSON.stringify(result, null, 2));
    process.exit(0);
}, fail:function(error){
    console.error("error: ", error);
    process.exit(1);
}});

这段代码做了一些有趣的事情:

  • 它使用成功和失败处理程序重载上下文对象。您可以将它们包装在“if”语句中,并使用context.succeed(message)context.fail(error) 在您的Lambda 代码中调用它们。这些不是 Lambda 官方支持的,而是在我们的代码中用作解决方法来访问成功/失败行为
    • 处理程序使用适当的错误代码调用 process.exit()。这允许您将执行链接到 CI/CD 工具或任何其他使用进程退出代码作为控制流的批处理工具中

一旦您编写了这个简单的测试工具,并调整了您的 Lambda 代码以调用成功/失败处理程序(如果存在)(像 if(context.success){context.success(args);} 这样简单的处理程序就足够了),您现在可以使用以下方法调用 lambda 函数node debug.js 并在控制台中查看结果。

我的 Lambda 函数中的单元测试也很幸运。由于您现在有了一个入口点以及如何调用 Lambda 函数的示例,您应该能够编写合适的单元和函数测试来表达您的所有功能。

关于缺点的简要说明

正如我所提到的,这种方法并不完美。以下是测试工具可能出现的一些问题:

  • 我们还没有对上下文对象进行任何模拟。您可以在 http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html 处查看上下文对象中可用的参数 - 您需要进行一些试验和错误才能准确确定这些参数中的最终格式
  • 我们没有进行任何机器仿真来捕捉硬件问题
  • 我们在这里只介绍了 Node.js 函数,其他语言可能无法适应回调方法
  • 我们重载了上下文机制以提供我们的成功-失败处理程序。如果 AWS 将名称相似的成员对象添加到 context 对象,这种方法可能会遇到问题

但是,尽管如此,您现在应该能够使用本地调试工具来测试和调试您的 Lambda 函数。我们在 Backand 使用了类似的框架 - https://www.backand.com - 作为我们的 Lambda 函数开发工具,它极大地提高了我们的 Lambda 开发速度。

【讨论】:

  • 我想这样做的主要原因是因为我想检查参数对象。我发现 AWS 文档不够详细,我在摸黑摸鱼。我希望能够逐步查看事件对象的确切外观(例如,event.Records[0].cf.request 内部到底是什么)。我们如何检查这些对象?我觉得使用 AWS 会大大降低开发人员的工作效率。
  • F.e.,这是 AWS 文档的限制:这篇关于 Node.js Lambda 处理程序的文章,docs.aws.amazon.com/lambda/latest/dg/…,有一个指向示例事件的链接,我很想了解 CLoudFront 事件,@987654326 @,但显然该示例对象不完整。此处的文章medium.com/@chrispointon/… 表明该示例中未显示更多属性。掌心
  • 由于缺乏信息,我假设request.uri 对象包含路径、查询字符串、AND 哈希字符串,这可能是完全错误的(基于上述Medium 文章)。
  • @trusktr 我可以检查事件对象的唯一方法是在响应中返回它。
【解决方案2】:

我想分享我发现的东西,因为我很难找到它。该解决方案基于我在文章“使用 VS 代码和 lambda-local 本地调试 AWS Lambda 函数”(https://www.codeproject.com/Articles/1163890/Debugging-AWS-Lambda-functions-locally-using-VS-Co) 中找到的内容,并进行了一些修改,以便在我们基于 Windows 的环境中工作。

总结如下:

1) 使用 Visual Studio Code 进行调试会话。用于调试 'llDebugDetail.js' 的 launch.json 示例如下:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "Launch Program",
            "program": "${workspaceRoot}/test/llDebugDetail.js",
            "cwd": "${workspaceRoot}"
        }
    ]
}

2) 使用 lambda-local 框架调用(执行)lambda 函数。必须在本地安装 lambda-local 框架,否则 VSC 调试器将找不到它。通过调用以下 URL 调用我们的 lambda 函数: https://xxx.execute-api.ap-southeast-2.amazonaws.com/resourceName/{id}/详细信息。 {id} 是用于选择产品项目并返回其详细信息的 GUID 参数。

这里是调用“getDetail”函数以返回产品详细信息的“llDebugDetail.js”代码,其中 GUID 作为其在 URL 中的 id。该函数位于“getDetail.js”文件中。

const lambdaLocal = require('lambda-local');
var path = require("path");
const myPath = path.join(__dirname, '../getDetail.js');
const testEvent = {
    "resource": "resourceName/12da3f7d-7ce2-433f-8659-5d7cd0d74d9a/detail",
    "pathParameters": {"id": "12da3f7d-7ce2-433f-8659-5d7cd0d74d9a"}
}

var lambdaFunc = require(myPath);

lambdaLocal.execute({
    event: testEvent,
    lambdaFunc: lambdaFunc, 
    lambdaHandler: "getDetail"
}).then(function(done) {
    console.log(done);
}).catch(function(err) {
    console.log(err);
});

完成上述操作后,您现在可以在代码中的任何位置设置断点,例如在 getDetail.js 中,启动程序并从 getDetail.js 中的断点逐步执行代码。

【讨论】:

    【解决方案3】:

    现在可以使用带有 Sigma IDE 的 AWS Lambda 进行逐步调试。是的,您在 AWS 中实际运行时调试该函数 - 请参阅下面的演示 https://serverless.asankha.com/2019/08/write-lambda-function-test-it-instantly.html

    【讨论】:

      【解决方案4】:

      您不能像在 VS 中那样调试 lambda 代码,但您可以调用一些测试数据并检查一切是否正常。

      1. 您可以使用 lambda-localserverless-offline 在您的机器上本地运行 lambda
      2. 因此,使用一些测试事件和数据调用您的 lambda,您可以记录并查看不同输入发生的情况

      【讨论】:

        【解决方案5】:

        Trek 10 最近发布了一个有趣的工具,允许在 AWS lambda 函数中单步执行 node.js 代码!怎么样,你可能会问? “魔法和镜子”,据他们说:-)

        显然,它不会直接附加到 Amazon 的主机进程(这是不可能的),但它会将您的代码分叉到在调试模式下运行的子进程中,并代理与本地 Chrome DevTools 的连接。 (实际上还有一些配置,您可以在下面的 github 存储库中阅读。)

        公告如下: https://www.trek10.com/blog/aws-lambda-debugger/

        和 github 存储库: https://github.com/trek10inc/aws-lambda-debugger

        【讨论】:

          【解决方案6】:

          到目前为止,我使用 VS Code 最简单的选择是:

          1. 创建一个新文件,将其命名为debug.js,然后从此处调用您的 lambda 函数,如下所示: const app = require('./index') app.handler()

          2. 像这样更改launcher.json 文件的程序条目: "program": "${workspaceFolder}/<your app dir>/debug.js"

          3. 您现在可以在这一行 (app.handler()) 上放一个断点,它就可以工作了

          【讨论】:

            【解决方案7】:

            正如其他人所指出的,您不能以原生方式单步调试 Lambda。但是正在开发新的工具,使之成为可能。 Rookout 现在提供生产 Node.js Lambda 的分步调试,无需分叉或停止代码,使用某种字节码级别的方法。

            【讨论】:

              【解决方案8】:

              如果您使用无服务器和无服务器离线插件在本地进行测试。 您可以参考以下:

              如果你使用的是windows,更新vscode的launch.json和package.json如下:

              // launch.json
              {
              
                  "version": "0.2.0",
              
                 "configurations": [
              
                     {
              
                         "type": "node",
              
                         "request": "launch",
              
                         "name": "Debug Serverless",
              
                         "cwd": "${workspaceFolder}",
              
                         "runtimeExecutable": "npm",
              
                         "runtimeArgs": [
              
                             "run",
              
                             "debug"
              
                         ],
              
                         "outFiles": [
              
                             "${workspaceFolder}/handler.js"
              
                         ],
              
                         "port": 9229,
              
                         "sourceMaps": true
              
                     }
              
                 ]
              
              }

              // package.json
              ....
              "scripts": {
                  "debug": "SET SLS_DEBUG=* && node --inspect %USERPROFILE%\\AppData\\Roaming\\npm\\node_modules\\serverless\\bin\\serverless offline -s dev"
                }

              如果在 linux 上,您的调试脚本将是:

              // package.json
              ....
              "scripts": {
                  "debug": "export SLS_DEBUG=* && node --inspect /usr/local/bin/serverless offline -s dev"
                }
              

              【讨论】:

                【解决方案9】:

                在 VSCode 中使用断点调试 lambda:

                首先,为您的处理程序编写测试用例,如下所示: index.test.js

                'use strict';
                
                const handler = require('../index');
                
                const chai = require('chai');
                
                const { expect } = chai;
                
                describe('debug demo', () => {
                  it('should return success', () => {
                    let event = {data: "some data"}
                    handler(event, '', function(err, res) {
                      expect(res.statusCode, '200')
                    });
                  });
                });
                

                现在添加 VSCode 调试器配置

                第 1 步: 点击左侧的调试器图标

                第 2 步: 点击添加配置

                并在launch.json文件中添加如下配置:

                {
                    "version": "0.2.0",
                    "configurations": [
                
                      {
                          "type": "node",
                          "request": "launch",
                          "name": "Mocha All",
                          "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
                          "args": [
                              "--timeout",
                              "999999",
                              "--colors",
                              "'${workspaceFolder}/lambda-codebase/**/test/*.test.js'"
                          ],
                          "console": "integratedTerminal",
                          "internalConsoleOptions": "neverOpen"
                      },
                      {
                          "type": "node",
                          "request": "launch",
                          "name": "Mocha Current File",
                          "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
                          "args": [
                              "--timeout",
                              "999999",
                              "--colors",
                              "${file}"
                          ],
                          "console": "integratedTerminal",
                          "internalConsoleOptions": "neverOpen"
                      }
                    ]
                  }
                

                第 3 步: 现在为您要调试的代码添加一个断点,如下所示:

                第 4 步: 现在通过单击文件来关注测试文件:

                第 5 步: 从下拉菜单中选择“Mocha All”选项以运行完整的解决方案,选择“Mocha current file”以仅运行选定的文件

                现在点击 DEBUG Play 按钮开始调试吧!

                【讨论】:

                  猜你喜欢
                  • 2021-09-11
                  • 2018-10-03
                  • 2015-11-15
                  • 2022-01-17
                  • 2019-07-18
                  • 2017-09-22
                  • 2020-02-15
                  • 2017-08-27
                  • 2019-05-09
                  相关资源
                  最近更新 更多