AWS Lambda Native Tracing for Node.js

This page covers the setup Instana AutoTrace for AWS Lambda functions written in Node.js.

Supported Runtimes

  • nodejs20.x
  • nodejs18.x
  • nodejs16.x
  • nodejs14.x

Installation

This documentation explains how to set up the tracing of Node.js Lambda functions. Ensure that you also have performed the setup of the AWS agent for Lambda monitoring to ensure the collection of necessary information about versions and some runtime metrics that Instana cannot collect from inside the AWS Lambda runtime.

The preferred method to enable AWS Lambda Node.js tracing is to follow the AutoTrace instructions. If, for some reason that is not possible due to runtime version limitations or other local constraints, there are other options listed as follows.

Instana AutoTrace setup

The Instana AutoTrace setup for Node.js allows you to trace your AWS Lambda functions is to use the Instana Lambda layer and a custom function handler. This approach requires no modification of the Lambda function code and is done purely through configuration. It is also suited to be automated or included in a Lambda deployment pipeline.

To enable tracing of Node.js Lambda functions, perform the following steps:

  1. Add the Instana Lambda layer to your function.

    1. In the configuration page for your Lambda function, click on the Layers box and then on Add a layer. layer
    2. In the popup that opens, select "Provide a layer version ARN" and copy and paste the ARN for the Instana Lambda Layer that matches your region; you can find the right ARN for the Instana Lambda Layer in the Instana Lambda Layers section. layer selection
  2. Configure the Lambda Handler. Set the handler to instana-aws-lambda-auto-wrap.handler if you use CommonJS. Set the handler to instana-aws-lambda-auto-wrap-esm.handler if you use ES Modules (ES6) (available from layer version 223).

    To change the setting for the Lambda handler, find the "Basic Settings" section on the configuration page.

    basic settings section edit button

    Click on edit and insert instana-aws-lambda-auto-wrap.handler into the field labeled "Handler".

    edit basic settings to set Instana's handler

    The Instana Lambda layer automatically triggers the default Node.js runtime handler index.handler. If you use a custom handler, specify your handler in the environment variable LAMBDA_HANDLER to notify the Instana Lambda Layer. See the next section for all environment variables that need to be set.

    The Lambda configuration page might display a warning like "Lambda can't find the file instana-aws-lambda-auto-wrap.js." This might also be displayed later when returning to the configuration page. Do not let this warning distract you. The handler is contained in the Instana Lambda layer but the AWS Lambda configuration page does not take that into account.

  3. Configure Environment Variables. Add the following environment variables:

    • INSTANA_ENDPOINT_URL: This is your serverless monitoring endpoint. Make sure to use the correct value for your region that starts with https://serverless-.
    • INSTANA_AGENT_KEY: Your agent key.
    • LAMBDA_HANDLER: Set your custom handler. If your main file is myModule.js, which exports the function myHandler, set the environment variable to myModule.myHandler. The default value is index.handler.

    In the following example, the original main Lambda Handler is index.js, and therefore you don't need to set the environment variable LAMBDA_HANDLER. settings for default env variables

    In the following example, the original main Lambda Handler is server.js, and therefore you need to set the environment variable LAMBDA_HANDLER to server.handler. settings for custom env variables

    You can also obtain the correct values for these environment variables by going to your Instana installation, click on "... More" -> "Agents" -> "Installing Instana Agents" -> Platform: "AWS" -> Technology: "AWS Lambda".

  4. Save the Lambda function definition. save

All the steps outlined above can be done either via the AWS web console or any of the usual AWS management tools, such as:

Here is an example aws CLI command that might serve as a starting point if you want to automate the Instana integration of your AWS Lambdas:

# Do not copy and paste this verbatim!
# It will overwrite any previously defined collection of layers and
# environment variables.
aws --region $YOUR_REGION lambda update-function-configuration \
  --function-name $YOUR_LAMBDA_FUNCTION_NAME \
  --layers $INSTANA_LAYER_ARN \
  --handler instana-aws-lambda-auto-wrap.handler \
  --environment ""Variables={INSTANA_ENDPOINT_URL=... , INSTANA_AGENT_KEY=... , ...}""

Instana Lambda Layers

Architecture x86_64

