Passa al contenuto principale

ADR-0013 - Observability stack: Prometheus + Grafana + Loki + Alertmanager self-hosted

  • Status: Accepted (2026-05-15)
  • Deciders: Massimo Bagnoli (architect), Claude (sintesi Architect+DevOps+QA+FinOps)
  • Implementation tasks: TASK-39 (Prometheus + node_exporter), TASK-40 (FastAPI /metrics), TASK-41 (Grafana + Caddy), TASK-42 (Loki + Promtail), TASK-43 (Alertmanager + alert rules)
  • Supersedes: nessuno
  • Superseded by: nessuno

Context

Akira e' una piattaforma VoIP wholesale Class-4 con stack distribuito: FastAPI, Kamailio, RTPengine, FreeSWITCH, Postgres/TimescaleDB, Redis e NATS. Senza observability centrale, ogni incidente operativo diventa una sessione manuale di SSH, journalctl e tail su host diversi, con tempi di diagnosi alti e rischio di perdere segnali correlati.

I task TASK-39, TASK-40, TASK-41, TASK-42 e TASK-43 introducono lo stack observability. Questa ADR rende esplicite le motivazioni della scelta, i trade-off rispetto a servizi managed e stack alternativi, le policy di retention e la proiezione costi a 12 mesi.

Vincoli operativi:

  • Budget: sotto 20 EUR/mese per staging e sotto 100 EUR/mese per produzione per la sola observability infrastructure.
  • Skillset team: 1 developer principale piu' agenti AI, senza ops dedicato.
  • Privacy: log e metriche possono contenere numeri telefonici, tenant id o altri dati operativi sensibili.
  • Onboarding: un nuovo dev deve usare dashboard base e alert senza conoscere PromQL o LogQL avanzati.
  • Scope Fase 1: 3 server staging.
  • Scope Fase 2: circa 12 server totali.
  • Scope produzione Fase 4: circa 15-20 server con target iniziale 200 CPS.

Decision

Adottiamo uno stack Grafana Labs self-hosted basato su componenti open-source installati come servizi di sistema e gestiti via Ansible.

ComponenteVersione targetRuoloBindReverse proxy
Prometheus2.55.xMetrics scrape e storage TSDB127.0.0.1:9090via Caddy solo se necessario
node_exporter1.8.xMetriche OS su ogni host:9100 su rete privata/Tailscalenessuno
FastAPI Instrumentator7.xMetriche applicative /metricsprocesso APInessuno
Grafana11.3.xUI, dashboard e datasource127.0.0.1:3001Caddy grafana.akira-staging.asheep.it
Loki3.2.xAggregazione log127.0.0.1:3100via datasource Grafana
Promtail3.2.xLog shipper su ogni host:9080 locale/privatonessuno
Alertmanager0.27.xRouting alert e silenziamenti127.0.0.1:9093Caddy alerts.akira-staging.asheep.it

Retention policies

  • Prometheus metrics: retention 30 giorni, limite locale 20GB.
  • Loki logs staging: retention 30 giorni, stima 50MB/giorno per 3 host, circa 1.5GB/mese.
  • Loki logs produzione: retention 30 giorni, stima 500MB/giorno per 15 host a 200 CPS, circa 15GB/mese.
  • Alertmanager state: effimero, in memoria, senza persistenza richiesta in Fase 1.

La retention di 30 giorni e' sufficiente per troubleshooting operativo, review settimanali degli SLO e confronto con deploy recenti. Non copre esigenze di audit a 12 mesi: quel requisito richiedera' export separato o storage freddo.

Network topology

  • Prometheus, Grafana, Loki e Alertmanager fanno bind su localhost sul nodo management.
  • node_exporter e promtail sono raggiungibili solo da rete privata o Tailscale; il firewall Hetzner blocca l'accesso pubblico.
  • Caddy e' l'unico entry point HTTP pubblico per le UI autorizzate.
  • Lo scrape Prometheus usa hostname stabili, preferibilmente Magic DNS Tailscale o inventory Ansible, evitando IP hardcoded.

