Para cumplir con el control requerido y reforzar la observabilidad de nuestro entorno, hemos habilitado el Environment Health streaming de Elastic Beanstalk hacia CloudWatch Logs. Esta funcionalidad se activa al habilitar el enhanced health reporting en el entorno y configurar el envío de la información de salud a CloudWatch. En este post veremos como podemos implementar la Monitorización de ElasticBeanstalk con CloudWatch logs.
0. Diagrama
Una imagen vale más que mil palabras. Esto será lo que vamos a montar.

1. Activar Environment Health streaming hacia CloudWatch Logs
Es importante remarcar que este flujo es independiente del streaming de logs de las instancias EC2. Al habilitarlo, Elastic Beanstalk crea automáticamente un log group en CloudWatch con la ruta /aws/elasticbeanstalk/<environment-name>/environment-health.log
, donde se almacenan registros cada vez que cambia el estado de salud del entorno (por ejemplo, pasando a Severe si el balanceador de carga falla). De esta forma no solo garantizamos la trazabilidad de los eventos críticos, sino que también alineamos la infraestructura con los requisitos de cumplimiento y seguridad establecidos.

Una vez activado el Health event streaming to CloudWatch logs, se empezará a enviar información siempre que haya un evento de health en nuestro entorno.
2. Revisando los logs
Y empezaremos a ver mensajes así:
{"id":"d5fc30ce-76b8-4bb6-82c3-803af0339be7","version":"1.0","type":"HealthTransition","color":"Red","timestamp":"2025-08-17T04:17:20Z","status":"Severe","causes":["100.0 % of the requests are erroring with HTTP 4xx."]}
{"id":"c9c6a3be-ff01-48e5-ae45-c43cdcdfd3e8","version":"1.0","type":"HealthTransition","color":"Green","timestamp":"2025-08-17T04:17:50Z","status":"Ok","causes":[]}
¿Qué podríamos sacar de aquí? Bueno, podríamos generar una métrica para monitorizar el heath status de nuestro entorno, y luego de ahí, crear una alarma. Por ejemplo si el estado pasa a “Red” durante más de 30 minutos, por ejemplo, que salte la alerta.
En CloudWatch podremos listar estos eventos con la “query” básica.
fields @timestamp, @message, @logStream, @log
| sort @timestamp desc
| limit 10000
O podemos empezar a jugar con el count y ver que ha sucedido en las últimas 24 horas.
fields @timestamp, @message, status, type
| filter type = "HealthTransition"
| stats count() by status
Ejemplo de lo que veríamos como resultado:

Vale, mi objetivo es pues crear una métrica que me sirva de alerta para saber el estado de mi entorno.
3. Crear la métrica
Para el asunto que estamos tratando hemos de tener en cuenta los diversos estados que el agente va a reportar. Aquí están listados.
- EBStatusOk
- EBStatusSevere
- EBStatusDegraded
- EBStatusInfo
- EbStatusNoData
Para empezar a monitorizar la salud de nuestro entorno con mayor granularidad, hemos creado una serie de métricas basadas en las transiciones de estado que reporta Elastic Beanstalk en sus logs de environment health. Cada métrica se activa únicamente cuando el entorno cambia de estado, evitando así falsos positivos por ausencia de eventos. La métrica EBStatusOk cuenta las transiciones a Ok, lo que nos permite identificar momentos en los que el entorno se recupera y vuelve a la normalidad. La métrica EBStatusSevere registra transiciones a Severe, un indicador de fallos críticos donde el balanceador de carga u otras partes clave del entorno dejan de responder. Por su parte, EBStatusDegraded mide transiciones a Degraded, reflejando una alta tasa de errores o problemas serios en varias instancias, pero sin llegar al nivel de criticidad máxima. Finalmente, EBStatusInfo contabiliza transiciones a Info, que aparecen normalmente durante despliegues o cuando se están ejecutando operaciones de mantenimiento en las instancias. Con este conjunto inicial de métricas podemos empezar a visualizar la estabilidad del entorno y entender mejor cómo evoluciona su estado en distintos escenarios.
Al revisar las métricas generadas durante el último mes, vemos que la mayoría de las transiciones corresponden a Ok (132 eventos), lo que refleja una recuperación frecuente del entorno tras operaciones o cambios. También se registraron 39 transiciones a Info, que suelen estar asociadas a despliegues y tareas de mantenimiento. Los estados más críticos fueron menos comunes: únicamente 4 transiciones a Severe, donde el entorno experimentó fallos graves, y 9 registros de No Data, que indican momentos puntuales en los que Elastic Beanstalk no recibió información suficiente para evaluar la salud. Esta distribución muestra un entorno generalmente estable, donde los episodios críticos son la excepción, pero que merece atención para entender qué originó los cambios a Severe o la falta de datos.
Bueno pues una vez explicado que queremos “ver” vamos a crearlo.
Las alarmas creadas desde la consola de Elastic Beanstalk son CloudWatch Alarms básicas ligadas al entorno y se eliminan con él. En cambio, las alarmas definidas en Terraform te dan control total (métricas personalizadas, treat_missing_data, metric math) y quedan gestionadas como infraestructura como código, independientes del ciclo de vida del entorno.
# Ajusta este valor al nombre real de tu log group de health:
# Suele ser: /aws/elasticbeanstalk/<environment-name>/environment-health.log
variable "eb_health_log_group" {
type = string
description = "CloudWatch Log Group para Environment Health de EB"
default = "/aws/elasticbeanstalk/MI-ENTORNO/environment-health.log"
}
# Métrica: cuenta 1 cada vez que el entorno transiciona a 'Ok'
resource "aws_cloudwatch_log_metric_filter" "eb_status_ok" {
name = "EBStatusOk"
log_group_name = var.eb_health_log_group
# Patrón JSON del evento HealthTransition con status=Ok
pattern = "{ $.type = \"HealthTransition\" && $.status = \"Ok\" }"
metric_transformation {
namespace = "Custom/EBHealth"
name = "EBStatusOk"
value = "1"
unit = "Count"
}
}
Veremos este objeto dentro de la consola de CloudWatch, en una pestaña del propio LogGroup.

