Overview
CloudWatch Logs is a managed log aggregation service. It stores log events in Log Groups and Log Streams, applies retention policies, and most importantly โ converts log patterns into CloudWatch metrics via Metric Filters. This is the bridge between raw log data and actionable alerts.
Why It Matters
Logs contain signal that metrics don’t capture โ specific error messages, user IDs, request paths, stack traces. Metric Filters extract that signal into quantifiable metrics without requiring a separate log analytics platform. Combined with CloudWatch Alarms, they enable alerting on application-level behavior from raw log data.
Where It Fits
DOP-C02 Domain 4 โ Monitoring and Logging
Application log line (“503 GET /api/health”) | v CloudWatch Log Stream (instance-id) | v CloudWatch Log Group (/platform/haproxy) | v Metric Filter (pattern: “503” โ HAProxy5xxErrors +1) | v CloudWatch Metric (DopLab/HAProxy5xxErrors) | v CloudWatch Alarm โ SNS โ email
The Big Picture
Your platform today AWS Equivalent
/var/log/haproxy.log โ CloudWatch Log Stream HAProxy server logs โ Log Group (/platform/haproxy) grep “503” logs | wc -l โ Metric Filter โ custom metric Prometheus alert rule โ CloudWatch Alarm on that metric
Core Concepts
Log Group โ the container for related log streams. Has a retention policy. One per application/service.
Log Stream โ one per source: one per EC2 instance, one per Lambda invocation, one per container. Named by instance ID for EC2.
Log Events โ individual log lines with millisecond timestamps.
Retention policies โ how long logs are kept:
1 day, 3 days, 7 days, 14 days, 30 days, 60 days, 90 days, 120 days, 150 days, 180 days, 1 year, 2 years, 5 years, 10 years, Never expire
Default is Never Expire โ always set a retention policy to control cost.
Metric Filters โ the exam-critical feature: Converts log patterns to CloudWatch metrics:
Pattern โ Metric increment “503” โ +1 to HAProxy5xxErrors “ERROR” โ +1 to ApplicationErrors “FATAL” โ +1 to FatalErrors
Filter pattern syntax:
“ERROR” โ contains the word ERROR “ERROR” - “TIMEOUT” โ contains ERROR but not TIMEOUT “[ip, id, status=5*]” โ structured: status starts with 5 { $.level = “ERROR” } โ JSON logs: field matching { $.httpStatusCode = 5* } โ JSON: status code starts with 5
defaultValue on metric transformation:
0โ periods with no matches report 0 (correct for error counters โ no errors = report 0, not silence)- omitted โ periods with no matches report no datapoint (silence)
Use defaultValue: 0 for error rate metrics so treat-missing-data: notBreaching works correctly.
Real-World Example
Live lab in devopslab, account 046685909731:
- Created log group
/dop-lab/haproxywith 7-day retention - Created log stream
test-instance-001 - Pushed 16 fake HAProxy 503 log events across three batches using
put-log-events - Created metric filter
haproxy-503-errorsโ pattern"503", namespaceDopLab, metricHAProxy5xxErrors, defaultValue0 - Queried metric after ~3 minutes โ confirmed
Sum: 15.0inGetMetricStatistics - Deleted log group after lab
Key observation: Metric Filter propagation takes 2-3 minutes after log events are ingested. Query with a wide enough time window and period.
Lab runbook:
# Create log group with retention
aws logs create-log-group --log-group-name /dop-lab/haproxy
aws logs put-retention-policy --log-group-name /dop-lab/haproxy --retention-in-days 7
# Create log stream
aws logs create-log-stream \
--log-group-name /dop-lab/haproxy \
--log-stream-name test-instance-001
# Push log event
aws logs put-log-events \
--log-group-name /dop-lab/haproxy \
--log-stream-name test-instance-001\
--log-events "[{\"timestamp\": $(date +%s%3N), \"message\": \"haproxy 503 GET /api/health\"}]"
# Create metric filter
aws logs put-metric-filter \
--log-group-name /dop-lab/haproxy \
--filter-name haproxy-503-errors \
--filter-pattern "503" \
--metric-transformations \
metricName=HAProxy5xxErrors,metricNamespace=DopLab,metricValue=1,defaultValue=0
# Query metric (wait 2-3 min)
aws cloudwatch get-metric-statistics \
--namespace DopLab \
--metric-name HAProxy5xxErrors \
--start-time $(date -u -d '15 minutes ago' +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
--period 900 \
--statistics Sum \
--output table
# Cleanup
aws logs delete-log-group --log-group-name /dop-lab/haproxy
Engineering Analogy
Metric Filters are the equivalent of grep "503" /var/log/haproxy.log | wc -l run continuously against a streaming log, publishing the count as a metric every minute. The difference: it’s serverless, always-on, and feeds directly into CloudWatch Alarms without any cron job or script.
Best Practices
- Always set retention policy on log groups โ default is Never Expire which accumulates cost
- Use
defaultValue: 0on metric filters for error counters โ ensures silence means zero errors, not unknown - Name log groups by service path:
/platform/haproxy,/platform/nginx,/app/api - Name log streams by instance ID โ CloudWatch Agent does this automatically
- Query with a period at least as wide as your filter propagation window (2-3 min minimum)
Common Mistakes
- No retention policy โ logs accumulate indefinitely, cost grows silently
- Missing
defaultValueon metric filter โ zero-error periods produce no datapoint, confusing alarm behavior - Filter pattern too broad (
"5"matches everything containing 5, not just 503s) โ use structured patterns for precision - Querying metric too soon after log ingestion โ allow 2-3 minutes for propagation
Pro Tip
aws logs filter-log-events --log-group-name <group> --filter-pattern "503"lets you search log events directly via CLI without a metric filter โ useful for ad-hoc incident investigation. It’s the CLI equivalent of CloudWatch Logs Insights for simple pattern searches.
Key Takeaways
- Log Group โ Log Streams โ Log Events is the hierarchy
- Always set retention policies โ never leave log groups at Never Expire
- Metric Filters convert log patterns into CloudWatch metrics โ no separate analytics platform needed
defaultValue: 0ensures error-free periods report 0, not silence- Filter propagation takes 2-3 minutes โ account for this when testing
Related Articles
- DevOpsPro-4.1-CloudWatch-Metrics-Alarms-and-SNS.md
- DevOpsPro-4.3-CloudWatch-Agent-System-Metrics-and-Log-Shipping.md
- DevOpsPro-4.5-CloudTrail-API-Audit-and-Event-History.md
References
- AWS Documentation: Amazon CloudWatch Logs
- Live lab performed in devopslab-vpc, account 046685909731, 2026-08-10