DEV Community

Rodel Talampas
Rodel Talampas

Posted on

Dynatrace monitoring for AWS Lambda

There are many ways to setup the dynatrace agent for Lambdas. The list can be seen below:

I don't have a preferred way to do so, but looking at the way we build our lambdas, the most efficient for us is a combination of environment variables and serverless framework.

Prerequisites

As of 3 Sept 2021, Dynatrace only supports the OneAgent for Lambda which runtime based on Amazon Linux 2 image.

Trace Python, Node.js, and Java Lambda functions
Lambda runtimes - AWS Lambda

Environment Variables

The following base environment variables need to be set into the Lambda’s environment

AWS_LAMBDA_EXEC_WRAPPER = /opt/dynatrace
DT_TENANT = vpc123456
DT_CLUSTER_ID = 1234456789 # Dynatrace Cluster Id
DT_CONNECTION_BASE_URL = https://vpc123456.live.dynatrace.com
DT_CONNECTION_AUTH_TOKEN = dt0a01.vpc123456.b19e9577f4cqerew43f9721ba4282a0d8004ae36bbba9983421231aaa4e
DT_LOGGING_DESTINATION: stdout
Enter fullscreen mode Exit fullscreen mode

To add log monitoring there are language-specific values that need to added:

DT_LOGGING_NODEJS_FLAGS: Exporter=true,LambdaSensor=true
DT_LOGGING_PYTHON_FLAGS  dynatrace=True
DT_LOGGING_JAVA_FLAGS=log-Transformer=true,log-EmbeddedJarClassLoader=true,log-OpenTelemetryUtils=true,log-AsyncClassRetransformer=true,log-ClassValue=true
Enter fullscreen mode Exit fullscreen mode

If the lambda is coded in NodeJS, use DT_LOGGING_NODEJS_FLAGS accordingly, and so on.
These are hard-coded values that really never change unless we change our Dynatrace Tenancy.

Dynatrace Agent

The Dynatrace agent is nothing but a simple Lambda Layer. There are 3 Programming Languages supported at the moment: Java, NodeJS, and Python. Each has its own Lambda Layer ARN. The AWS Region also plays a part on the ARN String Formulation. The 725887861453 being the Dynatrace AWS Account.

NodeJS = arn:aws:lambda:ap-southeast-2:725887861453:layer:Dynatrace_OneAgent_1_215_1_20210326-040705_nodejs:1
Java = arn:aws:lambda:ap-southeast-2:725887861453:layer:Dynatrace_OneAgent_1_215_161_20210428-142723_java:1
Python = arn:aws:lambda:ap-southeast-2:725887861453:layer:Dynatrace_OneAgent_1_215_2_20210326-095702_python:1
Enter fullscreen mode Exit fullscreen mode

Serverless Framework

Depending on how you configure your serverless framework, files to be updated depends on that. In our case, we split out stages (or environment) and serverless yaml.

stages.yml | env.yml

default_env: &default_env
  apm_exec_wrapper: '/opt/dynatrace'
  apm_tenant: vpc123456
  apm_cluster_id: 1234456789 
  apm_base_url: https://vpc123456.live.dynatrace.com
  apm_auth_token: dt0a01.vpc123456.b19e9577f4cqerew43f9721ba4282a0d8004ae36bbba9983421231aaa4e
  apm_layer: arn:aws:lambda:ap-southeast-2:725887861453:layer:Dynatrace_OneAgent_1_215_1_20210326-040705_nodejs:1
  apm_log_dest: stdout
  apm_log_flags: 'Exporter=true,LambdaSensor=true'
Enter fullscreen mode Exit fullscreen mode

On every environment key, add the following line <<: *default_env:

qa:
  <<: *default_env
  ...
  ...

show:
  <<: *default_env
  ...
  ...

prod:
  <<: *default_env
  ...
  ...
Enter fullscreen mode Exit fullscreen mode

This will tell each environment to use the same settings as the default_env.

serverless.yml

Create a custom layer if not yet created, add the following lines

custom:
  # custom environment 
  environment: ${file(./stages.yml):${opt:stage}}
  # dynatrace environment variables
  apm_exec_wrapper: ${file(./stages.yml):${opt:stage}.apm_exec_wrapper}
  apm_tenant: ${file(./stages.yml):${opt:stage}.apm_tenant}
  apm_cluster_id: ${file(./stages.yml):${opt:stage}.apm_cluster_id}
  apm_base_url: ${file(./stages.yml):${opt:stage}.apm_base_url}
  apm_auth_token: ${file(./stages.yml):${opt:stage}.apm_auth_token}
  apm_log_dest: ${file(./stages.yml):${opt:stage}.apm_log_dest}
  apm_log_flags: ${file(./stages.yml):${opt:stage}.apm_log_flags}
  # dynatrace lambda layer
  apm_layer: ${file(./stages.yml):${opt:stage}.apm_layer}
Enter fullscreen mode Exit fullscreen mode

Plugin the Environment variables under the provider layer, create if none

provider:
  ...
  ...
  environment:
    ...
    ...
    # dynatrace environment variables
    AWS_LAMBDA_EXEC_WRAPPER: ${self:custom.environment.apm_exec_wrapper}
    DT_TENANT: ${self:custom.environment.apm_tenant}
    DT_CLUSTER_ID: ${self:custom.environment.apm_cluster_id}
    DT_CONNECTION_BASE_URL: ${self:custom.environment.apm_base_url}
    DT_CONNECTION_AUTH_TOKEN: ${self:custom.environment.apm_auth_token}
    DT_LOGGING_DESTINATION: ${self:custom.environment.apm_log_dest}
    DT_LOGGING_NODEJS_FLAGS: ${self:custom.environment.apm_log_flags}
  ...
  ...
  ...
Enter fullscreen mode Exit fullscreen mode

On every function that is defined, add the Dynatrace Lambda Layer

functions:
  ...
  consume:
    handler: ...
    layers:
       - ${self:custom.apm_layer}
    ...
    ...
Enter fullscreen mode Exit fullscreen mode

Dynatrace UI

When a Lambda is fully integrated into Dynatrace you will be able to see a direct link to the Lambda Cloudwatch Logs and it will be part of the Dynatrace Service.

Top comments (0)