AWS Lambda Extension (Experimental)edit

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

Elastic’s APM Agents instrument AWS Lambda functions via an AWS Lambda Extension.

Extension Architectureedit

Normally, during the execution of a Lambda function, there’s only a single language process running in the AWS Lambda execution environment. However, with an AWS Lambda Extension, Lambda users can run a second process alongside their main service/application process.

image showing data flow from lambda function

By using a custom-built AWS Lambda Extension, Elastic APM Agents can send data to a locally running Lambda Extension process, and that process will forward data on to APM Server. The Lambda Extension ensures that any latency between the Lambda function and the AWS Server instance will not cause latency in the Lambda function/Service itself.

Instrumenting a Lambda Functionedit

The rest of this guide contains instructions for instrumenting a Lambda function. There are two high level steps to instrumenting an AWS Lambda function.

We’ll start with installing the Lambda extension.

Installing the Lambda Extension using the Installeredit

Elastic offers an installer for adding the Lambda Extension to your Lambda functions. If you’d prefer to skip the installer and manually install the extension, see the Manual Installation section below.

This installer will:

  1. Compile the Lambda Extension from source (written in go)
  2. Publish the Lambda Extension as a layer
  3. Configure a named Lambda function with the just published layer
  4. Configure the required environmental variables

If you’d rather manually install and configuration the Lambda Extension, see the Manual Installation section below.

The installer is distributed via GitHub as a Node.js project. Once you’ve cloned the repository and installed a version of Node.js, run the following commands.

    $ cd cli
    $ npm install   # installs the dependencies for the cli
    $ cp install.yaml.dist install.yaml
    # edit install.yaml to use your values (see below)
    $ ./elastic-lambda.js install

The elastic-lambda.js command assumes you have a install.yaml file configured. There’s a sample of this file distributed with the repository. To use it, just copy the file and edit its contents.

    $ cp install.yaml install.yaml.dist

Important: The installer assumes your local environment is configured to authenticate against the AWS APIs using Amazon’s standard environment variables. Depending on your authentication method, this may look something like the following

    $ AWS_DEFAULT_REGION=us-west-2 \
      AWS_ACCESS_KEY_ID=AKIAZEDJODE3B3UMDAKX \
      AWS_SECRET_ACCESS_KEY=hmE7n1gfiyXzgwOQu2bxOA92HrVVWh8WG \
      ./elastic-lambda.js install

Configuring the Installeredit

A fully configured install.yaml might look like the following

install:
  config:
    layer_name: "apm-lambda-extension"
    function_name: "your-function-name"
    lambda_env:
      ELASTIC_APM_LOG_LEVEL: "info"
      ELASTIC_APM_SECRET_TOKEN: "D...a"
      ELASTIC_APM_SERVER_URL: "https://apm-server.example.com:443"
      ELASTIC_APM_SERVICE_NAME: "Your Service Name"
      ELASTIC_APM_DATA_RECEIVER_TIMEOUT_SECONDS: "15"

The meaning of each install.yaml configuration field is as follows.

layer_nameedit

This is the name the compiler will use for your AWS Layer. The default, apm-lambda-extension, should work for most scenarios.

function_nameedit

The name of your Lambda function. The installer will use this to configure the correct Lambda function. This must be the name of a function that already exists.

lambda_envedit

The installer will use the key/value pairs in this section of the configuration file to add environment variables to your Lambda function. The provided variables are those required to make the extension work correctly.

ELASTIC_APM_LOG_LEVELedit

The log level for the APM Agent. Consult your APM Agent’s documentation for more information.

ELASTIC_APM_SECRET_TOKENedit

The APM secret token. The extension will use this when communicating with APM Server.

ELASTIC_APM_API_KEYedit

An alternative authentication method to the secret token. The extension will use this when communicating with APM Server.

ELASTIC_APM_SERVER_URLedit

Your APM Server URL. This is the final destination for your data.

ELASTIC_APM_SERVICE_NAMEedit

The configured name of your application or service. The APM Agent will use this value when reporting data to APM Server. If unset, the APM Agent will automatically set the value based on AWS_LAMBDA_FUNCTION_NAME or context.functionName.

ELASTIC_APM_DATA_RECEIVER_TIMEOUT_SECONDSedit

