La tua applicazione è in produzione. Funziona. Poi, senza preavviso, inizia a rallentare. Qualche utente si lamenta. Il server non dà segni di sofferenza, il database risponde, ma il carrello impiega 8 secondi a caricarsi. Apri i log: centinaia di righe, tutte mischiate, nessuna struttura. Hai qualche alert sul carico CPU, ma non dicono niente di utile. Ecco: hai monitoraggio, ma non osservabilità.
Noi, di Meteora Web, lo vediamo spesso nei progetti che ci arrivano. Un cliente ha installato Nagios, ha settato soglie di RAM, e pensa di essere a posto. Poi arriva il primo collo di bottiglia e non capisce da dove parte. L'observability non è uno strumento: è un approccio. Si regge su tre pilastri. Se ne manca uno, vedi solo metà del problema.
Questa guida ti spiega cosa sono log, metriche e trace, perché servono tutti e tre e come integrarli in un'applicazione reale. Niente teoria astratta: esempi PHP, Prometheus e OpenTelemetry che puoi usare subito.
I tre pilastri dell'observability: perché non basta un ping
Observability è la capacità di capire lo stato interno di un sistema a partire dai dati che produce. Non significa solo sapere se il server è vivo, ma poter rispondere a domande come: perché questa richiesta è lenta? o quale servizio sta perdendo pacchetti?
Tre tipi di dati ti danno la risposta:
- Log: registrazioni testuali di eventi discreti.
- Metriche: aggregazioni numeriche nel tempo.
- Trace: percorsi completi di una richiesta attraverso i servizi.
Ognuno risponde a una domanda diversa. Usarli insieme è come avere cronologia, bollettino e mappa allo stesso tempo.
Log: la cronaca degli eventi
Un log dice cosa è successo e quando. Ogni riga è un evento: un errore, un accesso, un pagamento. Ma senza struttura, i log sono rumore.
L'errore comune: scrivere frasi informali come "Errore nel login". Aiuta un umano, ma non un sistema di analisi. Serve un formato strutturato (JSON, key-value) che permetta di filtrare e aggregare.
Esempio pratico (PHP con Monolog):
<?php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\JsonFormatter;
$log = new Logger('app');
$handler = new StreamHandler('/var/log/app.log', Logger::WARNING);
$handler->setFormatter(new JsonFormatter());
$log->pushHandler($handler);
$log->error('Pagamento fallito', [
'order_id' => 12345,
'user_id' => 678,
'amount' => 49.99,
'gateway' => 'stripe',
'error_code' => 'card_declined'
]);
?>Così puoi cercare tutti gli errori di pagamento per gateway o per importo, anche con strumenti come Grafana Loki.
Metriche: i numeri che contano
Una metrica è un numero misurato in un istante: richieste al secondo, memoria usata, latenza media. Dice quanto e con che tendenza.
Le metriche sono aggregabili (count, sum, avg, percentili) e hanno un timestamp. Servono per soglie di allarme e per vedere pattern nel tempo.
Esempio pratico (Prometheus client in PHP):
<?php
use Prometheus\CollectorRegistry;
use Prometheus\Storage\InMemory;
use Prometheus\RenderTextFormat;
$registry = new CollectorRegistry(new InMemory());
$counter = $registry->registerCounter(
'app',
'http_requests_total',
'Total number of HTTP requests',
['method', 'endpoint']
);
$counter->incBy(1, ['GET', '/api/orders']);
// Esporre endpoint /metrics per Prometheus
$renderer = new RenderTextFormat();
echo $renderer->render($registry->getMetricFamilySamples());
?>Prometheus scansiona l'endpoint ogni 15 secondi. Con Grafana costruisci dashboard e alert. La domanda a cui rispondi: il sistema sta peggiorando?
Trace: il viaggio della richiesta
Un trace segue una richiesta attraverso tutti i servizi coinvolti. Ogni step è uno span con durata. Dice dove si perde tempo.
Senza trace, in un'architettura a microservizi non sai se il collo di bottiglia è nel gateway, nel servizio A, o nel database.
Esempio pratico (OpenTelemetry in PHP):
<?php
use OpenTelemetry\API\Globals;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\SDK\Trace\TracerProviderFactory;
$tracer = Globals::tracerProvider()->getTracer('app');
$span = $tracer->spanBuilder('process-order')
->setSpanKind(SpanKind::KIND_INTERNAL)
->startSpan();
try {
// logica di business
$span->setAttribute('order_id', 12345);
usleep(50000); // simula lavoro
} finally {
$span->end();
}
?>Esporta gli span verso Jaeger o Zipkin. Così vedi che la richiesta impiega 200ms nel gateway, 150ms nel servizio ordini, 5ms nel database. Il problema è nel gateway, non nel DB.
Integrare i tre pilastri in una applicazione reale
Non basta installare tre librerie. Devono parlarsi. Ad esempio, in un log strutturato puoi includere il trace ID e un correlation ID per collegare eventi a una specifica richiesta. Così, quando vedi una latenza anomala in una metrica, puoi aprire il trace corrispondente e cercare nei log l'errore.
Un pattern pratico: usa OpenTelemetry per generare trace, passa il trace ID nel logger, e arricchisci le metriche con tag (es. trace_id se supportato).
<?php
// Recupera trace ID dal contesto OpenTelemetry
$span = OpenTelemetry\API\Globals::tracerProvider()->getTracer('app')->spanBuilder('handle-request')->startSpan();
$traceId = $span->getContext()->getTraceId();
$log->info('Richiesta ricevuta', ['trace_id' => $traceId]);
// ...
?>Errori comuni e come evitarli
- Log non strutturati: se usi
echo "Error"osyslogsenza formato, i tool di analisi non possono processarli. Soluzione: adotta subito JSON. - Metriche senza contesto: una metrica
http_requests_totalsenza label (method, endpoint) non dice quale percorso è lento. Aggiungi sempre label. - Tracciamento solo del servizio principale: se non propaghi il contesto (per es. con intestazioni HTTP), i trace sono frammentati. Usa middleware di propagazione automatica (OpenTelemetry ha pacchetti per Laravel, Symfony, ecc.).
- Ignorare i costi: raccogliere tutto costa risorse (CPU, storage, trasferimento). Noi, di Meteora Web, consigliamo di iniziare con ciò che è critico: endpoint di pagamento, login, checkout. Poi espandere.
In sintesi — cosa fare adesso
- Struttura i log: passa a JSON con Monolog o qualsiasi logger che supporti formatter. Includi contesto (user ID, order ID, trace ID).
- Aggiungi metriche chiave: installa Prometheus e registra almeno latenza (percentili 50/90/99), tasso di errore e throughput per le API principali.
- Traccia le richieste critiche: integra OpenTelemetry nel tuo backend e invia trace a un backend compatibile (Jaeger, Tempo). Usa la propagazione del contesto anche tra microservizi.
- Crea una dashboard unica: su Grafana collega log (Loki), metriche (Prometheus) e trace (Tempo). Usa il correlation per saltare da un grafico di latenza al trace e poi al log.
- Misura il costo: tieni traccia dello storage dei log e delle metriche. Imposta retention policies. Non raccogliere dati che non userai.
L'observability non è un progetto da completare: è un'abitudine. Ogni nuova rotta, ogni nuovo servizio deve produrre i tre pilastri fin dal giorno zero. Se vuoi approfondire come gestire dati strutturati in produzione, leggi la nostra guida su MongoDB vs SQL. Per il resto, inizia oggi con un endpoint di health check che espone metriche e trace: vedrai la differenza al primo incidente.
Sponsored Protocol