🚀 Executive Summary
TL;DR: The article addresses the challenge of CloudWatch’s limited and costly log retention by providing a solution to sync critical logs to Datadog. This Python-based approach centralizes log visibility and offers a cost-effective method for long-term storage and analysis.
🎯 Key Takeaways
- A Python script utilizing `boto3` and `datadog` libraries can effectively filter CloudWatch log events and forward them to Datadog as events.
- Secure credential management is crucial, with recommendations for `config.env` using `python-dotenv` for development and IAM Roles for production environments.
- Automation via a cron job is essential for continuous syncing, and the script incorporates a `boto3` paginator for handling large log volumes and `time.sleep` to mitigate API rate limits.
Syncing CloudWatch Logs to Datadog for Retention
Hey team, Darian Vance here. Let’s talk about something that used to be a real time-sink for me: log spelunking. I’d jump between CloudWatch and Datadog, trying to piece together an incident report. The biggest headache was CloudWatch’s default retention. A critical log from a month ago? Gone. Extending retention in AWS is an option, but it gets pricey fast. My solution, which I now use in all my production setups, is to sync the important logs over to Datadog. You get centralized visibility and cost-effective long-term storage. This simple script probably saves me a few hours every month, and I want to walk you through how to set it up.
Prerequisites
Before we dive in, make sure you have the following ready to go:
- An AWS account with IAM credentials that have permissions for
logs:FilterLogEvents. - A Datadog account with your API Key and Application Key handy.
- Python 3 installed on the machine where this script will run.
- Access to a terminal or command line to install a few Python packages.
The Guide: A Step-by-Step Walkthrough
Step 1: Setting Up Your Environment
First, we need to get our Python environment ready. I’ll skip the standard virtual environment setup since you likely have your own workflow for that. The main thing is to install the libraries we’ll need. You can do this by running a command like ‘pip install boto3 datadog python-dotenv’ in your terminal.
Next, let’s handle our secrets. Create a file in your project directory named config.env. This is where we’ll store our keys so they aren’t hardcoded in the script, which is a major security no-no. Your file should look like this:
AWS_ACCESS_KEY_ID="YOUR_AWS_ACCESS_KEY"
AWS_SECRET_ACCESS_KEY="YOUR_AWS_SECRET_KEY"
AWS_REGION="us-east-1"
DATADOG_API_KEY="YOUR_DATADOG_API_KEY"
DATADOG_APP_KEY="YOUR_DATADOG_APP_KEY"
Pro Tip: For any real production environment, I strongly recommend using an IAM Role attached to the EC2 instance or Lambda function running the script. This is far more secure than storing IAM user credentials in a file. The `boto3` library will automatically pick up credentials from an IAM role, so you wouldn’t even need the AWS keys in your `config.env` file.
Step 2: The Python Sync Script
Now for the core logic. The goal here is to create a reusable script that can pull logs from a specified CloudWatch Log Group from the last ‘X’ hours and forward them to Datadog as events.
Here’s the full script. I’ll break down what each part does below.
import os
import boto3
import time
from datetime import datetime, timedelta, timezone
from datadog import initialize, api
from dotenv import load_dotenv
def main():
# --- Configuration ---
load_dotenv('config.env')
# Datadog credentials
dd_options = {
'api_key': os.getenv('DATADOG_API_KEY'),
'app_key': os.getenv('DATADOG_APP_KEY')
}
initialize(**dd_options)
# AWS credentials and log group
aws_region = os.getenv('AWS_REGION')
log_group_name = '/aws/lambda/your-function-name' # <-- IMPORTANT: Change this
# --- Logic ---
print(f"Starting sync for log group: {log_group_name}")
# Define the time window (last 24 hours)
end_time = datetime.now(timezone.utc)
start_time = end_time - timedelta(hours=24)
# Convert to milliseconds for AWS API
start_time_ms = int(start_time.timestamp() * 1000)
end_time_ms = int(end_time.timestamp() * 1000)
try:
# Connect to CloudWatch Logs
client = boto3.client(
'logs',
region_name=aws_region,
aws_access_key_id=os.getenv('AWS_ACCESS_KEY_ID'),
aws_secret_access_key=os.getenv('AWS_SECRET_ACCESS_KEY')
)
# Use a paginator to handle large log volumes
paginator = client.get_paginator('filter_log_events')
page_iterator = paginator.paginate(
logGroupName=log_group_name,
startTime=start_time_ms,
endTime=end_time_ms
)
log_count = 0
for page in page_iterator:
for event in page['events']:
log_message = event['message']
# Send to Datadog
api.Event.create(
title=f"CloudWatch Log from {log_group_name}",
text=log_message,
tags=[f"source:cloudwatch", f"log_group:{log_group_name}"],
source_type_name="aws"
)
log_count += 1
# Small delay to avoid hitting API rate limits
time.sleep(0.1)
print(f"Successfully synced {log_count} log events to Datadog.")
except Exception as e:
print(f"An error occurred: {e}")
return 1
return 0
if __name__ == "__main__":
main()
Code Breakdown:
- Configuration: We use
load_dotenvto pull in our secrets from theconfig.envfile. We then initialize the Datadog API with our keys. - Time Window: We calculate the start and end times for our log query. It’s critical to use timezone-aware datetime objects (
timezone.utc) to avoid any ambiguity, as AWS operates in UTC. - Boto3 Paginator: Instead of a simple
filter_log_eventscall, I’m using a paginator. This is a robust way to handle situations where a query returns more logs than can fit in a single API response. It automatically handles fetching subsequent pages of results for you. - Forwarding to Datadog: We loop through each log event found. For each one, we call
api.Event.create. Notice I’m adding tags like the source and log group name. This is incredibly useful for filtering and creating dashboards in Datadog later.
Step 3: Automating the Sync
Running this manually isn’t practical. We need to automate it. A simple cron job is perfect for this. For example, to run this script every day at 2 AM, you would set up a cron job like this. Don’t use a command like ‘crontab -e’, but rather add this line to your system’s crontab configuration.
0 2 * * * python3 script.py
Make sure you’re running this from the directory containing your script and `config.env` file, or adjust the paths accordingly. Remember, don’t use absolute paths starting with a slash in the cron command itself for security reasons.
Common Pitfalls (Where I Usually Mess Up)
- IAM Permissions: The most common error is an
AccessDeniedException. Double-check that your IAM user or role has thelogs:FilterLogEventspermission for the specific log group you are targeting. - API Rate Limiting: If you’re syncing a very chatty log group, you might hit AWS or Datadog API rate limits. The small
time.sleep(0.1)in the loop helps, but for massive volumes, you might need to batch your logs and send them to Datadog in fewer, larger requests. - Incorrect Log Group Name: It sounds simple, but a typo in the
log_group_namevariable is a frequent source of frustration. Always copy and paste it directly from the AWS console.
Conclusion
And that’s it. With a simple Python script and a cron job, you’ve built a reliable pipeline to move your important CloudWatch logs into Datadog for long-term retention and analysis. This not only saves you from potential AWS costs but also consolidates your observability stack. It’s a small investment of time that pays huge dividends when you’re troubleshooting an issue months down the line. Hope this helps you out.
🤖 Frequently Asked Questions
âť“ How can I sync CloudWatch logs to Datadog for long-term retention?
You can sync CloudWatch logs to Datadog by using a Python script that leverages `boto3` to call `filter_log_events` on CloudWatch and the `datadog` API to `Event.create` for each log, then automate its execution with a cron job.
âť“ How does syncing CloudWatch logs to Datadog compare to extending CloudWatch retention?
Extending CloudWatch retention can become ‘pricey fast.’ Syncing to Datadog provides ‘cost-effective long-term storage’ and ‘centralized visibility’ within an existing observability stack, potentially saving AWS costs.
âť“ What is a common implementation pitfall when syncing CloudWatch logs to Datadog?
A common pitfall is ‘IAM Permissions’ resulting in an `AccessDeniedException`. Ensure your IAM user or role has the `logs:FilterLogEvents` permission for the specific CloudWatch log group being targeted.
Leave a Reply