Auth

  • Grafana: password admin da vault (vault_grafana_admin_password), anonymous disabilitato, sign-up disabilitato.
  • Prometheus: nessuna auth applicativa in Fase 1; il controllo e' dato dal bind localhost e dalla mancata esposizione via Caddy.
  • Loki: auth_enabled: false, accessibile solo dal datasource Grafana su localhost.
  • Alertmanager: UI esposta via Caddy; basic auth o altro controllo di accesso potra' essere aggiunto in un task successivo.

Alert routing

  • Critical: Telegram bot verso canale NOC, repeat ogni 1h.
  • Warning: email a noc@asheep.it, repeat ogni 4h.
  • Info: solo dashboard in Fase 1, senza notifica attiva.
  • Inhibition: HostDown silenzia altri alert dello stesso host per ridurre rumore operativo.

Cost projection 12 months

In Fase 1 lo stack gira su akira-mgmt-01-staging, gia' previsto per altri servizi management. Il costo incrementale e' quindi vicino a 0 EUR/mese, salvo storage extra.

ScenarioHostStorage stimatoCosto licenzaCosto infra incrementaleProiezione 12 mesi
Staging Fase 13circa 20GB metriche + 2GB log/mese hot0 EUR0-5 EUR/mese0-60 EUR
Fase 212circa 20GB metriche + 8-10GB log/mese hot0 EUR5-15 EUR/mese60-180 EUR
Produzione Fase 415-20circa 20GB metriche + 15-25GB log/mese hot0 EUR15-50 EUR/mese180-600 EUR

Il costo resta sotto il budget indicato finche' la retention hot rimane a 30 giorni. Se viene richiesto un anno di log interrogabili in Loki, servono storage volume dedicato o tiering; a 15GB/mese la sola retention annuale dei log vale circa 180GB piu' overhead.

Consequences

Positive

  • Costo licenza nullo: Prometheus, Grafana OSS, Loki, Promtail, node_exporter e Alertmanager non introducono fee SaaS.
  • Costo incrementale basso: Fase 1 usa capacity gia' disponibile sul nodo management.
  • Privacy first: metriche e log restano dentro l'infrastruttura Akira.
  • Stack coerente: PromQL, LogQL e dashboard vivono nella stessa UI, riducendo il numero di strumenti da imparare.
  • Debug generalist-friendly: componenti single-purpose, config YAML e systemd sono piu' ispezionabili di una piattaforma SaaS opaca.
  • Tailscale-native: scrape e shipping possono restare su rete privata senza aprire porte pubbliche.
  • Migrazione futura chiara: Grafana Cloud puo' essere introdotto cambiando remote write/datasource senza riscrivere metriche e dashboard di base.

Negative

  • Single point of failure: in Fase 1 tutto converge su mgmt-01; se cade, si perdono metriche, log e alerting.
  • Bootstrap alerting debole: Alertmanager sullo stesso nodo che deve monitorare non puo' notificare la propria indisponibilita' totale.
  • Storage da monitorare: Loki in produzione puo' crescere rapidamente; 30 giorni sono gestibili, 12 mesi hot no.
  • No tracing distribuito: Tempo, Jaeger e OpenTelemetry non sono inclusi in questa ADR.
  • Rule maintenance manuale: alert rules in YAML versionate in Git sono auditabili, ma meno comode di una UX managed.
  • Dipendenza Telegram: le notifiche critical dipendono da un servizio terzo; l'email resta canale secondario ma non sostituisce SMS o paging dedicato.

Neutral

  • La scelta self-hosted e' una decisione di Fase 1/Fase 2, non un rifiuto permanente del managed.
  • Loki privilegia costo e integrazione con Grafana rispetto alla potenza di ricerca full-text di Elasticsearch.
  • Retention hot di 30 giorni e retention audit a lungo termine sono problemi distinti e vanno trattati con policy separate.

Alternatives considered

A1 - Grafana Cloud

Grafana Cloud offre Prometheus-compatible metrics, Loki-compatible logs, dashboard managed e alerting gestito.

