Claude Code × AWS CloudWatch Guía Completa | Análisis de Logs, Alarmas y Dashboards Automáticos
Optimiza AWS CloudWatch con Claude Code. Código práctico para análisis de patrones de logs, configuración automática de alarmas, dashboards de métricas e investigación de incidentes.
“¡Hay un error en producción! Pero hay demasiados logs y no sé por dónde empezar.” — Es el pánico clásico durante la gestión de incidentes.
CloudWatch es el servicio de monitoreo estándar de AWS, pero con volúmenes enormes de logs, la información crítica queda enterrada y la configuración de alarmas suele posponerse. En mi trabajo monitoreo un sistema con ECS + Lambda, y dejar que Claude Code lea los logs para identificar la causa ha reducido el tiempo promedio de respuesta a incidentes en un 40%.
Este artículo explica paso a paso cómo automatizar el análisis de logs de CloudWatch, el diseño de alarmas y la construcción de dashboards con Claude Code.
Componentes principales de CloudWatch
CloudWatch Logs : Almacenamiento y búsqueda de logs de apps y servicios AWS
CloudWatch Metrics : Datos numéricos como uso de CPU y conteo de solicitudes
CloudWatch Alarms : Detecta umbrales superados en métricas y notifica a SNS, etc.
CloudWatch Dashboards: Vistas personalizadas para visualizar métricas y logs
Log Insights : Motor de consultas similar a SQL para analizar logs
Paso 1: Delegar el análisis de patrones de logs a Claude Code
Durante un incidente, lo primero es entender el patrón de los logs de error.
# Obtener logs de error de la última hora
aws logs filter-log-events \
--log-group-name "/ecs/myapp" \
--start-time $(date -d "1 hour ago" +%s000) \
--filter-pattern "ERROR" \
--output json > error-logs.json
claude -p "
Analiza los siguientes logs de error de CloudWatch y:
1. Clasifica los errores por tipo (5xx, 4xx, errores de conexión a BD, timeouts, etc.)
2. Identifica el error más frecuente
3. Determina el momento en que los errores se dispararon
4. Propón hipótesis sobre la causa raíz
5. Sugiere los próximos pasos de investigación
$(cat error-logs.json | head -500)
"
Generar automáticamente consultas de Log Insights
claude -p "
Genera consultas de CloudWatch Log Insights para los siguientes propósitos:
1. Tasa de error por endpoint en la última hora (top 10)
2. Detalles de solicitudes con latencia superior a 500 ms
3. Todos los logs de operaciones de un usuario específico (user_id: 12345)
4. Primeros errores ocurridos dentro de los 30 minutos tras un despliegue
Formato de log: JSON (timestamp, level, message, user_id, endpoint, duration_ms, status_code)
"
Ejemplo de consultas de Log Insights generadas:
-- Tasa de error por endpoint
fields @timestamp, endpoint, status_code
| filter status_code >= 400
| stats count() as error_count by endpoint
| sort error_count desc
| limit 10
-- Solicitudes con latencia superior a 500 ms
fields @timestamp, endpoint, duration_ms, user_id
| filter duration_ms > 500
| sort duration_ms desc
| limit 50
-- Logs de operaciones de un usuario específico
fields @timestamp, level, message, endpoint
| filter user_id = "12345"
| sort @timestamp desc
| limit 100
Paso 2: Generar automáticamente la configuración de alarmas
claude -p "
Diseña todas las alarmas de CloudWatch necesarias para el siguiente sistema.
Implementa en CDK TypeScript.
[Arquitectura del sistema]
- ECS Fargate (servidor API, 2–10 instancias)
- RDS PostgreSQL
- ALB (Application Load Balancer)
- Lambda (procesamiento por lotes)
[Requisitos de alarmas]
- Producción: alarmas que se activen en menos de 5 minutos
- Destinos de notificación: SNS → Slack y PagerDuty
- Alarmas de dos niveles (Warning / Critical)
- Fuera del horario laboral: solo Critical
"
// lib/monitoring-stack.ts
import * as cdk from "aws-cdk-lib";
import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
import * as actions from "aws-cdk-lib/aws-cloudwatch-actions";
import * as sns from "aws-cdk-lib/aws-sns";
export class MonitoringStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const alertTopic = sns.Topic.fromTopicArn(
this, "AlertTopic",
`arn:aws:sns:${this.region}:${this.account}:prod-alerts`
);
const warnTopic = sns.Topic.fromTopicArn(
this, "WarnTopic",
`arn:aws:sns:${this.region}:${this.account}:prod-warnings`
);
// Alarma de tasa de error 5xx de ALB
const alb5xxAlarm = new cloudwatch.Alarm(this, "Alb5xxAlarm", {
alarmName: "prod-alb-5xx-critical",
alarmDescription: "Tasa de error 5xx de ALB superó el 5%",
metric: new cloudwatch.Metric({
namespace: "AWS/ApplicationELB",
metricName: "HTTPCode_Target_5XX_Count",
dimensionsMap: { LoadBalancer: "app/myapp/xxx" },
statistic: "Sum",
period: cdk.Duration.minutes(5),
}),
threshold: 10,
evaluationPeriods: 2,
comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
});
alb5xxAlarm.addAlarmAction(new actions.SnsAction(alertTopic));
// Alarma de uso de CPU de ECS (Warning/Critical)
const ecsCpuWarning = new cloudwatch.Alarm(this, "EcsCpuWarning", {
alarmName: "prod-ecs-cpu-warning",
metric: new cloudwatch.Metric({
namespace: "AWS/ECS",
metricName: "CPUUtilization",
dimensionsMap: { ClusterName: "myapp-cluster", ServiceName: "myapp-service" },
statistic: "Average",
period: cdk.Duration.minutes(5),
}),
threshold: 70,
evaluationPeriods: 3,
});
ecsCpuWarning.addAlarmAction(new actions.SnsAction(warnTopic));
const ecsCpuCritical = new cloudwatch.Alarm(this, "EcsCpuCritical", {
alarmName: "prod-ecs-cpu-critical",
metric: new cloudwatch.Metric({
namespace: "AWS/ECS",
metricName: "CPUUtilization",
dimensionsMap: { ClusterName: "myapp-cluster", ServiceName: "myapp-service" },
statistic: "Average",
period: cdk.Duration.minutes(5),
}),
threshold: 90,
evaluationPeriods: 2,
});
ecsCpuCritical.addAlarmAction(new actions.SnsAction(alertTopic));
// Alarma de número de conexiones de RDS
const rdsConnectionAlarm = new cloudwatch.Alarm(this, "RdsConnectionAlarm", {
alarmName: "prod-rds-connections-critical",
metric: new cloudwatch.Metric({
namespace: "AWS/RDS",
metricName: "DatabaseConnections",
dimensionsMap: { DBInstanceIdentifier: "myapp-db" },
statistic: "Maximum",
period: cdk.Duration.minutes(5),
}),
threshold: 80, // 80% del máximo de conexiones de db.t3.micro
evaluationPeriods: 2,
});
rdsConnectionAlarm.addAlarmAction(new actions.SnsAction(alertTopic));
// Alarma de errores de Lambda
const lambdaErrorAlarm = new cloudwatch.Alarm(this, "LambdaErrorAlarm", {
alarmName: "prod-lambda-errors-critical",
metric: new cloudwatch.Metric({
namespace: "AWS/Lambda",
metricName: "Errors",
dimensionsMap: { FunctionName: "myapp-batch" },
statistic: "Sum",
period: cdk.Duration.minutes(15),
}),
threshold: 5,
evaluationPeriods: 1,
});
lambdaErrorAlarm.addAlarmAction(new actions.SnsAction(alertTopic));
}
}
Paso 3: Generar automáticamente un dashboard personalizado
claude -p "
Genera un dashboard de CloudWatch en CDK que muestre la siguiente información.
[Diseño del dashboard]
Fila 1: Estado general del sistema (solicitudes ALB, tasa 5xx, latencia P50/P95/P99)
Fila 2: Servicio ECS (CPU, memoria, número de tareas en ejecución)
Fila 3: RDS (conexiones, latencia, uso de CPU)
Fila 4: Lambda (invocaciones, errores, duración)
Fila 5: Métricas de negocio (nuevos registros, tasa de éxito de pagos) ← métricas personalizadas
"
// Definición del dashboard (fragmento)
const dashboard = new cloudwatch.Dashboard(this, "AppDashboard", {
dashboardName: "myapp-production",
});
dashboard.addWidgets(
new cloudwatch.Row(
new cloudwatch.GraphWidget({
title: "Solicitudes ALB",
left: [new cloudwatch.Metric({
namespace: "AWS/ApplicationELB",
metricName: "RequestCount",
statistic: "Sum",
period: cdk.Duration.minutes(1),
})],
width: 8,
}),
new cloudwatch.GraphWidget({
title: "Tasa de error 5xx de ALB (%)",
left: [new cloudwatch.MathExpression({
expression: "5xx / (2xx + 3xx + 4xx + 5xx) * 100",
usingMetrics: {
"5xx": new cloudwatch.Metric({ metricName: "HTTPCode_Target_5XX_Count", namespace: "AWS/ApplicationELB", statistic: "Sum" }),
"2xx": new cloudwatch.Metric({ metricName: "HTTPCode_Target_2XX_Count", namespace: "AWS/ApplicationELB", statistic: "Sum" }),
"3xx": new cloudwatch.Metric({ metricName: "HTTPCode_Target_3XX_Count", namespace: "AWS/ApplicationELB", statistic: "Sum" }),
"4xx": new cloudwatch.Metric({ metricName: "HTTPCode_Target_4XX_Count", namespace: "AWS/ApplicationELB", statistic: "Sum" }),
},
period: cdk.Duration.minutes(1),
})],
width: 8,
}),
)
);
Paso 4: Delegar la investigación de incidentes a Claude Code
claude -p "
Quiero investigar un incidente en producción. Ejecuta los siguientes comandos y analiza los resultados:
1. aws logs filter-log-events --log-group-name '/ecs/myapp' \
--start-time \$(date -d '2 hours ago' +%s000) \
--filter-pattern 'ERROR' --limit 100
2. aws cloudwatch get-metric-statistics \
--namespace AWS/ApplicationELB \
--metric-name HTTPCode_Target_5XX_Count \
--start-time \$(date -d '2 hours ago' -u +%Y-%m-%dT%H:%M:%SZ) \
--end-time \$(date -u +%Y-%m-%dT%H:%M:%SZ) \
--period 300 --statistics Sum
Basándote en los resultados, resume:
- Hora de inicio del incidente
- Número estimado de usuarios afectados
- Top 3 hipótesis sobre la causa raíz
- Acciones de respuesta inmediata
"
Paso 5: Diseñar automáticamente métricas personalizadas
claude -p "
Genera código Node.js (AWS SDK v3) para medir los siguientes KPIs de negocio
de un e-commerce como métricas personalizadas de CloudWatch.
Métricas a medir:
- Número de pagos exitosos y fallidos (cada minuto)
- Tasa de abandono de carrito (cada 5 minutos)
- Nuevos registros de miembros (cada hora)
Espacio de nombres: MyApp/Business
Etiquetar cada métrica con el entorno (Production/Staging)
"
// src/monitoring/business-metrics.ts
import { CloudWatchClient, PutMetricDataCommand } from "@aws-sdk/client-cloudwatch";
const cw = new CloudWatchClient({ region: process.env.AWS_REGION });
const NAMESPACE = "MyApp/Business";
const ENV = process.env.NODE_ENV ?? "development";
export async function recordPaymentSuccess() {
await cw.send(new PutMetricDataCommand({
Namespace: NAMESPACE,
MetricData: [{
MetricName: "PaymentSuccess",
Value: 1,
Unit: "Count",
Dimensions: [{ Name: "Environment", Value: ENV }],
}],
}));
}
export async function recordPaymentFailure(reason: string) {
await cw.send(new PutMetricDataCommand({
Namespace: NAMESPACE,
MetricData: [{
MetricName: "PaymentFailure",
Value: 1,
Unit: "Count",
Dimensions: [
{ Name: "Environment", Value: ENV },
{ Name: "Reason", Value: reason },
],
}],
}));
}
4 errores comunes a evitar
1. evaluationPeriods demasiado corto
// ❌ La alarma se activa con picos momentáneos
evaluationPeriods: 1,
threshold: 10,
// ✅ La alarma solo se activa tras 3 períodos consecutivos (reduce falsos positivos)
evaluationPeriods: 3,
threshold: 10,
datapointsToAlarm: 2, // Alarma cuando el umbral se supera en 2 de 3 períodos
2. Ignorar los costos de Log Insights
Log Insights cobra según la cantidad de datos escaneados. Ejecutar consultas sin limitar el rango de tiempo puede generar facturas inesperadas. Especifica siempre --start-time y --end-time.
3. Las métricas personalizadas de alta resolución son costosas
Las métricas estándar (60 segundos) son gratuitas, pero las de alta resolución (1 segundo) cuestan aproximadamente 10 veces más. La agregación de 1 minuto suele ser suficiente para métricas de negocio.
4. No configurar el período de retención de logs de Lambda
El valor predeterminado es “Sin expiración”, lo que hace que los costos de almacenamiento crezcan indefinidamente. Siempre configura un período de retención en los grupos de logs.
new logs.LogGroup(this, "AppLogGroup", {
logGroupName: "/ecs/myapp",
retention: logs.RetentionDays.ONE_MONTH, // Eliminación automática tras 30 días
});
Resumen
| Tarea | Contribución de Claude Code |
|---|---|
| Análisis de logs | Lee logs de error y propone hipótesis de causa raíz con pasos de solución |
| Consultas Log Insights | Genera consultas a partir de una descripción del objetivo de análisis |
| Configuración de alarmas | Genera código CDK en bloque a partir de una descripción del sistema |
| Dashboard | Genera definiciones de widgets a partir de una descripción de lo que quieres ver |
| Investigación de incidentes | Ejecuta comandos AWS CLI y analiza los resultados |
“Configuraremos el monitoreo más tarde” — y entonces llega un incidente y no tienes visibilidad. Con Claude Code puedes tener alarmas y dashboards de nivel producción listos en 30 minutos.
Artículos relacionados
- Claude Code × AWS ECS/Fargate Guía Completa
- Claude Code × AWS CodePipeline/CodeBuild Guía Completa
- Claude Code × AWS IAM Guía Completa
Referencias
Lleva tu flujo con Claude Code al siguiente nivel
50 plantillas de prompts probadas en producción, listas para copiar y pegar en Claude Code.
PDF gratuito: Hoja de trucos de Claude Code en 5 minutos
Solo deja tu correo y te enviaremos al instante la hoja de trucos en una página A4.
Cuidamos tus datos personales y nunca enviamos spam.
Sobre el autor
Masa
Ingeniero apasionado por Claude Code. Dirige claudecode-lab.com, un medio tecnológico en 10 idiomas con más de 2.000 páginas.
Artículos relacionados
Claude Code × Amazon Bedrock Guía Completa | Ejecutar Claude en Producción con AWS
Guía completa para usar Amazon Bedrock con Claude Code. Desde autenticación IAM, streaming, integración con Lambda, implementación RAG hasta optimización de costos, basada en la experiencia real de producción de Masa.
Claude Code × AWS CodePipeline/CodeBuild Guía Completa | Construcción automática de pipelines CI/CD
Construye automáticamente CI/CD con AWS CodePipeline y CodeBuild usando Claude Code. Ejemplos reales de diseño de pipelines, generación de buildspec.yml, automatización de pruebas e infraestructura CDK.
Claude Code × AWS ECS/Fargate Guía Completa | Automatiza los Despliegues de Contenedores
Automatiza despliegues en AWS ECS/Fargate con Claude Code. Desde definiciones de tareas y configuración de servicios hasta despliegues Blue/Green e infraestructura CDK — basado en la experiencia real de Masa.