---
title: "Allarmi CloudWatch via chiamata, senza Lambda né Twilio"
description: "SNS non può chiamare un telefono. Instrada gli allarmi CloudWatch via EventBridge a un webhook di chiamata: setup, filtri e trappole da evitare."
date: 2026-10-16
author: Nooc
authorAvatarLink: /images/avatars/nooc.webp
authorLink: https://nooc.me
tags:
  - AWS
  - CloudWatch
  - EventBridge
  - avvisi via chiamata
  - webhook
  - reperibilità
---

# Allarmi CloudWatch via chiamata: da EventBridge al telefono, senza Lambda

Un allarme CloudWatch non può chiamare il tuo telefono. Le sue uniche azioni integrate sono SNS, Auto Scaling, EC2 e Systems Manager, e SNS finisce in una mail, in un SMS o in una coda che devi stare a guardare. I tutorial che alla fine fanno squillare il telefono mettono in piedi una funzione Lambda e un account Twilio. Puoi fare a meno di entrambi: lascia che EventBridge riceva il cambio di stato dell'allarme, lo rimodelli in un piccolo corpo JSON e lo mandi con una POST a un canale di chiamata Echobell.

Questa guida copre l'intero percorso: il canale, la regola EventBridge, l'input transformer, i filtri che mantengono significativo lo squillo e il motivo per cui puntare SNS direttamente al webhook sembra una buona idea e per lo più non funziona.

## Perché la solita strada con SNS diventa scomoda

Il consiglio di default è "allarme → topic SNS → sottoscrittore". Per una telefonata ci sono tre problemi:

- **SNS non ha un protocollo vocale.** I tipi di sottoscrittore sono email, SMS, push mobile, SQS, Lambda, Firehose e HTTP(S). Un SMS si perde facilmente ed è bloccato da Non disturbare; per una chiamata vocale serve qualcosa che costruisci tu.
- **Il messaggio HTTPS è una stringa dentro una stringa.** SNS consegna il suo envelope con `Content-Type: text/plain`, e l'allarme stesso è un documento JSON serializzato nel campo `Message` dell'envelope. Un ricevitore di webhook che legge dei campi — `AlarmName`, `NewStateValue` — trova un unico blob opaco.
- **L'envelope è grande.** Tra firma, URL del certificato di firma e link di disiscrizione, l'envelope aggiunge ben più di un kilobyte prima che inizi il testo del tuo allarme. Echobell tronca il corpo di una notifica a 1500 byte, quindi un template "riversa tutto il corpo" si interrompe proprio dove comincia la parte utile.

Puoi far funzionare SNS con una Lambda che spacchetta il messaggio e lo inoltra. Ma CloudWatch pubblica già ogni cambio di stato degli allarmi su EventBridge come un pulito evento JSON — senza alcuna azione da configurare — ed EventBridge può rimodellarlo e chiamare da solo un endpoint HTTPS.

## Cosa ti serve