Para ver si funciona, voy a forzar un evento en ElasticBeanstalk.

Después de forzar el evento, ya observo como el metric filter ha subido una métrica al namespace destinado.

Ep, y aquí está.


Vale, pues ahora solo falta añadir el resto de métricas y desplegarlas. Y cómo último paso, generaré un widget en el dashboard para mostrar todo esto.
4. Creación del resto de métricas
Para el resto seguiré el mismo esquema. No tiene mucho misterio.
resource "aws_cloudwatch_log_metric_filter" "eb_status_severe" {
name = "EBStatusSevere"
log_group_name = var.eb_health_log_group
pattern = "{ $.type = \"HealthTransition\" && $.status = \"Severe\" }"
metric_transformation {
namespace = "Custom/EBHealth"
name = "EBStatusSevere"
value = "1"
unit = "Count"
}
}
5. Creando la alerta
Ahora, lo que quiero es que siempre que mi entorno esté en un estado “Severe” reciba una alarma. Esto básicamente monitoriza la métrica y conectará con un topic SNS para enviar un email.
En un evento de falta de Spot posterior me di cuenta que el evento que necesitaba capturar era el de Degraded más color “Red”
resource "aws_cloudwatch_metric_alarm" "eb_severe_alarm" {
alarm_name = "eb-health-severe"
namespace = "Custom/EBHealth"
metric_name = "EBStatusSevere"
statistic = "Sum"
period = 60 # evalúa cada minuto
evaluation_periods = 5
datapoints_to_alarm = 1
threshold = 0 # cualquier aparición de 'Severe'
comparison_operator = "GreaterThanThreshold"
treat_missing_data = "notBreaching"
alarm_description = "Elastic Beanstalk environment entered Severe health state"
alarm_actions = [aws_sns_topic.alarms.arn] # usa tu topic existente
# ok_actions = [aws_sns_topic.alarms.arn] # (opcional) aviso al volver a OK
# insufficient_data_actions = [] # (opcional) ya es el valor por defecto
}
6. Resumen
En este post hemos visto como habilitar el Environment Health streaming de Elastic Beanstalk hacia CloudWatch Logs para mejorar la visibilidad y cumplir con los requisitos de compliance. A partir de estos registros, que solo se generan cuando el estado del entorno cambia (transiciones), diseñamos un conjunto de métricas personalizadas en CloudWatch que nos permiten cuantificar la frecuencia de cada estado.
Comenzamos con las métricas más relevantes: EBStatusOk (recuperaciones), EBStatusSevere (fallos críticos), EBStatusDegraded (degradación seria), EBStatusInfo (operaciones en curso) y EBStatusNoData (falta de señal del agente). Cada una de ellas se activa únicamente cuando el entorno entra en ese estado, evitando falsos positivos por ausencia de eventos.
Tras validar su funcionamiento en los logs —donde observamos que, por ejemplo, la terminación forzada de una instancia genera transiciones a No Data (Grey) y no a Severe— confirmamos que estas métricas reflejan fielmente la realidad operativa del entorno. Finalmente, configuramos una alarma crítica sobre EBStatusSevere, vinculada a un topic de SNS ya existente, para recibir notificaciones inmediatas por email únicamente en caso de incidentes graves.
Con este enfoque hemos pasado de depender solo de la consola de Elastic Beanstalk a contar con métricas reutilizables, dashboards y alertas centralizadas en CloudWatch, lo que refuerza tanto la observabilidad como el cumplimiento de los controles de seguridad exigidos.