The ARNs of the latest version of the AWS Lambda layers for the Lambda runtimes listed in Supported Runtimes are the following, per region:

Region ARN @instana/aws-lambda Version
af-south-1 arn:aws:lambda:af-south-1:410797082306:layer:instana-nodejs:28 3.5.0
ap-east-1 arn:aws:lambda:ap-east-1:410797082306:layer:instana-nodejs:28 3.5.0
ap-northeast-1 arn:aws:lambda:ap-northeast-1:410797082306:layer:instana-nodejs:184 3.5.0
ap-northeast-2 arn:aws:lambda:ap-northeast-2:410797082306:layer:instana-nodejs:182 3.5.0
ap-northeast-3 arn:aws:lambda:ap-northeast-3:410797082306:layer:instana-nodejs:28 3.5.0
ap-south-1 arn:aws:lambda:ap-south-1:410797082306:layer:instana-nodejs:182 3.5.0
ap-south-2 arn:aws:lambda:ap-south-2:410797082306:layer:instana-nodejs:28 3.5.0
ap-southeast-1 arn:aws:lambda:ap-southeast-1:410797082306:layer:instana-nodejs:182 3.5.0
ap-southeast-2 arn:aws:lambda:ap-southeast-2:410797082306:layer:instana-nodejs:182 3.5.0
ap-southeast-3 arn:aws:lambda:ap-southeast-3:410797082306:layer:instana-nodejs:28 3.5.0
ap-southeast-4 arn:aws:lambda:ap-southeast-4:410797082306:layer:instana-nodejs:28 3.5.0
ca-central-1 arn:aws:lambda:ca-central-1:410797082306:layer:instana-nodejs:182 3.5.0
cn-north-1 arn:aws-cn:lambda:cn-north-1:107998019096:layer:instana-nodejs:15 3.5.0
cn-northwest-1 arn:aws-cn:lambda:cn-northwest-1:107998019096:layer:instana-nodejs:15 3.5.0
eu-central-1 arn:aws:lambda:eu-central-1:410797082306:layer:instana-nodejs:181 3.5.0
eu-central-2 arn:aws:lambda:eu-central-2:410797082306:layer:instana-nodejs:27 3.5.0
eu-north-1 arn:aws:lambda:eu-north-1:410797082306:layer:instana-nodejs:181 3.5.0
eu-south-1 arn:aws:lambda:eu-south-1:410797082306:layer:instana-nodejs:27 3.5.0
eu-south-2 arn:aws:lambda:eu-south-2:410797082306:layer:instana-nodejs:27 3.5.0
eu-west-1 arn:aws:lambda:eu-west-1:410797082306:layer:instana-nodejs:181 3.5.0
eu-west-2 arn:aws:lambda:eu-west-2:410797082306:layer:instana-nodejs:181 3.5.0
eu-west-3 arn:aws:lambda:eu-west-3:410797082306:layer:instana-nodejs:181 3.5.0
il-central-1 arn:aws:lambda:il-central-1:410797082306:layer:instana-nodejs:24 3.5.0
me-central-1 arn:aws:lambda:me-central-1:410797082306:layer:instana-nodejs:26 3.5.0
me-south-1 arn:aws:lambda:me-south-1:410797082306:layer:instana-nodejs:26 3.5.0
sa-east-1 arn:aws:lambda:sa-east-1:410797082306:layer:instana-nodejs:180 3.5.0
us-east-1 arn:aws:lambda:us-east-1:410797082306:layer:instana-nodejs:180 3.5.0
us-east-2 arn:aws:lambda:us-east-2:410797082306:layer:instana-nodejs:180 3.5.0
us-west-1 arn:aws:lambda:us-west-1:410797082306:layer:instana-nodejs:180 3.5.0
us-west-2 arn:aws:lambda:us-west-2:410797082306:layer:instana-nodejs:180 3.5.0

That is, the pattern is arn:aws:lambda:${region}:410797082306:layer:instana-nodejs:${layer-version} (or arn:aws-cn:lambda:${region}:107998019096:layer:instana-nodejs:${layer-version} for AWS regions in China).

Make sure to always use the latest versions and update the layer version you are using in regular intervals to benefit from new features and fixes that we provide when publishing a new version of the layer.

