Nota: este tutorial sirve para cualquier aplicación desplegada en Amazon Web Services, no solo para skills Alexa. Por ejemplo, podemos seguir este tutorial pare recibir alertas (por email, Slack, Telegram, etc…) cuando una aplicación web desplegada en Amazon EC2 dé algún error.

Os dejo el código fuente en el repositorio de github 🔗.

El tutorial se divide en 2 opciones de implementación, una basada 100% en servicios de AWS y otra que utiliza el servicio externo Sentry.

Opción 1. Solución basada en AWS, sin tener que modificar el código de nuestras skills/aplicaciones. Usaremos «CloudWatch log triggers» para filtrar los logs y una función AWS Lambda para enviar las notificaciones.

Opción 2. Solución basada en Sentry. Sentry es un servicio de terceros que nos alerta de errores en nuestras aplicaciones. Está disponible en versión gratuita (limitada a 5.000 errores/mes) y en versión de pago.

 

Opción 1. Solución basada en AWS

  1. Lo primero que haremos es crear una nueva función AWS Lambda con el código fuente del repositorio de github 🔗. Puedes llamar a esta función «my-function-reads-errors-and-sends-notifications».
  2. A continuación, localiza en Amazon CloudWatch el grupo de logs que te interesa analizar. Y en la pestaña «Subscription filters», pulsa el botón «Create Lambda subscription filter».  En el ejemplo, queremos analizar los logs de una función Lambda llamada «my-function-writes-error-logs»:

3. La pantalla para crear la suscripción será similar a la siguiente captura. En el primer desplegable, selecciona la función Lambda que se encargará analizar los logs y de enviar las notificaciones (es decir, la función que creaste en el paso 1).

4. En el campo «Subscription filter pattern» puedes escribir algo como «error», «API error», etc. A la función Lambda del paso 1 solo se le enviarán las líneas de log que contengan dichas cadenas de texto.

5. Ahora vamos a crear un topic en Amazon SNS. Lo llamamos «ErrorNotification», escogemos tipo «standard» y la política de acceso por defecto.

6. Tras crear el topic de SNS, nos suscribiremos a él. Este paso lo hacemos también desde la consola de AWS. Para suscribirnos a un topic, debemos indicar nuestra dirección de email, recibiremos un email de confirmación y debemos pinchar en el enlace de contiene. Podemos suscribir a más de 1 dirección de email.

7. En la pantalla del SNS Topic aparece el identificador ARN del mismo. Cópialo y pégalo en el código de la función Lambda, en la línea siguiente:

const ARN_TOPIC_SNS = '<aquí el ARN de tu topic SNS>';

8. Si ahora invocas a tu función Lambda «my-function-writes-error-logs» que escribe en el log, si escribe un mensaje que haga match con el filter pattern del paso 4, entonces se invocará a la función «my-function-reads-errors-and-sends-notifications», que intentará publicar un mensaje en el SNS topic. Y dará un error por falta de permisos en el rol de ejecución de «my-function-reads-errors-and-sends-notifications». Verás un mensaje de error como éste en el log de dicha función:

9. Para solucionar el error anterior, añadimos una nueva política IAM en el rol de ejecución de la función lambda «my-function-reads-errors-and-sends-notifications». Siguiendo el principio de mínimo privilegio, vamos a conceder solo permiso de «publish» y solo en el topic que acabamos de crear. La nueva política añadida será así:

10. Ahora sí, si repetimos el paso 8, recibiremos un email feo de SNS 🙂 . El cuerpo del email es exactamente el mensaje del log de CloudWatch Logs que hizo match con los filtros del paso 4.

 

11. Para recibir el mismo mensaje por Telegram, basta con crear un bot de Telegram, crear un grupo de chat con dicho bot y configurar las 2 líneas siguientes de la función lambda:

const TELEGRAM_ACCESS_TOKEN = ''; // used for API https://api.telegram.org/bot<token>/
const TELEGRAM_ID_CHAT = ''; // Use this API yo get this ID chat: GET https://api.telegram.org/bot<token>/getUpdates

Para obtener esos 2 valores, seguimos estos pasos:

  • Abrimos telegram y buscamos al usuario «BotFather» (es un bot oficial de Telegram y la forma de crear bots).
  • Le mandamos a dicho bot el mensaje «/newBot». Seguimos los pasos hasta que nos responda con el TELEGRAM_ACCESS_TOKEN, que pegaremos en la función Lambda.
  • Creamos un grupo de chat en telegram y añadimos al bot (para añadirlo, lo buscamos por el username que le hayamos puesto durante el paso anterior).
  • Escribimos un mensaje en el grupo.

  • Desde una pestaña nueva del navegador web o usando Postman, llamamos a la URL https://api.telegram.org/bot<TELEGRAM_ACCESS_TOKEN>/getUpdates , que nos devolverá el TELEGRAM_ID_CHAT:
  • Pegamos el TELEGRAM_ID_CHAT en la función lambda, guardamos, hacemos deploy. Y volvemos a ejecutar la función Lambda que escribe errores en el Log. A los pocos segundos, tendremos la alerta también en el grupo de Telegram:

