Centralize Logs in CloudWatch
Centralize logs in CloudWatch from apps — Cloud security essentials.
Focus: centralize logs in cloudwatch from apps
You've built an amazing application and deployed it to AWS, the 'us-east-1' region. But when a security incident happens, you find yourself SSH-ing into each EC2 instance, digging through /var/log/application.log files by hand. Your logs are scattered across dozens of instances, some of which auto-scale and disappear, and you have no centralized view. This is the exact pain this lesson solves: centralizing logs in CloudWatch from your apps so that every log entry flows into one searchable, monitorable, and alertable place. Let's fix this today.
The problem this lesson solves
When your application runs on multiple EC2 instances, containers, or Lambda functions, each one writes its own local log files. Troubleshooting becomes a nightmare: you have to guess which instance saw the error, patch together log fragments, and you often miss the 'smoking gun' because the instance was terminated during a scale-in event.
Beyond the operational chaos, this lack of centralization is a security risk. Security teams need a single source of truth to spot brute-force attempts, API misuse, or data exfiltration patterns across your entire fleet. Manual log collection is slow, error-prone, and almost never real-time.
The solution is to stream all application logs to a central log management service—Amazon CloudWatch Logs. This gives you:
- Single pane of glass: Search across all instances, containers, and functions.
- Real-time monitoring: Set up alarms and dashboards on log patterns.
- Security and compliance: Preserve immutable logs for audits and forensics.
Core concept / mental model
Think of your application logs as water from many streams. Each app is a stream, and CloudWatch Logs is the reservoir. Instead of going to each stream to taste the water, you install pumps (agents) that continuously push water into the reservoir. Then you can sample, filter, and test the water all in one place.
In AWS terms, the key components are:
- Log group: The reservoir—a container for logs from a single application or service. E.g.,
/ec2/my-app,/aws/lambda/orders-function. - Log stream: A stream within the group—usually one per EC2 instance, container, or Lambda invocation. E.g.,
i-0ab3c4d5e6,2024/05/01/[$LATEST]c9e6. - Log event: A single log entry—a timestamp and a message.
- CloudWatch agent: The pump—a small daemon on your EC2 instance that reads local log files and sends them to CloudWatch Logs.
This architecture scales: one agent per instance, hundreds of streams per group, and you query across them all in seconds.
How it works step by step
Here's the high-level flow of centralizing logs in CloudWatch from apps:
- Prepare your application to write logs to a known location (e.g.,
/var/log/my-app/application.log) in a structured format (JSON or key-value). - Install the CloudWatch agent on each EC2 instance or container host. For Lambda, you don't need an agent—the runtime automatically sends logs to CloudWatch.
- Configure the agent with a JSON config that specifies which log files to watch, the log group, stream name format, and timestamp format.
- Start the agent and verify it's sending logs.
- Query and monitor your logs in the CloudWatch console, set up metric filters, and create alarms.
For containerized apps, you can use the Fluentd/Fluent Bit plugins instead of the agent. For on-premises servers, the same agent works with a customer account.
Hands-on walkthrough
Let's get our hands dirty. We'll centralize logs from a simple Python web app on an EC2 instance to CloudWatch Logs.
1. Install the CloudWatch agent
First, connect to your EC2 instance (Amazon Linux 2) and install the agent:
sudo yum install -y amazon-cloudwatch-agent
2. Create a CloudWatch agent configuration
The agent config is a JSON file. Here's an example that collects logs from /var/log/my-app/application.log:
{
"agent": {
"metrics_collection_interval": 60
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/my-app/application.log",
"log_group_name": "/ec2/my-app",
"log_stream_name": "{instance_id}",
"timestamp_format": "%Y-%m-%dT%H:%M:%S%z",
"timezone": "UTC"
}
]
}
}
}
}
Save this as /opt/aws/amazon-cloudwatch-agent/bin/config.json on the instance.
3. Start the agent
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
-a fetch-config \
-m ec2 \
-c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json \
-s
This fetches and starts the agent. Now let's generate some logs with a quick Python script and verify they arrive in CloudWatch.
4. Generate and verify logs
Create a simple Python app that writes a log with a unique message:
import logging
import time
logging.basicConfig(
filename="/var/log/my-app/application.log",
level=logging.INFO,
format="%(asctime)s %(message)s",
datefmt="%Y-%m-%dT%H:%M:%S%z"
)
for i in range(5):
logging.info(f"Order processed: order_{i}")
time.sleep(1)
Run it: python3 app.py. Then in the AWS console, go to CloudWatch > Log groups > /ec2/my-app and see your log streams. You should see the logs like:
2024-05-01T15:30:01+0000 Order processed: order_0
2024-05-01T15:30:02+0000 Order processed: order_1
...
Compare options / when to choose what
There are several ways to centralize logs in CloudWatch, and your choice depends on your environment:
| Approach | Best for | Pros | Cons |
|---|---|---|---|
| CloudWatch agent | EC2 instances, on-premises servers | Native integration, collects metrics too | Required per-server install, config overhead |
| Lambda integration | Serverless apps | Zero setup, automatic log collection | Limited to Lambda functions |
| Fluent Bit/Fluentd | Containerized apps (EKS/ECS) | Standard in Kubernetes, rich filtering | Extra service to manage |
| CloudWatch Logs API (SDK) | Custom apps with no file system | Full control | Only for small scale, manual push |
When to choose: For classic EC2 fleets, the agent is the go-to. For serverless, Lambda logging is automatic. For Kubernetes, use Fluent Bit. For quick prototyping, you can use the API directly.
Troubleshooting & edge cases
- No logs appear: Check the agent status with
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status. Also verify the log file path exists and has read permissions for thecwagentuser. - Incorrect timestamps: If logs show wrong times, set the
timestamp_formatto match your log format. You can use%Y-%m-%d %H:%M:%Sor JSON logs with atimestampkey. - Logs truncated: The agent has a max log size per event (256 KB). If your messages are larger, consider splitting them or using the API.
- IAM permissions: The instance profile must have
logs:PutLogEvents,logs:CreateLogStream, andlogs:CreateLogGroup. Missing permissions cause silent failures. - Multi-line logs: By default, the agent treats each line as a separate event. For stack traces, set
multi_line_start_patternto match the first line of your stack trace.
What you learned & what's next
You've learned the core concepts of centralizing logs in CloudWatch from apps: the problem of scattered logs, the mental model of log groups and streams, the step-by-step setup with the CloudWatch agent, and how to troubleshoot common issues. You now know how to stream logs from EC2 instances, and you understand alternative approaches for Lambda and containers.
Next step: In the next lesson, you'll build on this by setting up alarms and notifications on your centralized logs—so you're not just collecting logs, but actively responding to security events. That's where log-based monitoring turns into proactive defense.
Practice recap
Try it yourself: create an EC2 instance with a simple Python app that logs to a file. Install the CloudWatch agent, configure it to stream that file to a new log group, and verify the logs appear. Then use CloudWatch Logs Insights to query for a specific log message. This hands-on practice will solidify the steps you've learned and prepare you for the next lesson on log-based alerts.
Common mistakes
- Forgetting to attach the correct IAM role to the EC2 instance — the agent needs
logs:PutLogEventsand related permissions, otherwise it fails silently. - Setting the wrong timestamp format in the agent config — logs appear with current time instead of the actual event time, breaking log correlation.
- Not using structured logging (JSON) — makes it hard to query with CloudWatch Logs Insights, slowing down security investigations.
- Choosing the Logs API for high-throughput production apps — it's rate-limited and inefficient compared to the agent or Fluent Bit.
Variations
- For Kubernetes, use Fluent Bit with the CloudWatch output plugin instead of the CloudWatch agent.
- Use CloudWatch Logs Insights for free-text search and SQL-like queries across all log groups to spot anomalies.
- For serverless, rely on the built-in Lambda log integration — no agent needed, logs are automatically sent to CloudWatch.
Real-world use cases
- A security operations team monitors login attempts across 500 EC2 instances by centralizing
/var/log/auth.loginto a single log group, then alerts on brute-force patterns. - A fintech startup aggregates transaction logs from a microservices fleet on EKS using Fluent Bit to meet PCI DSS audit requirements with a 6-month log retention policy.
- An e-commerce platform correlates API error logs from Lambda functions and EC2 instances in one CloudWatch Logs Insights dashboard to debug a multi-service outage.
Key takeaways
- Centralizing logs in CloudWatch gives you a single searchable source of truth for all your app logs, which is crucial for security discovery and incident response.
- The CloudWatch agent is the primary tool for EC2 and on-premises servers—it reads local files and streams them to a log group.
- Log groups hold streams; each stream typically maps to an instance or container, helping you isolate and trace issues.
- IAM permissions are essential—without them, log shipping silently fails.
- Choose your approach based on the environment: agent for EC2, Lambda integration for serverless, and Fluent Bit for Kubernetes.
- Use CloudWatch Logs Insights to run advanced queries across centralized logs for security analysis.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.