DEV Community

Yash
Yash

Posted on

CloudWatch auto-monitoring on deploy: the Terraform pattern

CloudWatch auto-monitoring on deploy: the Terraform pattern

Most teams add monitoring after their first incident. Here's how to wire it in automatically.

Monitoring module

variable "service_name" {}; variable "environment" {}
variable "alert_email" {}; variable "alb_arn_suffix" {}

resource "aws_cloudwatch_log_group" "service" {
  name              = "/ecs/${var.environment}/${var.service_name}"
  retention_in_days = var.environment == "prod" ? 90 : 14
}
resource "aws_sns_topic" "alerts" { name = "${var.service_name}-${var.environment}-alerts" }
resource "aws_sns_topic_subscription" "email" {
  topic_arn = aws_sns_topic.alerts.arn; protocol = "email"; endpoint = var.alert_email
}
resource "aws_cloudwatch_metric_alarm" "error_rate" {
  alarm_name          = "${var.service_name}-5xx-rate"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2; threshold = 5; alarm_actions = [aws_sns_topic.alerts.arn]
  metric_query { id = "rate"; expression = "errors/requests*100"; return_data = true }
  metric_query { id = "errors"; metric {
    metric_name = "HTTPCode_Target_5XX_Count"; namespace = "AWS/ApplicationELB"
    period = 60; stat = "Sum"; dimensions = { LoadBalancer = var.alb_arn_suffix }
  }}
  metric_query { id = "requests"; metric {
    metric_name = "RequestCount"; namespace = "AWS/ApplicationELB"
    period = 60; stat = "Sum"; dimensions = { LoadBalancer = var.alb_arn_suffix }
  }}
}
resource "aws_cloudwatch_dashboard" "service" {
  dashboard_name = "${var.service_name}-${var.environment}"
  dashboard_body = jsonencode({ widgets = [
    { type = "metric", properties = {
      title = "Request Count"
      metrics = [["AWS/ApplicationELB","RequestCount","LoadBalancer",var.alb_arn_suffix]]
      period = 60; stat = "Sum"
    }},
    { type = "metric", properties = {
      title = "5XX Errors"
      metrics = [["AWS/ApplicationELB","HTTPCode_Target_5XX_Count","LoadBalancer",var.alb_arn_suffix]]
      period = 60; stat = "Sum"
    }}
  ]})
}
Enter fullscreen mode Exit fullscreen mode

One-line usage per project

module "monitoring" {
  source = "../../modules/service-monitoring"
  service_name = "payment-api"; environment = "prod"
  alert_email = "oncall@mycompany.com"; alb_arn_suffix = module.alb.arn_suffix
}
Enter fullscreen mode Exit fullscreen mode

Key insight: Terraform's idempotency means the dashboard and alarms exist after every apply. Monitoring is guaranteed by the deploy process itself.

Step2Dev applies this pattern automatically on every project you connect.

👉 step2dev.com

What monitoring do you consider non-negotiable for a new service?

Top comments (0)