As of version 71/1.121.0, the Node.js layer includes Instana's AWS Lambda extension. Monitoring data and traces will be offloaded locally to Instana's Lambda extension, which will then forward it to the Instana backend. This provides the following advantage: The Lambda function's response will be send back to the invoking client immediately when the handler has finished, without waiting for data to be send to the Instana backend. This feature is currently limited to Lambda functions configured with 256 MB of memory or more. Using the Instana Lambda extension can be disabled by setting the environment variable INSTANA_DISABLE_LAMBDA_EXTENSION to a non-empty string for the Lambda function.

Architecture arm64

Region ARN @instana/aws-lambda Version
af-south-1 arn:aws:lambda:af-south-1:410797082306:layer:instana-nodejs-arm64:26 3.5.0
ap-east-1 arn:aws:lambda:ap-east-1:410797082306:layer:instana-nodejs-arm64:26 3.5.0
ap-northeast-1 arn:aws:lambda:ap-northeast-1:410797082306:layer:instana-nodejs-arm64:65 3.5.0
ap-northeast-2 arn:aws:lambda:ap-northeast-2:410797082306:layer:instana-nodejs-arm64:65 3.5.0
ap-northeast-3 arn:aws:lambda:ap-northeast-3:410797082306:layer:instana-nodejs-arm64:26 3.5.0
ap-south-1 arn:aws:lambda:ap-south-1:410797082306:layer:instana-nodejs-arm64:65 3.5.0
ap-south-2 arn:aws:lambda:ap-south-2:410797082306:layer:instana-nodejs-arm64:26 3.5.0
ap-southeast-1 arn:aws:lambda:ap-southeast-1:410797082306:layer:instana-nodejs-arm64:65 3.5.0
ap-southeast-2 arn:aws:lambda:ap-southeast-2:410797082306:layer:instana-nodejs-arm64:65 3.5.0
ap-southeast-3 arn:aws:lambda:ap-southeast-3:410797082306:layer:instana-nodejs-arm64:26 3.5.0
ap-southeast-4 arn:aws:lambda:ap-southeast-4:410797082306:layer:instana-nodejs-arm64:26 3.5.0
ca-central-1 arn:aws:lambda:ca-central-1:410797082306:layer:instana-nodejs-arm64:65 3.5.0
cn-north-1 arn:aws-cn:lambda:cn-north-1:107998019096:layer:instana-nodejs-arm64:15 3.5.0
cn-northwest-1 arn:aws-cn:lambda:cn-northwest-1:107998019096:layer:instana-nodejs-arm64:15 3.5.0
eu-central-1 arn:aws:lambda:eu-central-1:410797082306:layer:instana-nodejs-arm64:65 3.5.0
eu-central-2 arn:aws:lambda:eu-central-2:410797082306:layer:instana-nodejs-arm64:26 3.5.0
eu-north-1 arn:aws:lambda:eu-north-1:410797082306:layer:instana-nodejs-arm64:65 3.5.0
eu-south-1 arn:aws:lambda:eu-south-1:410797082306:layer:instana-nodejs-arm64:26 3.5.0
eu-south-2 arn:aws:lambda:eu-south-2:410797082306:layer:instana-nodejs-arm64:26 3.5.0
eu-west-1 arn:aws:lambda:eu-west-1:410797082306:layer:instana-nodejs-arm64:65 3.5.0
eu-west-2 arn:aws:lambda:eu-west-2:410797082306:layer:instana-nodejs-arm64:65 3.5.0
eu-west-3 arn:aws:lambda:eu-west-3:410797082306:layer:instana-nodejs-arm64:65 3.5.0
il-central-1 arn:aws:lambda:il-central-1:410797082306:layer:instana-nodejs-arm64:24 3.5.0
me-central-1 arn:aws:lambda:me-central-1:410797082306:layer:instana-nodejs-arm64:26 3.5.0
me-south-1 arn:aws:lambda:me-south-1:410797082306:layer:instana-nodejs-arm64:26 3.5.0
sa-east-1 arn:aws:lambda:sa-east-1:410797082306:layer:instana-nodejs-arm64:65 3.5.0
us-east-1 arn:aws:lambda:us-east-1:410797082306:layer:instana-nodejs-arm64:65 3.5.0
us-east-2 arn:aws:lambda:us-east-2:410797082306:layer:instana-nodejs-arm64:65 3.5.0
us-west-1 arn:aws:lambda:us-west-1:410797082306:layer:instana-nodejs-arm64:65 3.5.0
us-west-2 arn:aws:lambda:us-west-2:410797082306:layer:instana-nodejs-arm64:65 3.5.0

