getsentry / sentry-javascript

Official Sentry SDKs for JavaScript
https://sentry.io
MIT License
7.85k stars 1.55k forks source link

nodeProfilingIntegration from @sentry/profiling-node does not work in aws lambda #12994

Closed petar-ps closed 1 month ago

petar-ps commented 1 month ago

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/aws-serverless

SDK Version

8.19.0

Framework Version

Node 20.14/Node 18

Link to Sentry event

There is no event

SDK Setup/Reproduction Example

import * as Sentry from '@sentry/aws-serverless';
import { nodeProfilingIntegration } from '@sentry/profiling-node';

Sentry.init({
    dsn: 'MY_DSN',
    integrations: [nodeProfilingIntegration()],
    tracesSampleRate: 1.0,
    profilesSampleRate: 1.0,
});

Steps to Reproduce

Aws sam build the lambda but when i invoke locally or on via amazon server it just crash on start up.

Expected Result

To finish init and continue execution.

Actual Result

Lambda crash on start up. nodeProfilingIntegration() crash.

LOG:

undefined   ERROR   Uncaught Exception  
{
    "errorType": "TypeError",
    "errorMessage": "The \"path\" argument must be of type string or an instance of URL. Received undefined",
    "code": "ERR_INVALID_ARG_TYPE",
    "stack": [
        "TypeError [ERR_INVALID_ARG_TYPE]: The \"path\" argument must be of type string or an instance of URL. Received undefined",
        "    at __node_internal_captureLargerStackTrace (node:internal/errors:496:5)",
        "    at new NodeError (node:internal/errors:405:5)",
        "    at Object.fileURLToPath (node:internal/url:1477:11)",
        "    at Object.<anonymous> (/src/sdk.ts:384:50)",
        "    at Module._compile (node:internal/modules/cjs/loader:1364:14)",
        "    at Module._extensions..js (node:internal/modules/cjs/loader:1422:10)",
        "    at Module.load (node:internal/modules/cjs/loader:1203:32)",
        "    at Module._load (node:internal/modules/cjs/loader:1019:12)",
        "    at Module.require (node:internal/modules/cjs/loader:1231:19)",
        "    at require (node:internal/modules/helpers:177:18)",
        "    at _tryRequireFile (file:///var/runtime/index.mjs:1002:37)",
        "    at _tryRequire (file:///var/runtime/index.mjs:1052:25)",
        "    at _loadUserApp (file:///var/runtime/index.mjs:1081:22)",
        "    at UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1119:27)",
        "    at start (file:///var/runtime/index.mjs:1282:42)",
        "    at file:///var/runtime/index.mjs:1288:7",
        "    at ModuleJob.run (node:internal/modules/esm/module_job:195:25)",
        "    at async ModuleLoader.import (node:internal/modules/esm/loader:337:24)",
        "    at async loadESM (node:internal/process/esm_loader:34:7)",
        "    at async handleMainPromise (node:internal/modules/run_main:106:12)"
    ]
}
JonasBa commented 1 month ago

@petar-ps would you mind sharing a small reproducible example with us please? It seems like this fails at attempting to require the bindings file in ESM mode, but it's a bit hard to say exactly why this would happen without attempting to reproduce it. Thanks so much!

petar-ps commented 1 month ago

@petar-ps would you mind sharing a small reproducible example with us please? It seems like this fails at attempting to require the bindings file in ESM mode, but it's a bit hard to say exactly why this would happen without attempting to reproduce it. Thanks so much!

Here is the repo: https://github.com/petar-ps/sentry-problem Do npm i, and then if you have AWS SAM you can go and do sam build and sam local invoke.

If you dont have AWS SAM, you can download zip file and create lambda, then import from this zip. Go to Test it and you will see similar error: sentry-problem-HelloWorldFunction-SxJXUHiYkIVF-4618c3c7-f19d-43d1-a0c3-bc615e70ae55.zip

s1gr1d commented 1 month ago

Hello, thanks for the reproduction, we are taking a look at this!

andreiborza commented 1 month ago

Hello @petar-ps, thanks for filing this and providing a reproduction. We've had a look at this and the issue is twofold.

We don't provide a layer for @sentry/profiling-node out of the box today (but I think we probably should), so you'd have to create a lambda layer yourself that has @sentry/profiling-node and all its dependencies inside node_modules. Please have a look at https://docs.aws.amazon.com/lambda/latest/dg/nodejs-package.html#nodejs-package-dependencies-layers for how to do that.

You'll also have to mark @sentry/profiling-node as external in your SAM template.yaml like so:

# template.yaml
...
    Metadata: # Manage esbuild properties
      BuildMethod: esbuild
      BuildProperties:
        External:
          - '@sentry/profiling-node'

Please let us know if you're still having problems after trying this.

petar-ps commented 1 month ago

Thank you @andreiborza. It works. Just to send this message if someone have the same problem like me for the future with AWS SAM and typescript.

Building and using the same layers from local is broken in AWS SAM. Yes, you can build and deploy a layer from SAM but you cannot use it. You must include that deployed layer like this inside your options for your function:

In template.yaml:

yourLambdaFunction:
    Type: AWS::Serverless::Function
    ......
    Layers:
        - ARN of your deployed layer

Other things to consider is typescript will warn you when you try to import something from /opt/nodejs/node_modules/yourFile so you have 2 options: 1) Dont do anything. SAM will build the app without problems, and will run it locally. But you will have red line showing error so if that is bothering you, you can do: 2) In tsconfig.json you can make path to your layer if it is in the same repo (this is my example):

"paths": {
      "/opt/nodejs/node_modules/*": [
        "../layers/sentryLayer/.aws-sam/build/SentryLayer/nodejs/node_modules/*"
      ]
    }

This will shut TS mouth. But again in local invoke or aws invoke, amazon will provide that path for you so this is really cosmetic in my opinion. If you are using functions from that package in the code, then its not cosmetic because you will get completition for that code.

One more thing. Watch how do you reference layers. I built my layer with SAM and SAM build with structure nodejs/ instead of nodejs/node18 so be careful how do you reference your layer.