- Un account AWS e il permesso di creare regole, connessioni e API destination in EventBridge
- Echobell installato ([App Store](https://apps.apple.com/app/apple-store/id6743597198?pt=128151925&ct=blog-cloudwatch-alarm-phone-call-alerts-it&mt=8) / [Google Play](https://play.google.com/store/apps/details?id=one.echobell.echobellandroid))
- Almeno un allarme CloudWatch esistente
- Dieci minuti

Dalla tua parte non serve nulla che accetti traffico in ingresso. La richiesta in uscita la fa EventBridge.

## Passo 1 — Crea un canale che squilla

In Echobell crea un canale e imposta il tipo di notifica su **Chiamata**. Un canale di chiamata si comporta come una telefonata in arrivo invece che come un push, quindi passa attraverso Full Immersion e Non disturbare di iOS.

Il transformer del passo 3 invia un corpo piatto con i campi `alarm`, `state`, `reason`, `region` e `link`, quindi i template restano brevi:

```
Titolo: {{state}}: {{alarm}}
Corpo: {{reason}}
```

Imposta il **template del link** nelle impostazioni avanzate, così toccando la notifica si apre l'allarme nella console:

```
{{link}}
```

Copia l'URL del webhook dalla vista di dettaglio del canale:

```
https://hook.echobell.one/t/<channel-token>
```

## Passo 2 — Crea la connection e l'API destination

EventBridge chiama endpoint HTTPS esterni tramite una **API destination**, che richiede una **connection** che porta l'autenticazione. Echobell autentica con il token segreto nell'URL, quindi la connection è una formalità — ma EventBridge non crea una destination senza.

1. Apri **EventBridge → Integration → API destinations → Connections → Create connection**
2. **Name**: `echobell`
3. **Authorization type**: **API key**
4. **API key name**: `x-source`, **Value**: `eventbridge`
5. Crearla, poi vai su **API destinations → Create API destination**
6. **Name**: `echobell-calling`
7. **API destination endpoint**: l'URL del tuo canale Echobell del passo 1
8. **HTTP method**: `POST`
9. **Invocation rate limit**: `1` al secondo basta e avanza e fa da valvola di sicurezza
10. **Connection**: `echobell`

L'header con la API key viene inviato a ogni richiesta. Puoi controllarlo in una condizione del canale Echobell se vuoi un secondo cancello davanti al token:

```
header["x-source"] == "eventbridge"
```

## Passo 3 — Crea la regola e l'input transformer

Vai su **EventBridge → Rules → Create rule** nella stessa regione dei tuoi allarmi. Le regole sono regionali: un allarme in `eu-west-1` è invisibile a una regola in `us-east-1`.

Usa l'event bus **default** e una regola di tipo **event pattern**. Questo pattern intercetta ogni allarme che passa in `ALARM`:

```json
{
  "source": ["aws.cloudwatch"],
  "detail-type": ["CloudWatch Alarm State Change"],
  "detail": {
    "state": { "value": ["ALARM"] }
  }
}
```

Come target scegli **EventBridge API destination** e seleziona `echobell-calling`. Lascia che la console crei una nuova execution role: concede `events:InvokeApiDestination` per questa destination e nient'altro.

Poi espandi **Additional settings → Configure target input → Input transformer**:

**Input path**

```json
{
  "alarm": "$.detail.alarmName",
  "state": "$.detail.state.value",
  "reason": "$.detail.state.reason",
  "region": "$.region",
  "time": "$.time"
}
```

**Template**

```json
{
  "alarm": "<alarm>",
  "state": "<state>",
  "reason": "<reason>",
  "region": "<region>",
  "time": "<time>",
  "link": "https://console.aws.amazon.com/cloudwatch/home?region=<region>#alarmsV2:alarm/<alarm>"
}
```

EventBridge invia il risultato come `application/json`, ed è ciò che permette a Echobell di leggere direttamente `{{alarm}}` e `{{state}}`.

## Passo 4 — Sapere com'è fatto davvero l'evento

L'input path legge dall'evento che CloudWatch pubblica. In versione ridotta è:

```json
{
  "version": "0",
  "id": "c4c1c1c9-6542-e61b-6ef0-8c4d36933a92",
  "detail-type": "CloudWatch Alarm State Change",
  "source": "aws.cloudwatch",
  "account": "123456789012",
  "time": "2026-10-16T03:12:44Z",
  "region": "us-east-1",
  "resources": ["arn:aws:cloudwatch:us-east-1:123456789012:alarm:prod-api-5xx"],
  "detail": {
    "alarmName": "prod-api-5xx",
    "state": {
      "value": "ALARM",
      "reason": "Threshold Crossed: 1 out of the last 1 datapoints [42.0] was greater than the threshold (10.0).",
      "timestamp": "2026-10-16T03:12:44.000+0000"
    },
    "previousState": { "value": "OK" },
    "configuration": { "description": "API 5xx errors on the prod load balancer" }
  }
}
```

Cose da sapere prima di modificare un template:

- **L'allarme sta sotto `detail`.** `$.alarmName` non trova nulla; `$.detail.alarmName` sì.
- **`state.reason` è testo generato.** Nomina il datapoint e la soglia, che è esattamente ciò che vuoi sentire alle 3 di notte.
- **I nomi degli allarmi vengono inseriti così come sono.** Un doppio apice dentro il nome o il reason di un allarme romperebbe il JSON prodotto dal transformer. Nei nomi degli allarmi usa solo lettere, cifre, trattini e underscore — comunque una buona pratica — altrimenti la chiamata fallirà con un 400.
- **Il link richiede un nome semplice.** Un nome con spazi o `#` non porterà al punto giusto; la ricerca della console lo trova comunque.

## Passo 5 — Restringi a ciò che merita una chiamata

Un canale che squilla per ogni `ALARM` è il modo più rapido per abituarsi a ignorarlo. Filtra in due punti.

**Nel pattern di EventBridge**, che gira prima che venga inviato qualsiasi cosa:

| Obiettivo | Modifica al pattern |
| --- | --- |
| Solo allarmi di produzione | `"alarmName": [{ "prefix": "prod-" }]` dentro `detail` |
| Saltare tutto ciò che non è urgente | Chiamali `warn-…` e usa `"alarmName": [{ "anything-but": { "prefix": "warn-" } }]` |
| Solo allarmi specifici | `"alarmName": ["prod-api-5xx", "prod-db-cpu"]` |
| Solo allarmi veri, non stati di test | Mantieni `"state": { "value": ["ALARM"] }` — un evento `INSUFFICIENT_DATA` non corrisponde mai |
| Un solo account o regione | Aggiungi `"account": ["123456789012"]` o `"region": ["us-east-1"]` al livello superiore |

**In Echobell**, usa una condizione di canale per ciò che il pattern non sa esprimere, come una finestra oraria:

```
state == "ALARM" && (hour >= 17 || hour < 9)
```

Le variabili di orario di Echobell sono in UTC, quindi converti prima dal tuo fuso. Il [riferimento delle condizioni](/it/docs/conditions) elenca tutte le variabili.

## Passo 6 — Una porta più silenziosa per i ripristini

Una seconda regola con `"value": ["OK"]` può dirti che il problema è rientrato, senza squillare. Crea un secondo canale Echobell di tipo **Urgente (Time Sensitive)** (o normale), una seconda API destination che punti a quello e riusa lo stesso input transformer. Il template del titolo `{{state}}: {{alarm}}` si legge già come "OK: prod-api-5xx".

| Regola | Stato | Tipo di canale | Comportamento |
| --- | --- | --- | --- |
| `alarms-to-call` | `ALARM`, prefisso `prod-` | Chiamata | Squilla attraverso Full Immersion |
| `alarms-warn` | `ALARM`, prefisso `warn-` | Urgente | Schermata di blocco, senza squillo |
| `alarms-recovered` | `OK` | Normale | Push ordinario |

## Provalo prima di fidarti

Non aspettare che la produzione si rompa. Forza un allarme nello stato che vuoi:

```bash
aws cloudwatch set-alarm-state \
  --alarm-name prod-api-5xx \
  --state-value ALARM \
  --state-reason "Manual test of the Echobell path"
```

L'allarme torna al suo stato reale alla valutazione successiva, ma l'evento di cambio di stato è vero e attraversa la tua regola. Per testare solo il lato Echobell, attiva direttamente il canale:

```bash
curl -X POST https://hook.echobell.one/t/<channel-token> \
  -H 'Content-Type: application/json' \
  -d '{"alarm":"prod-api-5xx","state":"ALARM","reason":"Manual test","region":"us-east-1","link":"https://console.aws.amazon.com/cloudwatch/"}'
```

Se il `curl` squilla e il test dell'allarme no, il problema è nella regola, nel transformer o nella destination, non nel canale.

## E SNS con email-to-call?

Se hai già un topic SNS dappertutto e non vuoi toccare EventBridge, esistono altre due strade:

- **SNS → Lambda → webhook.** Poche righe di codice leggono `Message` e poi inviano un corpo piatto allo stesso URL Echobell. Funziona, ma ora hai una funzione, una role e i suoi log da gestire.
- **SNS → email → trigger email di Echobell.** Iscrivi al topic l'[indirizzo del trigger email](/it/docs/email-trigger) del canale. L'allarme arriva come email e `{{subject}}` e `{{text}}` nei tuoi template diventano la notifica. È la configurazione più leggera di tutte, con l'avvertenza che le sottoscrizioni email di SNS richiedono un click di conferma una tantum e il testo non viene rimodellato.

Iscrivere direttamente l'URL del webhook Echobell al topic come endpoint HTTPS è la strada da evitare: la richiesta di conferma arriva come notifica, e ogni allarme successivo è il lungo envelope descritto sopra.

## Limiti che contano durante un incidente

- **1 MiB di corpo.** Echobell rifiuta con HTTP 413 i corpi di trigger oltre 1 MiB. Un allarme trasformato pesa poche centinaia di byte, quindi qui non ci arriverai.
- **120 richieste al minuto per token.** Oltre, il trigger risponde `429` con `RATE_LIMIT_EXCEEDED` e un `Retry-After`. Il limite di 1 al secondo della destination ti tiene sotto, ed EventBridge ritenta gli eventi che non è riuscito a consegnare.
- **1500 byte di corpo della notifica.** Gli output più lunghi vengono troncati. `state.reason` è una frase o due e ci sta.

## Cosa questo setup non ti dà

- **Nessuna presa in carico.** Rispondere alla chiamata non dice nulla a CloudWatch e non silenzia gli altri sottoscrittori.
- **Nessuna escalation né turno.** Vengono chiamati tutti gli iscritti al canale; nessuno viene chiamato dopo.
- **Nessuna deduplicazione oltre all'allarme.** Un allarme instabile che passa `OK → ALARM` ogni pochi minuti squillerà ogni volta. Risolvilo con periodi di valutazione più lunghi o con `DatapointsToAlarm` sull'allarme stesso.
- **Nessuna sincronizzazione bidirezionale.** Risolvere la causa non cancella nulla sul telefono.

Se sono ostacoli insormontabili, ti serve una piattaforma di reperibilità completa. Se ti serve "chiamami quando scatta l'allarme di produzione", sono una manciata di schermate della console.

## Risoluzione dei problemi

**L'allarme è scattato ma non è arrivato nulla.** Apri la scheda **Monitoring** della regola: `Invocations` mostra se il pattern ha corrisposto, `FailedInvocations` se la consegna è fallita. Le regole in una regione diversa da quella dell'allarme non corrispondono mai.

**La regola corrisponde ma la chiamata fallisce con un 400.** Il transformer ha prodotto JSON non valido. Cerca un apice o un backslash nel nome o nel reason dell'allarme.

**La notifica è vuota.** Il template sta leggendo un campo che il transformer non ha inviato. Il corpo è piatto: `{{alarm}}`, non `{{detail.alarmName}}`.

**Squilla ripetutamente per un allarme.** L'allarme è instabile. Allunga il periodo di valutazione o richiedi più datapoint; è un'impostazione di CloudWatch, non di Echobell.

**Squilla per un allarme che non ti aspettavi.** Controlla nel pattern la mancanza di un filtro `prefix`, e ricorda che anche gli allarmi compositi e quelli creati da altri strumenti (le policy di Auto Scaling, per esempio) emettono cambi di stato.

## Domande frequenti

### CloudWatch può chiamare un numero di telefono in modo nativo?

No. Le azioni degli allarmi CloudWatch sono notifiche SNS, Auto Scaling, azioni EC2 e Systems Manager. Una chiamata vocale richiede un servizio esterno: una Lambda che chiama tramite un provider, una piattaforma di reperibilità o un webhook di chiamata come Echobell.

### Mi serve un topic SNS?

No. CloudWatch emette da solo su EventBridge gli eventi di cambio di stato degli allarmi, che l'allarme abbia azioni o meno. Puoi lasciare vuoto l'elenco delle azioni dell'allarme.

### Un allarme CloudWatch passa attraverso Non disturbare?

Solo se arriva come avviso in stile chiamata. Un canale Echobell di tipo chiamata si comporta come una telefonata in arrivo, e Full Immersion e Non disturbare di iOS la lasciano passare. Un SMS o un push normale no.

### Perché non iscrivere direttamente l'URL del webhook a SNS?

SNS invia `text/plain` con l'allarme serializzato dentro una stringa `Message`, quindi il template non può leggere i singoli campi, e l'envelope è abbastanza lungo da essere troncato. SNS manda inoltre prima una conferma di sottoscrizione, che arriverebbe come notifica.

### Ha un costo su AWS?

Gli eventi di cambio di stato degli allarmi raggiungono l'event bus default senza costi; le invocazioni delle API destination sono fatturate a richiesta. Con il volume di un set di allarmi sano è una cifra trascurabile, ma controlla i prezzi attuali di EventBridge per la tua regione.

### Posso chiamare persone diverse per allarmi diversi?

Sì. Crea un canale per ogni destinatario, una regola per canale, e lascia che ognuno si iscriva con il tipo di notifica che preferisce. Non c'è presa in carico, quindi vengono chiamati tutti quelli iscritti con "chiamata".

### E gli allarmi in più regioni o account?

Le regole sono per regione, quindi crea la regola in ogni regione che usi (la stessa definizione di API destination si ripete per regione). Per più account, invia gli eventi a un bus centrale in un account e metti lì la regola.

## In sintesi

Il percorso è fatto di cinque parti: un canale di chiamata, una connection e una API destination che puntano a esso, una regola che intercetta solo gli allarmi per cui vale la pena svegliare qualcuno, un input transformer che appiattisce l'evento e un test forzato con `set-alarm-state` prima di fare affidamento su qualsiasi cosa. Tutto il resto qui serve a tenerlo abbastanza stretto perché tra un mese uno squillo significhi ancora qualcosa.

[Scarica Echobell per iPhone](https://apps.apple.com/app/apple-store/id6743597198?pt=128151925&ct=blog-cloudwatch-alarm-phone-call-alerts-it&mt=8) oppure [prendilo su Google Play](https://play.google.com/store/apps/details?id=one.echobell.echobellandroid), poi esegui il test con `set-alarm-state`.

## Articoli correlati

- [Riferimento delle condizioni di canale](/it/docs/conditions)
- [Guida all'integrazione con i webhook](/it/docs/webhook)
- [Guida al trigger email](/it/docs/email-trigger)
- [Avvisi Sentry via chiamata](/it/blog/sentry-phone-call-alerts)
- [Avvisi via chiamata per i downtime delle API](/it/blog/phone-call-alerts-api-downtime)
- [Guida per sviluppatori all'alert fatigue](/it/blog/fix-alert-fatigue-developer-guide)
- [Superare la modalità Full Immersion di iOS per gli avvisi critici](/it/blog/how-to-bypass-ios-focus-mode-for-critical-alerts)
