CloudWatch Logs Insights Queries
Prerequisites
- AWS account with appropriate permissions
- Terraform >= 1.0
- Log group with log data
Step 1: Create the Log Group
module "app_logs" {
source = "registry.patterneddesigns.ca/essentials/cloudwatch-logs/aws"
version = "1.3.0"
log_group_name = "/app/demo"
retention_in_days = 30
}
Step 2: Create Saved Queries
resource "aws_cloudwatch_query_definition" "recent_errors" {
name = "Recent Errors"
log_group_names = [module.app_logs.log_group_name]
query_string = <<-EOT
fields @timestamp, @message, @logStream
| filter @message like /ERROR/
| sort @timestamp desc
| limit 100
EOT
}
resource "aws_cloudwatch_query_definition" "request_latency" {
name = "Request Latency Stats"
log_group_names = [module.app_logs.log_group_name]
query_string = <<-EOT
fields @timestamp, @message
| parse @message /latency=(?<latency>\d+)ms/
| stats avg(latency) as avg_latency,
max(latency) as max_latency,
min(latency) as min_latency,
pct(latency, 95) as p95_latency
by bin(5m)
EOT
}
resource "aws_cloudwatch_query_definition" "error_breakdown" {
name = "Error Type Breakdown"
log_group_names = [module.app_logs.log_group_name]
query_string = <<-EOT
fields @timestamp, @message
| filter @message like /ERROR/
| parse @message /ERROR: (?<error_type>\w+)/
| stats count(*) as count by error_type
| sort count desc
EOT
}
Step 3: Query Via AWS CLI
Run queries from the command line:
# Start a query
aws logs start-query \
--log-group-name "/app/demo" \
--start-time $(date -d '1 hour ago' +%s) \
--end-time $(date +%s) \
--query-string 'fields @timestamp, @message | filter @message like /ERROR/ | limit 20'
# Get query results (use query-id from previous command)
aws logs get-query-results --query-id "your-query-id"
Step 4: Create Dashboard Widget
resource "aws_cloudwatch_dashboard" "main" {
dashboard_name = "application-logs"
dashboard_body = jsonencode({
widgets = [
{
type = "log"
x = 0
y = 0
width = 24
height = 6
properties = {
query = "SOURCE '${module.app_logs.log_group_name}' | fields @timestamp, @message | filter @message like /ERROR/ | sort @timestamp desc | limit 50"
region = data.aws_region.current.name
title = "Recent Errors"
}
}
]
})
}