Instana Lambda Layer for Container Based Functions

If your team uses Container based Lambda deploys, you can use our base containers on icr.io/instana/aws-lambda-nodejs or include the following snippet in your Dockerfile and set the build time arguments to the appropriate versions.

# This is the container image that delivers Instana's monitoring capabilities.
# It will not become the base image for your Lambda container image, it just provides a few files.
FROM icr.io/instana/aws-lambda-nodejs:latest as instana-layer

# This is the actual base image for your Lambda container image. You can also use any other base image that is suitable
# for container image based Lambda functions.
FROM public.ecr.aws/lambda/nodejs:14

# Copy Instana's Node.js monitoring components into your Lambda container image.
COPY --from=instana-layer /opt/extensions/ /opt/extensions/
COPY --from=instana-layer /opt/nodejs/ /opt/nodejs/

# The remainder of your Dockerfile, as it was without adding the Instana layer. The following is just an example:
COPY index.js package.json package-lock.json /var/task/
WORKDIR /var/task
RUN npm install

# Override the CMD. This can also be done as a parameter override outside of the Dockerfile, for example in the AWS console.
# If you use ES modules, use CMD [ "instana-aws-lambda-auto-wrap-esm.handler" ] instead.
CMD [ "instana-aws-lambda-auto-wrap.handler" ]

Instead of icr.io/instana/aws-lambda-nodejs:latest, you can also use a specific version of the Instana npm module @instana/aws-lambda greater or equal to 1.137.2 (see CHANGELOG), so for example:

FROM icr.io/instana/aws-lambda-nodejs:1.140.1 as instana-layer

Or you can only pin the major version, while allowing for more recent minor/patch releases:

FROM icr.io/instana/aws-lambda-nodejs:1 as instana-layer

Future versions of icr.io/instana/aws-lambda-nodejs will drop support for older Lambda Node.js runtimes. For example, beginning with version icr.io/instana/aws-lambda-nodejs:2.0.0, support for nodejs8.x will be dropped. You are recommended to pin the major version when using older Lambda runtimes.

Instana Lambda Layer & Manual Wrapping

You can also add the Instana Lambda layer to your function as described above, but refrain from using instana-aws-lambda-auto-wrap.handler. In particular, this is the recommended approach for AWS Lambdas based on the "Node.js 8.10" runtime. Here are the required steps for this setup:

  1. Add the Instana Lambda layer to your function. You can find the ARN of the Instana Lambda layer in the table above.
  2. Add the environment variables INSTANA_ENDPOINT_URL and INSTANA_AGENT_KEY with the required values.
  3. Modify the function's code according to the section Manually Wrapping the Handler.

Installing @instana/aws-lambda Manually

Instead of using the Instana Lambda layer, you can also choose to install the npm package @instana/aws-lambda manually:

  1. Add the dependency @instana/aws-lambda to your project by executing npm install -S @instana/aws-lambda (or yarn add @instana/aws-lambda) in your project directory. This will add the package to your node_modules folder and save the dependency in your package.json file.
  2. Add the environment variables INSTANA_ENDPOINT_URL and INSTANA_AGENT_KEY with the required values.
  3. Modify the function's code according to the section Manually Wrapping the Handler.

Manually Wrapping the Handler

If you do not want or fail to use the auto-wrap handler, you need to modify the code of your Node.js AWS Lambda function slightly to enable Instana tracing for it.

The code modifications described in this section are not required if you use the Instana Lambda layer and the auto-wrap handler as described in the section AutoTrace AWS Lambdas.

