The Datadog Lambda Forwarder is a surprisingly simple Lambda function that acts as a buffer and enrichment layer for your AWS Lambda logs, getting them to Datadog without you needing to configure anything on the Lambda function itself.
Let’s see it in action. Imagine a simple Python Lambda function that logs a message:
import json
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
logger.info("Processing an event")
return {
"statusCode": 200,
"body": json.dumps({
"message": "Hello from Lambda!",
}),
}
By default, this log would go to CloudWatch Logs. If you’ve set up the Datadog Lambda Forwarder, it will automatically subscribe to your Lambda function’s CloudWatch Log Group. When a log event is written, the Forwarder intercepts it.
Here’s what that intercepted log might look like before the Forwarder:
{
"message": "2023-10-27T10:00:00.123Z INFO Processing an event",
"timestamp": 1698397200123,
"level": "INFO",
"logStream": "2023/10/27/[$LATEST]abcdef1234567890abcdef1234567890",
"logGroup": "/aws/lambda/my-simple-function"
}
The Forwarder then processes this. It might add tags like aws_account, aws_region, function_name, and function_arn. It can also reformat the log message for better parsing in Datadog, potentially separating the timestamp, level, and message into distinct fields. The Forwarder then sends this enriched log to Datadog via the Datadog Agent API.
The problem this solves is the operational overhead of managing log ingestion. Without the Forwarder, you’d typically set up a separate process (like another Lambda function, Kinesis Firehose, or a dedicated agent on an EC2 instance) to pull logs from CloudWatch Logs and send them to Datadog. The Forwarder centralizes this into a single, managed Lambda function deployed via CloudFormation or Terraform.
The core of the Forwarder is its index.handler function. This function is triggered by CloudWatch Logs. It receives a payload containing log events. The Forwarder iterates through these events, extracts relevant information, adds Datadog-specific tags, and then batches them up to send to your Datadog intake endpoint.
Crucially, the Forwarder operates as a subscriber to your Lambda function’s CloudWatch Log Group. When you deploy the Forwarder using Datadog’s provided CloudFormation template, it creates a subscription filter on the log group of any Lambda function in the same account and region that matches its configuration. This means the logs are duplicated: they still go to CloudWatch Logs (for compliance, debugging, or if the Forwarder fails) and are also sent to Datadog.
You control the Forwarder’s behavior through environment variables. For example, DD_SITE tells the Forwarder which Datadog environment to send data to (e.g., datadoghq.com or datadoghq.eu). DD_API_KEY (or DD_API_KEY_SECRET_ARN for better security) is essential for authentication. DD_FORWARDER_LOG_GROUP_NAME can be used to limit which log groups the Forwarder processes, preventing it from consuming logs from unrelated functions. You can also configure DD_ENABLE_TAG_COLLECTION to true to automatically collect tags like aws_lambda_function_name and aws_lambda_function_arn.
The most surprising thing about the Forwarder is its ability to handle structured logging out-of-the-box. If your Lambda function emits JSON logs (e.g., by configuring your logger to output JSON), the Forwarder can often detect this and send the JSON payload directly to Datadog, preserving the structure for more powerful querying and visualization. This means you don’t need to manually parse your log messages within Datadog if your application already logs in a structured format.
The next step after getting logs into Datadog is usually to configure metrics collection from those logs.