aws / aws-toolkit-vscode

Amazon Q, CodeCatalyst, Local Lambda debug, SAM/CFN syntax, ECS Terminal, AWS resources
https://marketplace.visualstudio.com/items?itemName=AmazonWebServices.amazon-q-vscode
Apache License 2.0
1.46k stars 397 forks source link

Debugging Lambdas with a Layer (Or alternative) #5045

Open ghost opened 3 months ago

ghost commented 3 months ago

System details

Question

How can I debug Lambdas which will have a lambda layer attached using AWS SAM without including all dependencies in the requirements.txt?

We have a repo which contains a series of about 15 services and the code for their associated lambdas. Each lambda has an associated requirements.txt which is used by a build job to package the code and upload to S3. We have a few instances where we're using lambda layers to include dependencies which aren't available through pip or simply to reduce the size of the deployment package, however I'm struggling to create a launch configuration for these functions which includes all the necessary dependancies during testing.

I've tried using a preLaunchTask to temporarily add the layer dependencies to requirements.txt, and a postDebugTask to clean these up, however I couldn't get the postDebugTask to run (I think it must run in a different context as it can never be found despite being in my tasks.json).

I've also looked into using a custom template for the invokeTarget, however this approach seems to lack the full debugging functionality with VSCode (Breakpoints etc).

I think a separate prod-requirements.txt might work for the instances where we aim to minimise the package size, but wouldn't solve the issue of including binaries which aren't in pip such as git-lambda-layer.

Does anyone have any guidance on how we might be able to approach this, whilst managing the configuration for about 30 lambdas in a single repository.

I'm happy to provide more context if needed.

Sample from launch.json:

{
  "configurations": [
    {
      "type": "aws-sam",
      "request": "direct-invoke",
      "name": "common:data-bucket-transform:lambda.handler (python3.9)",
      "invokeTarget": {
        "target": "code",
        "projectRoot": "${workspaceFolder}/common/data-bucket-transform",
        "lambdaHandler": "lambda.handler"
      },
      "lambda": {
        "runtime": "python3.9",
        "payload": {
          "path": "${workspaceFolder}/common/data-bucket-transform/event.json"
        },
        "environmentVariables": {
          "LOG_LEVEL": "DEBUG",
          "ECOSYSTEM": "dev",
          "ENVIRONMENT": "dev",
          "SERVICE": "common"
        }
      }
    }
    # 30 more configurations
  ]
}

Sample of File Structure:

.
├── common
│   ├── data-bucket-transform
|   |   ├── event.json
│   │   ├── lambda.py
│   │   └── requirements.txt
│   └── uncompress-cloudwatch
|       ├── event.json
│       ├── lambda.py
│       └── requirements.txt
justinmk3 commented 2 months ago

Lambda layers are currently not well-supported: https://github.com/aws/aws-toolkit-vscode/issues?q=is%3Aissue+is%3Aopen+layer+image

The recommended alternative is to use Lambda with packagetype=image https://docs.aws.amazon.com/lambda/latest/dg/images-create.html . This allows you to define a Dockerfile that defines your Lambda environment.

This essentially replaces Lambda "layers", so we don't have plans to add explicit support for layers to AWS Toolkit.

romeubertho commented 2 months ago

Hello, a workaround is adding debugpy>=1.0,<2 to your lambda requirements.txt check the workaroud issue here

example of my working lambda launch.json with this workaround:

    {
      "name": "MonitoringFunction",
      "type": "aws-sam",
      "request": "direct-invoke",
      "invokeTarget": {
        "target": "template",
        "templatePath": "src/template.yaml",
        "logicalId": "MonitoringFunction"
      },
      "lambda": {
        "environmentVariables": {
          "ENV": "dev",
          "DB_HOST": "localhost",
          "DB_PORT": "5432",
          "DB_NAME": "lalala",
          "DB_USER": "postgres",
          "DB_PASSWORD": "postgres"
        },
        "payload": {
          "path": "src/functions/monitoring/events/event.json"
        }
      },
      "sam": {
        "buildDir": "src/.aws-sam",
        "template": {
          "parameters": {
            "Env": "dev"
          }
        }
      }
    }