If you bundle your Lambda handler with webpack, this approach is not recommended, since Instana's core packge does not support being pre-processed with webpack. The AutoTrace AWS Lambdas approach is suitable for Lambdas using webpack. As an alternative, you can use manual wrapping and exclude, at a minimum, the package @instana/aws-lambda (or all dependencies) from being preprocessed by webpack. See this section in the Node.js documentation; for the serverless framework also refer to the Serverless framework section.

  1. Add the line const instana = require('@instana/aws-lambda'); to the very top of your handler JavaScript file.
  2. Wrap your handler function in an instana.wrap() call.
  3. Configure the environment variables for the connection to the Instana backend as described in the Instana AutoTrace for AWS Lambda documentation.

Here are some before/after examples for the different handler function styles that can be used for Node.js based AWS Lambdas:

Async Function Style Handler

If you use an async function as your handler, it should look like this:

exports.handler = async (event, context) => {
  // your code
};

The resulting code should look like this:

const instana = require('@instana/aws-lambda');

exports.handler = instana.wrap(async (event, context) => {
  // your code
}); // <- don't forget the closing ) for the instana.wrap(

Promise Style Lambda Handler

If you use a promise style handler, it should look like this:

exports.handler = (event, context) => {
  // your code, which returns a promise
};

The resulting code should look like this:

const instana = require('@instana/aws-lambda');

exports.handler = instana.wrap((event, context) => {
  // your code, which returns a promise
}); // <- don't forget the closing ) for the instana.wrap(

Callback Style Lambda Handler

If you use a callback style handler, it should look like this:

exports.handler = (event, context, callback) => {
  // your code
};

The resulting code should look like this:

const instana = require('@instana/aws-lambda');

exports.handler = instana.wrap((event, context, callback) => {
  // your code
}); // <- don't forget the closing ) for the instana.wrap(

Configuration Object

You can also pass in an optional configuration object as the first argument when wrapping your handler:

exports.handler = instana.wrap({
    // ... your configuration, for example:
    tracing: {
      stackTraceLength: 10
    }
  },
  async (event, context) => {
  // your code
});

Configuration values that are not supported in native Lambda tracing (like agentHost, agentPort and reportUnhandledPromiseRejections) are silently ignored.

Note that you can also use the environment variables listed in section Other Configuration Options and most of the ones listed on the Node.js configuration page.

Integrating Instana Tracing with the Serverless Framework

Edit the serverless.yml to integrate Instana tracing with the Serverless Framework. Follow the steps:

  1. Copy the Layer ARN from the list, and add the ARN to the layers section of the target function definition.

  2. Add environment variables INSTANA_AGENT_KEY, INSTANA_ENDPOINT_URL and LAMBDA_HANDLER. For further information, see Instana AutoTrace setup.

See the following example serverless.yml:

service: service-a

provider:
  name: aws
  runtime: nodejs16.x
  stage: dev
  region: us-east-2

functions:
  with-layer:
    environment:
      INSTANA_ENDPOINT_URL: INSTANA_ENDPOINT_URL
      INSTANA_AGENT_KEY: INSTANA_AGENT_KEY
      LAMBDA_HANDLER: src/index.handler
    layers:
      - arn:aws:lambda:us-east-2:410797082306:layer:instana-nodejs:111
    handler: instana-aws-lambda-auto-wrap.handler

Serverless Offline

Prerequisite: Ensure that you have followed step 1 and 2 in the Integrating Instana Tracing with the Serverless Framework section.

Edit the serverless.yml file to intergate Instana with the Serverless Framework and Serverless Offline. Follow the steps:

  1. Set the NODE_PATH environment variable to be $NODE_PATH:/opt/nodejs/node_modules.
  2. Set useDocker field to be true in the custom section. Then the Instana layer will be downloaded into a Docker container automatically.

See the following example serverless.yml:

service: service-b

provider:
  name: aws
  runtime: nodejs12.x
  stage: dev
  region: us-east-2

plugins:
  - serverless-offline

custom:
  serverless-offline:
    useDocker: true

functions:
  with-serverless-offline:
    environment:
      NODE_PATH: $NODE_PATH:/opt/nodejs/node_modules
      INSTANA_ENDPOINT_URL: INSTANA_ENDPOINT_URL
      INSTANA_AGENT_KEY: INSTANA_AGENT_KEY
      LAMBDA_HANDLER: src/index.handler
    layers:
      - arn:aws:lambda:us-east-2:410797082306:layer:instana-nodejs:111
    handler: instana-aws-lambda-auto-wrap.handler

Serverless Webpack

