Instrumenting Node.js Serverless Applications
If you previously set up your Lambda functions using the Datadog Forwarder, see
instrumenting using the Datadog Forwarder. Otherwise, follow the instructions in this guide to instrument using the Datadog Lambda Extension.
Installation
Datadog offers many different ways to enable instrumentation for your serverless applications. Choose a method below that best suits your needs. Datadog generally recommends using the Datadog CLI. You must follow the instructions for “Container Image” if your application is deployed as a container image.
The Datadog CLI modifies existing Lambda functions’ configurations to enable instrumentation without requiring a new deployment. It is the quickest way to get started with Datadog’s serverless monitoring.
Install the Datadog CLI client
npm install -g @datadog/datadog-ci
If you are new to Datadog serverless monitoring, launch the Datadog CLI in the interactive mode to guide your first installation for a quick start, and you can ignore the remaining steps. To permanently install Datadog for your production applications, skip this step and follow the remaining ones to run the Datadog CLI command in your CI/CD pipelines after your normal deployment.
datadog-ci lambda instrument -i
Configure the AWS credentials
Datadog CLI requires access to the AWS Lambda service, and depends on the AWS JavaScript SDK to resolve the credentials. Ensure your AWS credentials are configured using the same method you would use when invoking the AWS CLI.
Configure the Datadog site
export DATADOG_SITE="<DATADOG_SITE>"
Replace <DATADOG_SITE>
with
(ensure the correct SITE is selected on the right).
Configure the Datadog API key
Datadog recommends saving the Datadog API key in AWS Secrets Manager for security and easy rotation. The key needs to be stored as a plaintext string (not a JSON blob). Ensure your Lambda functions have the required secretsmanager:GetSecretValue
IAM permission.
export DATADOG_API_KEY_SECRET_ARN="<DATADOG_API_KEY_SECRET_ARN>"
For quick testing purposes, you can also set the Datadog API key in plaintext:
export DATADOG_API_KEY="<DATADOG_API_KEY>"
Instrument your Lambda functions
Note: Instrument your Lambda functions in a dev or staging environment first! Should the instrumentation result be unsatisfactory, run uninstrument
with the same arguments to revert the changes.
To instrument your Lambda functions, run the following command.
datadog-ci lambda instrument -f <functionname> -f <another_functionname> -r <aws_region> -v 101 -e 51
To fill in the placeholders:
- Replace
<functionname>
and <another_functionname>
with your Lambda function names. Alternatively, you can use --functions-regex
to automatically instrument multiple functions whose names match the given regular expression. - Replace
<aws_region>
with the AWS region name.
Additional parameters can be found in the CLI documentation.
The Datadog Serverless Plugin automatically configures your functions to send metrics, traces, and logs to Datadog through the Datadog Lambda Extension.
To install and configure the Datadog Serverless Plugin, follow these steps:
Install the Datadog Serverless Plugin:
serverless plugin install --name serverless-plugin-datadog
Update your serverless.yml
:
custom:
datadog:
site: <DATADOG_SITE>
apiKeySecretArn: <DATADOG_API_KEY_SECRET_ARN>
To fill in the placeholders:
- Replace
<DATADOG_SITE>
with
(ensure the correct SITE is selected on the right). - Replace
<DATADOG_API_KEY_SECRET_ARN>
with the ARN of the AWS secret where your Datadog API key is securely stored. The key needs to be stored as a plaintext string (not a JSON blob). The secretsmanager:GetSecretValue
permission is required. For quick testing, you can instead use apiKey
and set the Datadog API key in plaintext.
For more information and additional settings, see the plugin documentation.
The Datadog CloudFormation macro automatically transforms your SAM application template to install Datadog on your functions using Lambda layers, and configures your functions to send metrics, traces, and logs to Datadog through the Datadog Lambda Extension.
Install the Datadog CloudFormation macro
Run the following command with your AWS credentials to deploy a CloudFormation stack that installs the macro AWS resource. You only need to install the macro once for a given region in your account. Replace create-stack
with update-stack
to update the macro to the latest version.
aws cloudformation create-stack \
--stack-name datadog-serverless-macro \
--template-url https://datadog-cloudformation-template.s3.amazonaws.com/aws/serverless-macro/latest.yml \
--capabilities CAPABILITY_AUTO_EXPAND CAPABILITY_IAM
The macro is now deployed and ready to use.
Instrument your Lambda functions
Add the DatadogServerless
transform after the AWS::Serverless
transform under the Transform
section in your for SAM template.yml
.
Transform:
- AWS::Serverless-2016-10-31
- Name: DatadogServerless
Parameters:
stackName: !Ref "AWS::StackName"
nodeLayerVersion: 101
extensionLayerVersion: 51
site: "<DATADOG_SITE>"
apiKeySecretArn: "<DATADOG_API_KEY_SECRET_ARN>"
To fill in the placeholders:
- Replace
<DATADOG_SITE>
with
(ensure the correct SITE is selected on the right). - Replace
<DATADOG_API_KEY_SECRET_ARN>
with the ARN of the AWS secret where your Datadog API key is securely stored. The key needs to be stored as a plaintext string (not a JSON blob). The secretsmanager:GetSecretValue
permission is required. For quick testing, you can use apiKey
instead and set the Datadog API key in plaintext.
More information and additional parameters can be found in the macro documentation.
The Datadog CDK Construct automatically installs Datadog on your functions using Lambda Layers, and configures your functions to send metrics, traces, and logs to Datadog through the Datadog Lambda Extension.
Install the Datadog CDK constructs library
# For AWS CDK v1
npm install datadog-cdk-constructs --save-dev
# For AWS CDK v2
npm install datadog-cdk-constructs-v2 --save-dev
Instrument your Lambda functions
// For AWS CDK v1
import { Datadog } from "datadog-cdk-constructs";
// For AWS CDK v2
import { Datadog } from "datadog-cdk-constructs-v2";
const datadog = new Datadog(this, "Datadog", {
nodeLayerVersion: 101,
extensionLayerVersion: 51,
site: "<DATADOG_SITE>",
apiKeySecretArn: "<DATADOG_API_KEY_SECRET_ARN>"
});
datadog.addLambdaFunctions([<LAMBDA_FUNCTIONS>])
To fill in the placeholders:
- Replace
<DATADOG_SITE>
with
(ensure the correct SITE is selected on the right). - Replace
<DATADOG_API_KEY_SECRET_ARN>
with the ARN of the AWS secret where your Datadog API key is securely stored. The key needs to be stored as a plaintext string (not a JSON blob).The secretsmanager:GetSecretValue
permission is required. For quick testing, you can use apiKey
instead and set the Datadog API key in plaintext.
More information and additional parameters can be found on the Datadog CDK documentation.
Install the Datadog Lambda Library
If you are deploying your Lambda function as a container image, you cannot use the Datadog Lambda library as a Lambda Layer. Instead, you must package the Datadog Lambda and tracing libraries within the image.
npm install datadog-lambda-js dd-trace
Note that the minor version of the datadog-lambda-js
package always matches the layer version. For example, datadog-lambda-js v0.5.0
matches the content of layer version 5.
Install the Datadog Lambda Extension
Add the Datadog Lambda Extension to your container image by adding the following to your Dockerfile:
COPY --from=public.ecr.aws/datadog/lambda-extension:<TAG> /opt/extensions/ /opt/extensions
Replace <TAG>
with either a specific version number (for example, 51
) or with latest
. Alpine is also supported with specific version numbers (such as 51-alpine
) or with latest-alpine
. You can see a complete list of possible tags in the Amazon ECR repository.
Redirect the handler function
- Set your image’s
CMD
value to node_modules/datadog-lambda-js/dist/handler.handler
. You can set this in AWS or directly in your Dockerfile. Note that the value set in AWS overrides the value in the Dockerfile if you set both. - Set the environment variable
DD_LAMBDA_HANDLER
to your original handler, for example, myfunc.handler
. - If you are using ESModule with the container, you will need to remove the
handler.js
file. This file exists for Node 12 and will be removed when AWS deprecates Node 12 support.RUN rm node_modules/datadog-lambda-js/dist/handler.js
CMD ["node_modules/datadog-lambda-js/dist/handler.handler"]
Note: If your Lambda function runs on arm64
, you must either build your container image in an arm64-based Amazon Linux environment or apply the Datadog wrapper in your function code instead. You may also need to do that if you are using a third-party security or monitoring tool that is incompatible with the Datadog handler redirection.
Configure the Datadog site and API key
- Set the environment variable
DD_SITE
to
(ensure the correct SITE is selected on the right). - Set the environment variable
DD_API_KEY_SECRET_ARN
with the ARN of the AWS secret where your Datadog API key is securely stored. The key needs to be stored as a plaintext string (not a JSON blob). The secretsmanager:GetSecretValue
permission is required. For quick testing, you can use DD_API_KEY
instead and set the Datadog API key in plaintext.
Use this format for your Terraform resource:
resource "aws_lambda_function" "lambda" {
"function_name" = ...
...
# Remember sure to choose the right layers based on your Lambda architecture and AWS regions
layers = [
<DATADOG_TRACER_ARN>,
<DATADOG_EXTENSION_ARN>
]
handler = "/opt/nodejs/node_modules/datadog-lambda-js/handler.handler"
environment {
variables = {
DD_SITE = <DATADOG_SITE>
DD_API_KEY_SECRET_ARN = <API_KEY>
DD_LAMBDA_HANDLER = <LAMBDA_HANDLER>
}
}
}
Fill in variables accordingly:
Replace <DATADOG_TRACER_ARN>
with the ARN of the appropriate Datadog tracer depending on your type of region:
AWS REGIONS | LAYERS |
---|
Commercial | arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-<RUNTIME>:101 |
GovCloud | arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:Datadog-<RUNTIME>:101 |
In the ARN, replace <AWS_REGION>
with a valid AWS region, such as us-east-1
. Replace <RUNTIME>
with Node14-x
, Node16-x
, Node18-x
or Node20-x
.
Replace <DATADOG_EXTENSION_ARN>
with the ARN of the appropriate Datadog Lambda Extension for your region and architecture:
AWS REGIONS | ARCHITECTURE | LAYERS |
---|
Commercial | x86_64 | arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-Extension:51 |
arm64 | arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-Extension-ARM:51 |
GovCloud | x86_64 | arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:Datadog-Extension:51 |
arm64 | arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:Datadog-Extension-ARM:51 |
Replace <DATADOG_SITE>
with
(ensure the correct SITE is selected on the right).
Replace <API_KEY>
with the ARN of the AWS secret where your Datadog API key is securely stored. The key needs to be stored as a plaintext string (not a JSON blob). The secretsmanager:GetSecretValue
permission is required. For quick testing, use DD_API_KEY
instead of DD_API_KEY_SECRET_ARN
and set the value to your Datadog API key in plaintext.
Replace <LAMBDA_HANDLER>
with your original handler. For example, myfunc.handler
.
Full example
resource "aws_lambda_function" "lambda" {
"function_name" = ...
...
# Remember sure to choose the right layers based on your Lambda architecture and AWS regions
layers = [
"arn:aws:lambda:us-east-1:464622532012:layer:Datadog-Node16-x:96",
"arn:aws:lambda:us-east-1:464622532012:layer:Datadog-Extension:45"
]
handler = "/opt/nodejs/node_modules/datadog-lambda-js/handler.handler"
environment {
variables = {
DD_SITE = datadoghq.com
DD_API_KEY_SECRET_ARN = "arn:aws..."
DD_LAMBDA_HANDLER = "myfunc.handler"
}
}
}
- Set the environment variable DD_LAMBDA_HANDLER to your original handler, for example,
myfunc.handler
.
If you are not using a serverless development tool that Datadog supports, such as the Serverless Framework or AWS CDK, Datadog strongly encourages you instrument your serverless applications with the
Datadog CLI.
Install the Datadog Lambda library
The Datadog Lambda Library can be imported either as a layer (recommended) OR as a JavaScript package.
The minor version of the datadog-lambda-js
package always matches the layer version. For example, datadog-lambda-js v0.5.0 matches the content of layer version 5.
Option A: Configure the layers for your Lambda function using the ARN in the following format:
# Use this format for AWS commercial regions
arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-<RUNTIME>:101
# Use this format for AWS GovCloud regions
arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:Datadog-<RUNTIME>:101
Replace <AWS_REGION>
with a valid AWS region such as us-east-1
. The available RUNTIME
options are Node12-x
, Node14-x
, Node16-x
and Node18-x
.
Option B: If you cannot use the prebuilt Datadog Lambda layer, alternatively you can install the packages datadog-lambda-js
and dd-trace
using your favorite package manager.
npm install datadog-lambda-js dd-trace
Install the Datadog Lambda Extension
Configure the layers for your Lambda function using the ARN in the following format:
# Use this format for x86-based Lambda deployed in AWS commercial regions
arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-Extension:51
# Use this format for arm64-based Lambda deployed in AWS commercial regions
arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-Extension-ARM:51
# Use this format for x86-based Lambda deployed in AWS GovCloud regions
arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:Datadog-Extension:51
# Use this format for arm64-based Lambda deployed in AWS GovCloud regions
arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:Datadog-Extension-ARM:51
Replace <AWS_REGION>
with a valid AWS region, such as us-east-1
.
Redirect the handler function
- Set your function’s handler to
/opt/nodejs/node_modules/datadog-lambda-js/handler.handler
if using the layer, or node_modules/datadog-lambda-js/dist/handler.handler
if using the package. - Set the environment variable
DD_LAMBDA_HANDLER
to your original handler, for example, myfunc.handler
.
Note: If your Lambda function runs on arm64
and the datadog-lambda-js
library is installed as a NPM package (option B of step 1), you must apply the Datadog wrapper in your function code instead. You may also need to do that if you are using a third-party security or monitoring tool that is incompatible with the Datadog handler redirection.
Configure Datadog site and API key
- Set the environment variable
DD_SITE
to
(ensure the correct SITE is selected on the right). - Set the environment variable
DD_API_KEY_SECRET_ARN
with the ARN of the AWS secret where your Datadog API key is securely stored. The key needs to be stored as a plaintext string (not a JSON blob). The secretsmanager:GetSecretValue
permission is required. For quick testing, you can use DD_API_KEY
instead and set the Datadog API key in plaintext.
What’s next?
- Congratulations! You can now view metrics, logs, and traces on the Serverless Homepage.
- Turn on threat monitoring to get alerted on attackers targeting your service.
- See the sample code to monitor custom business logic
- See the troubleshooting guide if you have trouble collecting the telemetry
- See the advanced configurations to
- connect your telemetry using tags
- collect telemetry for Amazon API Gateway, SQS, etc.
- capture the Lambda request and response payloads
- link errors of your Lambda functions to your source code
- filter or scrub sensitive information from logs or traces
Monitor custom business logic
To monitor your custom business logic, submit a custom metric or span using the sample code below. For additional options, see custom metric submission for serverless applications and the APM guide for custom instrumentation.
const { sendDistributionMetric, sendDistributionMetricWithDate } = require('datadog-lambda-js');
const tracer = require('dd-trace');
// submit a custom span named "sleep"
const sleep = tracer.wrap('sleep', (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms));
});
exports.handler = async (event) => {
// add custom tags to the lambda function span,
// does NOT work when X-Ray tracing is enabled
const span = tracer.scope().active();
span.setTag('customer_id', '123456');
await sleep(100);
// submit a custom span
const sandwich = tracer.trace('hello.world', () => {
console.log('Hello, World!');
});
// submit a custom metric
sendDistributionMetric(
'coffee_house.order_value', // metric name
12.45, // metric value
'product:latte', // tag
'order:online' // another tag
);
const response = {
statusCode: 200,
body: JSON.stringify('Hello from serverless!')
};
return response;
};
Further Reading
Additional helpful documentation, links, and articles: