Building Your Own Historical Uptime Dashboard: Lessons from Tracking GitHub’s Availability
Monitorare l’uptime di servizi esterni è fondamentale quando il tuo business dipende da API di terze parti. Dopo aver subito tre incidenti critici in produzione causati da degradazioni di GitHub non rilevate tempestivamente, ho costruito un sistema di tracking storico che oggi raccoglie dati da oltre 18 mesi. In questo articolo condivido l’architettura e il codice per replicare questo sistema, integrandolo con Pimcore come backend di gestione e visualizzazione.
Prerequisiti
- PHP 8.1+ con estensioni
pdo_sqlite,curl,json - Pimcore 11.x installato e funzionante
- Node.js 18+ per il frontend di visualizzazione
- Composer e npm configurati
- FamiliaritĂ con i Data Objects di Pimcore
- Conoscenza base di SQLite e time-series data
💡 Il sistema è progettato per funzionare su un VPS da 5€/mese — nessun database server dedicato richiesto.
Architettura e Concetti Chiave
Il sistema si compone di tre layer principali: Collection (scraping rispettoso delle status page), Storage (persistenza efficiente con SQLite + aggregazioni), e Visualization (dashboard interattiva integrata in Pimcore).
flowchart TD
subgraph Collection["Layer di Collection"]
A[Cron Job ogni 5 min] --> B[Status Page Scraper]
B --> C{Rate Limiter}
C -->|OK| D[Parser JSON/HTML]
C -->|Throttled| E[Backoff Queue]
E --> C
end
subgraph Storage["Layer di Storage"]
D --> F[SQLite Raw Events]
F --> G[Aggregation Worker]
G --> H[Hourly Rollups]
G --> I[Daily Rollups]
H --> J[Pimcore Data Objects]
I --> J
end
subgraph Visualization["Layer di Visualization"]
J --> K[REST API Controller]
K --> L[Chart.js Dashboard]
L --> M[Incident Timeline]
L --> N[Trend Analysis]
end
F -.->|Backup giornaliero| O[(Flat File Archive)]
Il flusso garantisce tre proprietĂ essenziali:
- Resilienza: il rate limiter previene ban dalle status page
- Efficienza: le aggregazioni riducono i dati raw da GB a MB
- GranularitĂ : manteniamo i dati grezzi per analisi forensi
📝 GitHub espone la sua status page via API JSON su
https://www.githubstatus.com/api/v2/status.json— non serve parsing HTML.
Implementazione Passo-Passo
Configurazione del Data Model in Pimcore
Prima di tutto, definiamo la struttura dati in Pimcore per memorizzare i rollup aggregati. Creiamo due classi: UptimeService per i servizi monitorati e UptimeDataPoint per i dati aggregati.
| |
| |
Dopo aver creato le definizioni, rigenera le classi:
| |
Sistema di Scraping con Rate Limiting Intelligente
Il cuore del sistema è lo scraper che rispetta i limiti delle status page. Implementiamo un servizio Symfony che gestisce backoff esponenziale e caching.
| |
⚠️ Non ridurre l’intervallo di check sotto i 5 minuti per servizi pubblici. Rischi di essere bannato e violare i ToS.
Storage Time-Series con SQLite e Aggregazioni Automatiche
SQLite è sorprendentemente efficace per dati time-series fino a decine di milioni di righe. Il trucco è nelle aggregazioni pre-calcolate che riducono drasticamente i tempi di query.
| |
Configurazione per Produzione
Il passaggio a produzione richiede attenzione su diversi fronti: rate limiting, gestione connessioni, logging strutturato e deployment automatizzato.
Docker Compose per Produzione
| |
đź’ˇ Usa un utente database read-only per l’API pubblica. Limita i danni in caso di SQL injection.
API REST con Caching Intelligente
| |
Architettura del Sistema di Produzione
flowchart TD
subgraph External["Servizi Esterni"]
GH[GitHub Status API]
AWS[AWS Health API]
CF[Cloudflare Status]
end
subgraph Collectors["Layer di Raccolta"]
C1[Collector Pod 1]
C2[Collector Pod 2]
C3[Collector Pod 3]
end
subgraph DataLayer["Layer Dati"]
PG[(PostgreSQL Primary)]
PGR[(PostgreSQL Replica)]
RD[(Redis Cache)]
end
subgraph API["Layer API"]
LB[Load Balancer]
A1[API Pod 1]
A2[API Pod 2]
A3[API Pod 3]
end
subgraph Processing["Background Jobs"]
AGG[Aggregator Cron]
ALERT[Alert Manager]
end
GH --> C1 & C2 & C3
AWS --> C1 & C2 & C3
CF --> C1 & C2 & C3
C1 & C2 & C3 --> PG
PG --> PGR
PG --> AGG
AGG --> PG
PG --> ALERT
LB --> A1 & A2 & A3
A1 & A2 & A3 --> RD
RD -.->|cache miss| PGR
ALERT -->|webhook| SLACK[Slack]
ALERT -->|email| EMAIL[Email Service]
Errori Comuni e Troubleshooting
1. Rate Limiting delle API Esterne
| |
⚠️ Non fidarti mai dei rate limit documentati. GitHub dice 60 req/h per utenti non autenticati, ma applica limiti più stretti durante picchi di traffico.
2. Drift Temporale nei Check
| |
3. Problemi di Connessione al Database
| |
📝 PostgreSQL chiude le connessioni idle dopo
idle_session_timeout. Con pool di connessioni lunghe, implementa sempre un health check periodico.
Performance e ScalabilitĂ
Indici Ottimizzati per Query Frequenti
| |
Benchmark e Metriche
| |
| |
Conclusioni e Next Steps
Costruire un sistema di monitoraggio uptime robusto richiede attenzione su piĂą fronti:
Quello che abbiamo coperto:
- Schema database ottimizzato per time-series con aggregazioni pre-calcolate
- Collector resiliente con gestione rate limiting adattivo
- API con caching multi-livello
- Deployment containerizzato production-ready
Prossimi passi consigliati:
Alerting intelligente: Integra con PagerDuty/Opsgenie usando soglie dinamiche basate su baseline storiche, non valori fissi
Correlazione incidenti: Quando GitHub va down, spesso impatta CI/CD di altri servizi. Implementa detection di incidenti correlati
Predizione: Con 6+ mesi di dati, puoi trainare modelli semplici per predire degradation basandosi su pattern temporali
SLA Reporting: Genera report automatici mensili per stakeholder, con calcolo preciso di SLA breach e crediti dovuti
đź’ˇ Il vero valore di un sistema di uptime tracking emerge dopo mesi di dati. Resisti alla tentazione di aggiungere feature prima di avere una base solida di dati storici.
Risorse Aggiuntive
- Atlassian Statuspage API Documentation - Reference per integrare altri status page che usano la stessa piattaforma
- PostgreSQL Time-Series Best Practices - Confronto approfondito tra PostgreSQL vanilla e TimescaleDB per workload time-series
- Prometheus Alerting Rules - Pattern per alerting che puoi adattare al tuo sistema custom
- Google SRE Book - Chapter 4: Service Level Objectives - Fondamentali su come definire e misurare SLO/SLI
- GitHub Status API - Documentazione ufficiale dell’API che abbiamo usato come esempio principale
Errori Comuni e Troubleshooting
1. Rate Limiting Non Gestito
L’errore piĂą frequente quando si interrogano API di status è ignorare i limiti di rate.
| |
⚠️ Warning: GitHub Status API non ha rate limit documentati, ma altri provider (come Atlassian) limitano a 100 richieste/minuto. Implementa sempre throttling preventivo.
2. Timezone Hell nei Calcoli di Uptime
| |
đź’ˇ Tip: Salva SEMPRE i timestamp in UTC nel database. Converti in timezone locale solo al momento del rendering nella UI.
3. Memory Leak nel Polling Continuo
| |
4. Schema Database Non Ottimizzato per Query Temporali
| |
📝 Note: Con PostgreSQL, usa
EXPLAIN ANALYZEper verificare che le query usino gli indici. Un dashboard con 90 giorni di dati dovrebbe rispondere in <100ms.
Diagramma di Flusso per Troubleshooting
flowchart TD
A[Problema Rilevato] --> B{Tipo di Errore?}
B -->|429 Too Many Requests| C[Rate Limiting]
C --> C1[Verifica Retry-After header]
C1 --> C2[Implementa backoff esponenziale]
C2 --> C3[Aggiungi request queue]
B -->|Dati Inconsistenti| D[Timezone Issue]
D --> D1[Verifica storage in UTC]
D1 --> D2[Controlla conversioni display]
D2 --> D3[Aggiungi timezone nei log]
B -->|Memory Crescente| E[Memory Leak]
E --> E1[Verifica cleanup interval]
E1 --> E2[Controlla AbortController]
E2 --> E3[Profila con --inspect]
B -->|Query Lente| F[Database Issue]
F --> F1[EXPLAIN ANALYZE]
F1 --> F2{Usa indice?}
F2 -->|No| F3[Crea indice appropriato]
F2 -->|Sì ma lento| F4[Considera materialized view]
C3 --> G[âś… Problema Risolto]
D3 --> G
E3 --> G
F3 --> G
F4 --> G
Conclusioni e Next Steps
Costruire un dashboard di uptime storico non è solo un esercizio tecnico — è un investimento nella comprensione dei tuoi dependency esterni. Dopo mesi di tracking di GitHub e altri servizi, ho imparato che:
I numeri di uptime pubblicati sono ottimistici: Il 99.95% dichiarato raramente corrisponde all’esperienza reale degli utenti. Il tuo sistema di monitoring cattura degradazioni che le status page ufficiali minimizzano.
I pattern si ripetono: Gli incident tendono a concentrarsi in orari specifici (deploy window) e giorni specifici (fine mese per servizi con billing). Questi pattern informano quando schedulare i tuoi deploy critici.
La granularità conta: Polling ogni 5 minuti vs ogni 30 secondi rivela realtà molto diverse. Per servizi critici, il costo computazionale del polling frequente è giustificato.
Roadmap Consigliata
Fase 1 (Settimana 1-2): MVP funzionante
- Polling base per 2-3 servizi critici
- Storage in SQLite (migra dopo)
- Dashboard minimale con uptime percentuale
Fase 2 (Settimana 3-4): Alerting e storicizzazione
- Notifiche su degradazioni
- Migrazione a PostgreSQL con retention policy
- API per integrazioni esterne
Fase 3 (Mese 2): Analytics avanzati
- Correlazione tra incident e tuoi deployment
- Predizione basata su pattern storici
- Report automatici per stakeholder
Fase 4 (Ongoing): Scaling
- Multi-region monitoring per latency check
- Synthetic monitoring (non solo status API)
- Integrazione con incident management interno
Metriche di Successo
| |
đź’ˇ Tip finale: Non aspettare la perfezione. Lancia il tuo MVP, inizia a raccogliere dati, e itera. I dati storici che non raccogli oggi non potrai mai recuperarli.
Risorse Aggiuntive
- Atlassian Statuspage API Documentation - La maggior parte delle status page (inclusa GitHub) usa Statuspage.io. Questa documentazione ti permette di interrogare qualsiasi servizio che lo utilizza
- **[OpenTelemetry Collector Configuration