Prerequisite: Ensure that you have followed step 1 and 2 in the Integrating Instana Tracing with the Serverless Framework section.

Edit the serverless.yml file to intergate Instana with the Serverless Framework and Serverless Webpack.

Add entrypoint to the target Lambda function definition. The entrypoint is your original Node.js Lambda handler, which is triggered automatically by the Instana Lambda layer. For further information, see Instana AutoTrace setup.

See the following example serverless.yml:

service: service-c

provider:
  name: aws
  runtime: nodejs12.x
  stage: dev
  region: us-east-2

plugins:
  - serverless-webpack

package:
  individually: true

functions:
  with-serverless-webpack:
    environment:
      INSTANA_ENDPOINT_URL: INSTANA_ENDPOINT_URL
      INSTANA_AGENT_KEY: INSTANA_AGENT_KEY
      LAMBDA_HANDLER: src/index.handler
    layers:
      - arn:aws:lambda:us-east-2:410797082306:layer:instana-nodejs:110
    handler: instana-aws-lambda-auto-wrap.handler
    entrypoint: src/index.handler

Notes:

Fire & Forget Calls

If you use fire-and-forget style calls in your Node.js Lambda function, Instana cannot guarantee to capture those reliably. A fire-and-forget call is any asynchronous call for which you do not wait for the result. Here is an example:

const fetch = require('node-fetch');

exports.handler = async event => {
  fetch('https://example.com/fire-and-forget'); // No await here!

  const response = await fetch('https://example.com/wait-for-me');

  return {
    message: response.text()
  };
}

This Lambda handler uses the node-fetch package to make two HTTP calls. The second call is called with the async keyword, thus execution will wait for it to finish. This call will be traced reliably.

In contrast to this, the code does not wait for the result of the first call (fetch('https://example.com/fire-and-forget')). That call might have finished by the time the Lambda execution finishes or not. If it has not finished when the Lamba execution as a whole terminates, the call will not be reported to the Instana backend. If you inspect a corresponding trace in the Instana UI you might see a warning that says "Parent span is missing for some of the entry spans in this trace during the processing."

This example used the async/await style, but similar examples also exist for promise-style and callback-style code.

SSM Support

Available from the version 99 of the layer instana-nodejs/@instana/aws-lambda@1.138.0.

You can also provide the Instana Agent Key via the AWS SSM (System Manager) Parameter Store.

  1. Add the Instana Agent Key to your SSM parameter store. Remember or copy the parameter name.
  2. Remove INSTANA_AGENT_KEY from your environment variables.
  3. Add INSTANA_SSM_PARAM_NAME to your environment variables with the copied parameter name.
  4. If you have added the parameter as a "SecureString", you also need to set INSTANA_SSM_DECRYPTION=true. If you have used type "String", no additional variable needs to be set.

If you don't remove INSTANA_AGENT_KEY from your environment variables, the SSM environment variables will be ignored.

Older Node.js Lambda Runtimes

At the time of writing, Amazon offers Node.js 14, 12, and 10 as Lambda runtimes. Instana does not support older Node.js Lambda runtimes that have already been decomissioned by AWS (e.g. Node 4 and 6). If you still have Lambdas deployed that use those runtimes, update them to a more recent Node.js Lambda runtime before configuring them for native Instana tracing. Node.js 8 is still supported for now although it is already end of life.

Using the Instana API in Lambda Functions

You can access and use the entire Instana API in your Lambda code, same as in a plain vanilla Node.js app using @instana/collector.

If you use the Instana Node.js Lambda layer and the auto-wrap handler, you need to add the following line to your code:

const instana = require('@instana/aws-lambda');

If you use manual wrapping, you have that line already in your Lambda handler file.

If you use the Instana Node.js Lambda layer, do not add the package @instana/aws-lambda as a dependency to your package.json file. This package is provided by the Instana Node.js Lambda layer. Adding it as a dependency while also using the Lambda layer is not supported.

If your Lambda function code consists of multiple source files, you can also add the statement const instana = require('@instana/aws-lambda'); in other source code files to get access to the Instana Node.js API there.

Additional Environment Variables

Name Default Value Description
INSTANA_DISABLE_LAMBDA_EXTENSION false Any non-empty string. Disable the lambda extension or not.