12. Para recibir en Slack las alertas, es aún más sencillo. Sigue los pasos de este enlace para obtener la SLACK_WEBHOOK_URL que deberás pegar en la función Lambda: https://api.slack.com/messaging/webhooks . Tras completar los pasos y pegar la URL única en la función Lambda, recibirás también las alertas así 🙂

Y hasta aquí la opción 1 👨‍💻

 

Opción 2. Solución basada en Sentry

La implementación usando Sentry es mucho sencilla. Primero entra en https://sentry.io, inicia sesión y crea un proyecto de forma gratuita. Cuando te pregunte el tipo de proyecto, indica «lambda (node)». A continuación verás los pasos para la instalación sencilla. Solo requiere añadir el módulo @sentry/serverless en nuestro proyecto, inicializarlo, modificar mínimamente el handler principal y utlizar los métodos Sentry.captureMessage() y Sentry.captureException() para empezar a recibir resultados en Sentry.io:

npm install @sentry/serverless --save

Tras realizar los cambios en tu función AWS Lambda, invócala para que Sentry reciba el primer evento y se complete la configuración. Por ejemplo, puedes añadir la línea «Sentry.captureMessage(‘Sentry message :)’);» para que Sentry reciba el primer evento.

A continuación, entra en la sección «Issues» de Sentry, verás el detalle del evento recibido, que tendrá un aspecto similar a éste:

Desde la sección «Alerts», puedes configurar los emails de aviso. Por ejemplo, puedes indicar que se te envíe un email cuando llega a Sentry una issue nueva, o cuando una issue se repite más de N veces. Los emails de Sentry contienen un resumen del evento capturado:

Por último, desde la sección «Settings > Integrations» puedes activar las integraciones con multitud de servicios somo Slack, Jira, Trello, Asana… no está Telegram 🙁

Hasta aquí hemos explicado lo básico, pero Sentry ofrece más opciones a los desarrolladores para añadir contexto en los eventos. Si quieres ver cómo añadir información del usuario y tags desde tu código, mira este tutorial de Xavi.

Si bien la funcionalidad de Sentry es muy completa, incluso en la versión gratuita, también tiene un impacto en el rendimiento de nuestro backend. En las pruebas realizadas, la función lambda que actúa como bakend de la skill Alexa, ha pasado de un tiempo de ejecución < 20 ms (sin Sentry) a un tiempo de ejecución de > 300 ms con Sentry. Creo que la penalización de Sentry se nota más en AWS Lambda que en otro tipo de servidores de aplicaciones, por las características de AWS Lambda: En AWS Lambda, Sentry no puede enviar la información a sus servidores después de que la función haya respondido al usuario (porque la instancia de AWS Lambda puede desaparecer a partir de ese momento). Mientras, en otros servidores de aplicaciones en los que se garantiza la ejecución después de responder al usuario, es posible que Sentry gestione con una cola de mensajes la comunicación con sus servidores, penalizando menos el rendimiento de la aplicación que monitoriza. Este punto habría que tenerlo en cuenta y estudiarlo más.

 

Conclusiones

A modo de resumen he preparado esta tabla comparativa. Dependiendo del tipo de proyecto y los errores que se quieran monitorizar (recurrencia y criticidad), puede interesar empezar por la opción 1 o por la 2:

Comparativa Opción 1: AWS Lambda Opción 2: Sentry
Coste Costes del uso de AWS (tráfico saliente, ejecución de AWS Lambda… ver free-tier 🔗). Versión gratuita hasta 5.000 eventos/mes 🔗.
¿Afecta al rendimiento del backend? No. 😍 Sí (medir). 🤔
¿Requiere modificar el código fuente del backend? No (pero hay que desplegar la AWS Lambda y configurar las integraciones 1 vez).  😍 Un poco. 🤔
Nivel de detalle de la monitorización Limitado al mensaje de log, extraído de AWS CloudWatch Logs, pero puede ser suficiente. 🤔 Muy alto. 😍
¿Puedo monitorizar otras cosas? Sí, todo lo que haya en CloudWatch Logs, como los mensajes de «timeout» de la propia función AWS Lambda. 😍 Se puede configurar Sentry para que alerte si el timeout de la AWS Lambda está a punto de suceder. 🤔
Filtros y reglas Limitado a los que se apliquen en AWS CloudWatch Logs Subscription (string patterns). Se repiten N veces las alertas si el error ocurre N veces. 🤔 Avanzados. Agrupa los eventos que ocurren más de una vez. Permite crear reglas avanzadas de alertas (para recibir solo alertas de errores nuevos, o solo si el error se repite más de N veces, etc). 😍
Entorno colaborativo Varias personas pueden recibir las alertas por mail (SNS), por grupo de Telegram o de Slack, pero no hay un entorno web donde gestionar qué errores han sido corregidos y cuáles son nuevos. 🤔 Con las versiones de pago, las alertas pueden ser atendidas por más de 1 persona. 🤔
Integraciones posibles Las 3 (mail, Slack y Telegram), las cuales hay que mantener. Añadir nuevas requeriría programación.🤔 Muchísimas (Telegram no). 🤔😍
Skills mejoradas Uso de AWS CloudWatch Logs Subscriptions, Telegram bots, Slack apps, SNS… 🙂 Uso de Sentry 🙂

 

Enlaces de interés