Alertas de fallos de Netlify Functions a Slack, Telegram y WhatsApp

Alertas de fallos de Netlify Functions a Slack, Telegram y WhatsApp

Un webhook de deploy de Netlify dispara cuando muere el build. Una Function que lanza en runtime es otro fallo: el sitio sigue verde, /api/checkout devuelve 500 y nadie mira Functions → Logs hasta que un cliente se queja.

No necesitas un SDK de Slack dentro de cada función. Captura la excepción, POST a AlertHub, y Slack, Telegram, WhatsApp, Discord o Teams reciben el mismo evento critical.

Esto es distinto de las notificaciones de deploy de Netlify (webhooks salientes del estado del build). Aquí la propia función avisa de que ha petado.

Qué deberías alertar

EventoDóndeNivel recomendadoPor qué importa
Excepción no controlada en una función HTTPtry/catch alrededor del handlerCriticalCheckout, auth o un webhook tuyo acaba de morir
Función programada fallidael mismo try/catch en el cronCriticalEl job nocturno no corrió
4xx de un API aguas abajo que ya manejassendAlert explícitoWarningRecuperable; aún merece una fila en el panel
Invocación correctaomitir, o infoInfoSolo historial — no pings a Slack

Solo warning y critical se empujan a canales externos. Las llamadas correctas deben quedarse en info (o omitirse).

Configuración (una sola vez)

  1. Crea un proyecto en app.thealerthub.com y copia la clave secreta.
  2. En Netlify: Project configuration → Environment variables → añade ALERTHUB_KEY. Ámbitola a Production (y Preview si quieres ruido de PRs). Nunca pongas la clave en el código de la función.
  3. Conecta destinos en AlertHub. Telegram basta para un maintainer; Slack para el canal del equipo.

Docs: API de ingestión. Webhooks de deploy fallido (no crashes de funciones): fuente Netlify.

Alerta 1: Función HTTP petada (el valor por defecto)

Functions 2.0 exportan un handler por defecto. Envuelve el trabajo en try/catch, avisa a AlertHub y luego devuelve 500. Traga los errores del notify para que un AlertHub caído no oculte el stack original.

// netlify/functions/checkout.mjs
const ALERTHUB_URL = 'https://api.thealerthub.com/sendAlert';

async function notifyAlertHub({ title, description, level = 'critical' }) {
  try {
    await fetch(ALERTHUB_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        ah_key: process.env.ALERTHUB_KEY,
        ah_title: title,
        ah_description: description,
        ah_level: level,
        ah_source: 'Netlify Function',
      }),
    });
  } catch (notifyError) {
    console.error('AlertHub notify failed', notifyError);
  }
}

export default async (req, context) => {
  try {
    const body = await req.json();
    const result = await chargeCustomer(body);
    return Response.json({ ok: true, result });
  } catch (error) {
    const stack = error instanceof Error ? error.stack : String(error);
    await notifyAlertHub({
      title: 'Netlify Function failed: checkout',
      description: `${stack}\nurl: ${req.url}\nrequestId: ${context.requestId}`,
    });
    return new Response('Internal error', { status: 500 });
  }
};

export const config = { path: '/api/checkout' };

Despliega, fuerza un throw (un payload malo basta) y confirma la alerta en el panel y en tus canales.

Alerta 2: exports.handler clásico

Las funciones antiguas siguen usando la API compatible con Lambda. Misma variable de entorno, mismo cuerpo JSON:

// netlify/functions/legacy-webhook.js
const ALERTHUB_URL = 'https://api.thealerthub.com/sendAlert';

exports.handler = async (event) => {
  try {
    await processWebhook(JSON.parse(event.body || '{}'));
    return { statusCode: 200, body: '{"ok":true}' };
  } catch (error) {
    try {
      await fetch(ALERTHUB_URL, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          ah_key: process.env.ALERTHUB_KEY,
          ah_title: 'Netlify Function failed: legacy-webhook',
          ah_description: error instanceof Error ? error.stack : String(error),
          ah_level: 'critical',
          ah_source: 'Netlify Function',
        }),
      });
    } catch (notifyError) {
      console.error('AlertHub notify failed', notifyError);
    }
    return { statusCode: 500, body: 'Internal error' };
  }
};

Alerta 3: Función programada

Las funciones cron fallan en silencio si solo miras el sitio. El mismo catch, ah_source distinto para filtrar el feed:

// netlify/functions/nightly-sync.mjs
export default async () => {
  try {
    await syncOrders();
    return new Response('ok');
  } catch (error) {
    await fetch('https://api.thealerthub.com/sendAlert', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        ah_key: process.env.ALERTHUB_KEY,
        ah_title: 'Netlify scheduled function failed: nightly-sync',
        ah_description: error instanceof Error ? error.stack : String(error),
        ah_level: 'critical',
        ah_source: 'Netlify Cron',
      }),
    }).catch((notifyError) => console.error('AlertHub notify failed', notifyError));
    return new Response('Internal error', { status: 500 });
  }
};

export const config = { schedule: '0 3 * * *' };

Ideas para sacarle más partido

  • Reutiliza un helper. Copia notifyAlertHub a netlify/functions/_lib/alerthub.mjs e impórtalo en cada handler.
  • Incluye requestId. La descripción de arriba abre la fila en los logs de Netlify Functions con una búsqueda.
  • Preview vs production. Usa un segundo proyecto AlertHub (o warning en Deploy Previews) para que un PR roto no pagine el canal de guardia.
  • Edge Functions. El mismo try/catch + fetch. Lee la clave con Netlify.env.get('ALERTHUB_KEY') (o Deno.env.get) — sigue siendo una variable de entorno, nunca un ah_key hardcodeado.
  • Combínalo con webhooks de deploy. Fallos de build vía deploys de Netlify; crashes de runtime con los snippets de arriba.

Preguntas frecuentes

¿Por qué no solo los logs / el email de Netlify?
Los logs necesitan que alguien los abra. El email de Netlify se ahoga junto a los newsletters. AlertHub es el último salto para que Slack, Telegram y WhatsApp sigan sincronizados.

¿Funciona process.env.ALERTHUB_KEY en Functions 2.0?
Sí. Configúrala en la UI de Netlify (o netlify env:set ALERTHUB_KEY). Vuelve a desplegar después de añadir la variable para que producción la recoja.

¿Puedo enviar info al éxito?
Sí, con "ah_level": "info". No se repartirá a canales.

¿Es lo mismo que un deploy fallido de Netlify?
No. Los webhooks de deploy cubren build/publish. Esto cubre excepciones dentro de una función cuando el sitio ya está en vivo. Usa ambos.

Siguientes pasos

Añade ALERTHUB_KEY, pega el try/catch en una función de producción, fuerza un throw y conecta Slack o Telegram.

Relacionado: deploys de Netlify · fallos de Cloudflare Workers · API de ingestión