Con el objetivo de que se active una alerta de CloudWatch cuando un mensaje de una cola de SQS a una función lambda supere el número máximo de reintentos.
Supuse que sería fácil y que la métrica NumberOfMessagesReceived lo reflejaría. Aquellos familiarizados con esto sabrán que este no es el caso.
Mi solución rápida y fácil para este problema fue introducir un "Limbo" que actúa como el primer DLQ y en cuestión de segundos envía el mensaje al DLQ final/real. En las métricas, esto da como resultado un pico en la métrica de mensajes visibles de la cola "Limbo". Entonces, tener un umbral de alerta de " > 0 " significa que cada vez que esa cola recibe un mensaje, se puede emitir una alerta.
Sin embargo, los poderes por encima de mí no están contentos con tener una cola "Limbo" para cada vez que queremos esta funcionalidad.
Por lo que he podido averiguar, existen algunos métodos alternativos, pero estos parecen peores que la Solución Limbo .
El primero es tener una nueva función lambda que use un SQS DLQ como fuente y genere la alerta.
En segundo lugar, tener la lógica have dentro de las lambdas existentes (que procesan los mensajes de SQS) leer la cantidad de veces que se ha vuelto a intentar un mensaje y, en el momento final, generar la alerta. Este tipo de elimina la ventaja de usar una cola y una política de re-conducción en primer lugar, y es una solución de ingeniería excesiva.
La última alternativa que se me ocurre es usar algunas matemáticas métricas para mirar el DLQ y calcular si hubo un aumento en los últimos X minutos.
Todas estas parecen soluciones extrañas y demasiado complejas para lo que (estoy convencido) debe tener una implementación simple. ¿Cómo creo una alerta cada vez que un DLQ recibe un mensaje?
Encontré este mismo problema y tuve éxito al implementarlo usando Metrics Math. Cloudwatch tiene una función RATE() que:
"Devuelve la tasa de cambio de la métrica por segundo. Esto se calcula como la diferencia entre el valor del punto de datos más reciente y el valor del punto de datos anterior, dividido por la diferencia de tiempo en segundos entre los dos valores".
https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/using-metric-math.html
Así que creé una alarma que analiza la tasa de cambio de la métrica ApproximateNumberOfMessagesVisible en la cola Deadletter. Entra en alarma cuando la tasa de cambio es mayor que 0. Aquí hay un ejemplo de plantilla de Cloudformation para la alarma:
DeadletterAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: "DEADLETTER_ALARM" ComparisonOperator: GreaterThanThreshold EvaluationPeriods: 1 TreatMissingData: missing Threshold: '0' Metrics: - Id: r1 Expression: RATE(FILL(m1, 0)) ReturnData: true - Id: m1 Label: VisibleAverage ReturnData: false MetricStat: Stat: Average Period: '300' Metric: MetricName: ApproximateNumberOfMessagesVisible Namespace: AWS/SQS Dimensions: - Name: QueueName Value: "Deadletter_queue_name"Otra forma de lograr esto es generar una alarma en ApproximateNumberOfMessagesDelayed . Entonces solo necesita establecer un retraso en su DLQ. Así que podría verse algo como esto:
MyDLQAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: MyDLQAlarm AlarmDescription: "Alarm when we have 1 or more failed messages in 10 minutes for MyQueue." Namespace: "AWS/SQS" MetricName: "ApproximateNumberOfMessagesDelayed" Dimensions: - Name: "QueueName" Value: Fn::GetAtt: - "MyQueue" - "QueueName" Statistic: "Sum" Period: 300 DatapointsToAlarm: 1 EvaluationPeriods: 2 Threshold: 1 ComparisonOperator: "GreaterThanOrEqualToThreshold" AlarmActions: - Ref: "SNSTopic"Entonces su DLQ puede verse así:
MyQueueDLQ: Type: AWS::SQS::Queue Properties: QueueName: MyQueueDLQ MessageRetentionPeriod: 1209600 DelaySeconds: 60