Pro: riduce operations, include piani free/entry-level e mantiene compatibilita' concettuale con lo stack scelto.

Contro: costo crescente con serie metriche, log e utenti; invio di dati sensibili a terza parte; dipendenza da policy e limiti del provider.

Verdict: rejected per Fase 1. Possibile upgrade in Fase 4 se l'onere operativo del self-hosted supera il costo managed.

A2 - DataDog

DataDog e' una piattaforma SaaS completa per metriche, log, APM, synthetics e alerting.

Pro: UX molto matura, integrazioni ampie, alerting potente e bassa manutenzione interna.

Contro: costo fuori budget per 15-20 host con log/APM, lock-in forte e minore controllo sui dati sensibili.

Verdict: rejected categoricamente per budget e privacy.

A3 - ELK stack

Elasticsearch, Logstash e Kibana sono uno stack maturo per log search e analytics.

Pro: ricerca full-text potente, ecosistema grande, adatto a use case log-centric complessi.

Contro: richiede piu' RAM e tuning, non copre metriche native, introduce complessita' operativa sproporzionata per Fase 1.

Verdict: rejected. Loki e' sufficiente per log operativi correlati a metriche e dashboard Grafana.

A4 - CloudWatch

CloudWatch sarebbe l'opzione managed naturale in un'infrastruttura AWS.

Pro: integrato con AWS, metriche e log gestiti, alerting disponibile.

Contro: Akira gira su Hetzner, quindi introdurrebbe una dipendenza cloud non necessaria, trasferimento dati e lock-in senza beneficio proporzionato.

Verdict: rejected come non applicabile all'architettura corrente.

A5 - Prometheus + InfluxDB + Telegraf

InfluxDB e Telegraf possono coprire metriche time-series e collection multi-source.

Pro: InfluxDB e' valido per long-term time-series e Telegraf ha molti input plugin.

Contro: duplica il ruolo di Prometheus, aggiunge un secondo modello query/storage e non risolve i log.

Verdict: rejected per over-engineering e sovrapposizione funzionale.

Implementation references

  • TASK-39: infra/roles/prometheus/, infra/roles/node_exporter/, infra/playbooks/bootstrap_all.yml, infra/playbooks/deploy_management.yml.
  • TASK-40: apps/api/src/akira_api/main.py o equivalente backend FastAPI, Instrumentator e test /metrics.
  • TASK-41: infra/roles/grafana/, dashboard fastapi-overview e system-overview, infra/roles/caddy/templates/Caddyfile.j2.
  • TASK-42: infra/roles/loki/, infra/roles/promtail/, datasource Loki in Grafana.
  • TASK-43: infra/roles/alertmanager/, rule Prometheus akira-base.yml, Caddy block alerts.*.

Monitoring & success metrics

  • Prometheus uptime: target 99.5% in Fase 1.
  • Loki ingestion lag: p95 sotto 10 secondi dalla generazione del log alla visibilita' in Grafana.
  • Alert false positive rate: sotto 5%; alert non actionable vanno rimossi o trasformati in dashboard.
  • Dashboard load time: sotto 2 secondi per FastAPI Overview e System Overview su intervallo standard.
  • Onboarding nuovo dev: sotto 1 giorno per leggere dashboard base e collegare alert ai runbook.
  • Storage usage: alert sopra 85% del volume dedicato a metriche/log.

Open questions

  • Multi-tenant Grafana in Fase 4: capire se clienti wholesale dovranno vedere metriche isolate per tenant. Grafana OSS non risolve bene questo caso senza separazioni forti.
  • Tracing distribuito: valutare Tempo o Jaeger con OpenTelemetry quando il signaling stack sara' completo.
  • High availability observability: decidere in Fase 4 se introdurre Alertmanager cluster, Prometheus federation o servizio esterno di health check.
  • Log retention long-term: se audit/compliance richiede 12 mesi, introdurre tier freddo su Storage Box o object storage con export compresso.
  • Paging critical: valutare SMS o provider paging dedicato se Telegram/email non sono sufficienti per produzione.