The timeout value, in seconds, for the Lambda Extension’s server.

Manual Installationedit

It’s possible to install and configure the extension manually. In order to do so, you’ll need to

  1. Download a release zip file
  2. Publish that release zip file as a Lambda layer
  3. Configure your function to use that layer
  4. Configure your function’s environment variables correctly
Download a Released Extensionedit

The extension is released as a ZIP archive via the GitHub releases page. To download an archive, simply navigate to the latest version, and choose either the AMD64 or ARM64 release (depending on which architecture your Lambda function uses).

image of assets tab in releases

Publish a Lambda layeredit

Next, you’ll want to take that release ZIP file and publish it as a Lambda layer. A Lambda layer is a zip file archive that contains additional code or files for your Lambda function.

To do this, navigate to the Layers section of the AWS console, click the Create layer button, and follow the prompts to upload the ZIP archive as a layer.

image of layers section in the Amazon Console

After publishing a layer, you’ll receive a Version ARN. This ARN is the layer’s unique identifier.

Configure the Layeredit

Once you’ve published a layer, you’ll need to configure your function to use that layer. To add a layer

  1. Navigate to your function in the AWS Console
  2. Scroll to the Layers section and click the Add a layer button image of layer configuration section in AWS Console
  3. Choose the Specify an ARN radio button
  4. Enter the Version ARN of your layer in the Specify an ARN text input
  5. Click the Add button
Configure your Environment Variablesedit

Finally, once the layer’s in place you’ll need to configure a few environmental variables. To configure variables

  1. Navigate to your function in the AWS Console
  2. Click on the Configuration tab
  3. Click on Environment variables
  4. Add the necessary variables.
The Necessary Variablesedit

The necessary environment variables depend on the APM agent being used. Follow the Node.js agent setup guide, Python agent setup guide or Java agent setup guide, respectively, for specific instructions on setting the environment variables.

ELASTIC_APM_CENTRAL_CONFIGedit

The ELASTIC_APM_CENTRAL_CONFIG value must be set to false. Central configuration does not work in a Lambda environment, and having this on will negatively impact the performance of your Lambda function.

ELASTIC_APM_CLOUD_PROVIDERedit

The ELASTIC_APM_CLOUD_PROVIDER value must be set to none. Amazon’s Cloud Metadata APIs are not available in an AWS Lambda environment, and attempting to fetch this data will negatively impact the performance of your Lambda function.

ELASTIC_APM_LAMBDA_APM_SERVERedit

The ELASTIC_APM_LAMBDA_APM_SERVER controls where the Lambda extension will ship data. This should be the URL of the final APM Server destination for your telemetry.

ELASTIC_APM_SECRET_TOKEN or ELASTIC_APM_API_KEYedit

Either ELASTIC_APM_API_KEY or ELASTIC_APM_SECRET_TOKEN needs to be set. This controls the authentication method that the extension uses when sending data to the URL configured via ELASTIC_APM_LAMBDA_APM_SERVER.

ELASTIC_APM_SERVER_URLedit

This must be configured to the value http://localhost:8200. This configuration field controls where your APM Agent sends data. The extension listens for data on localhost:8200.

Configuring the Agent and Lambda Function handleredit

Once you’ve installed the extension, there’s one last step to take. You’ll need to wrap the Lambda function handler.

Node.jsedit

In Node.js, you wrap a Lambda function handler using the following syntax.

const apm = require('elastic-apm-node').start({/*...*/})
exports.handler = apm.lambda(async function handler (event, context) {
    const response = {
      statusCode: 200,
      body: "hello new async."
    };
    return response
})

See the Node.js agent setup guide for detailed instructions on setting up the Node.js agent for AWS Lambda.

Pythonedit

In Python, you wrap a Lambda function handler using the following syntax.

from elasticapm import capture_serverless
@capture_serverless()
def handler(event, context):
    return {"statusCode": r.status_code, "body": "Success!"}

See the Python agent setup guide for detailed instructions on setting up the Python agent for AWS Lambda.

Javaedit

Like the extension, the Elastic APM Java agent is installed as a Lambda layer. Since it relies on a wrapper script to automatically attach to the Lambda function, not all environment variables listed in The Necessary Variables need to be configured.

See the Java agent setup guide for detailed instructions on setting up the Java agent for AWS Lambda.