Il tracing è un metodo di osservazione del flusso delle richieste attraverso un sistema distribuito, in cui ogni fase di elaborazione viene registrata come evento separato con un timestamp. Secondo OpenTelemetry, 2025, un trace combina il percorso completo di una richiesta dal punto di ingresso alla risposta finale, attraversando tutti i microservizi e le chiamate esterne. Ciò consente agli sviluppatori di identificare colli di bottiglia, ritardi e guasti in architetture complesse di backend mobili.
Punti chiave
Il tracing è un metodo di osservazione distribuita in cui ogni richiesta in arrivo viene tracciata attraverso tutti i servizi e componenti del sistema. A differenza delle metriche, che mostrano valori aggregati (tempo medio di risposta, numero di errori), il tracing preserva il contesto completo di una singola richiesta specifica.
Ogni fase di elaborazione — una chiamata al database, una richiesta HTTP a un altro microservizio, l'esecuzione di un'attività in background — viene registrata come unità separata con timestamp, stato e attributi. Secondo Google Dapper (pubblicazione originale del 2010), il tracing consente di localizzare i ritardi nei sistemi distribuiti con la precisione di una singola chiamata.
Il tracing è particolarmente importante per le applicazioni mobili dove il backend è composto da decine di microservizi. Un'azione dell'utente — come l'accesso a un account — può passare attraverso API Gateway, servizio di autenticazione, database e servizio Push. Senza tracing, determinare quale componente sta rallentando la risposta è praticamente impossibile.
L'unità base del tracing è uno span. Ogni span rappresenta un'operazione logica: una richiesta HTTP, una query SQL, una chiamata gRPC, una serializzazione JSON. Uno span contiene un identificatore univoco, identificatore padre, nome dell'operazione, ora di inizio, durata, stato e un insieme di attributi.
Tutti gli span relativi a una stessa richiesta radice vengono raggruppati in un trace. Lo span radice rappresenta il punto di ingresso — una richiesta HTTP dal client mobile all'API. Gli span figli formano un albero, in cui ogni span fa riferimento al suo genitore tramite il campo parent_span_id.
La durata di un trace è uguale alla somma delle durate dei segmenti temporali unici di tutti gli span. Se due span figli vengono eseguiti in parallelo, il loro tempo non viene sommato — questo è fondamentale per analizzare correttamente i ritardi causati da chiamate parallele ai microservizi.
Ogni span può contenere attributi — coppie chiave-valore con meta-informazioni: URL della richiesta, ID utente, versione API, nome host. Gli attributi vengono utilizzati per filtrare e raggruppare i trace. Oltre agli attributi, gli span supportano eventi — timestamp con descrizioni testuali, come "cache miss" o "tentativo di riconnessione".
Il distributed tracing risolve il problema di collegare span creati in processi diversi e su macchine diverse. Il meccanismo si basa sulla propagazione del contesto: quando il servizio A chiama il servizio B, viene aggiunta un'intestazione contenente l'ID del trace corrente e l'ID dello span padre alla richiesta in uscita.
I protocolli standard di propagazione del contesto sono W3C Trace Context (intestazioni traceparent e tracestate) e Zipkin B3 (intestazioni X-B3-TraceId, X-B3-SpanId). W3C Trace Context è stato adottato come standard dal consorzio W3C nel 2021 ed è supportato da tutti i principali provider di telemetria.
Ricevendo la richiesta, il servizio B estrae il trace_id dall'intestazione e crea uno span figlio con quel trace_id. Così, al completamento della richiesta, tutti gli span dei diversi servizi vengono combinati in un unico trace lato collettore. Ciò richiede che ogni servizio sia strumentato con la stessa libreria di tracing.
Nello sviluppo mobile, la propagazione del contesto copre non solo il backend ma anche l'interazione client-server. Un'applicazione mobile può inviare un trace_id nell'intestazione di ogni richiesta API, consentendo di collegare un'azione del client con l'elaborazione lato server. L'SDK OpenTelemetry per iOS e Android supporta la creazione e propagazione automatica del contesto di trace attraverso i client HTTP.
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.context.Context
class TracingInterceptor : Interceptor {
private val tracer: Tracer = OpenTelemetry.getTracer("mobile-app")
override fun intercept(chain: Interceptor.Chain): Response {
val span = tracer.spanBuilder("HTTP POST /api/login")
.setParent(Context.current())
.startSpan()
return chain.proceed(chain.request())
.also { span.end() }
}
}
L'interceptor Kotlin presentato crea uno span per ogni richiesta HTTP al server. Il contesto genitore viene propagato dal codice chiamante tramite Context.current(), consentendo di collegare il tracing lato client con quello lato server.
OpenTelemetry è lo standard de facto per la raccolta di dati di trace. Fornisce un'API unificata per generare span, strumentazione automatica delle librerie più diffuse e un meccanismo flessibile per esportare i dati verso vari backend: Jaeger, Zipkin, Grafana Tempo, Datadog, New Relic.
OpenTelemetry supporta la creazione automatica di span per i framework più diffusi: Spring Boot, Ktor, Flask, Express, gRPC. Lo sviluppatore deve solo aggiungere una dipendenza al progetto e la libreria intercetta automaticamente le richieste in entrata e in uscita. L'auto-strumentazione per Java utilizza un javaagent che modifica il bytecode al volo senza modificare il codice sorgente.
Per le piattaforme mobili, OpenTelemetry fornisce Swift SDK e Kotlin SDK. Creano automaticamente span per richieste di rete (URLSession, OkHttp), operazioni di database (CoreData, Room) e attività in background. Lo sviluppatore può aggiungere span personalizzati per la logica di business.
Gli span raccolti vengono inviati a un collettore tramite il protocollo OTLP (OpenTelemetry Protocol). Il collettore può bufferizzare, filtrare e inoltrare i dati a uno o più sistemi di archiviazione. Secondo la documentazione OpenTelemetry, la latenza tipica dalla generazione di uno span alla sua visualizzazione in una dashboard è di 2–5 secondi quando si utilizza l'esportazione gRPC.
import OpenTelemetryApi
import OpenTelemetrySdk
import URLSessionInstrumentation
let instrumentation = URLSessionInstrumentation()
instrumentation.enable()
let tracer = OpenTelemetry.instance.tracerFactory
.get("mobile-monitoring")
let span = tracer.spanBuilder("fetch-user-profile")
.setAttribute(key: "user.id", value: userId)
.startSpan()
span.end()
Il codice Swift attiva la strumentazione automatica del livello di rete e crea uno span personalizzato per l'operazione di recupero del profilo utente. L'attributo user.id consente successivamente di filtrare i trace per un utente specifico.
Nei sistemi ad alto carico, è impossibile tracciare ogni richiesta — ciò crea un carico inaccettabile su archiviazione e rete. Il campionamento risolve questo problema salvando solo un sottoinsieme di trace. La scelta della strategia influisce direttamente sulla completezza dei dati e sul costo dell'infrastruttura.
La decisione di salvare un trace viene presa al momento della sua creazione — nello span radice. L'approccio più semplice e comune: una percentuale fissa di richieste (ad esempio 5%) viene salvata, il resto viene scartato. Lo svantaggio è che non è possibile garantire che errori rari vengano catturati. Il Probability sampler in OpenTelemetry supporta l'impostazione della probabilità da 0.0 a 1.0.
La decisione viene rimandata fino al completamento di tutti gli span del trace. Un analizzatore valuta se il trace contiene errori, superamento dei tempi o attributi interessanti e solo allora lo salva. Questo approccio richiede il buffering di tutti gli span nel collettore, aumentando il consumo di memoria. Secondo Grafana Labs, il campionamento tail-based è del 40–60% più efficiente in termini di "costo per dato utile" in sistemi con errori rari ma critici.
| Strategia | Vantaggi | Svantaggi |
|---|---|---|
| Probabilità fissa | Semplicità, carico prevedibile | Perde eventi rari |
| Limite di frequenza | Volume dati garantito | Copertura non uniforme |
| Tail-based | Cattura tutti gli errori | Elevato consumo memoria |
| Adattivo | Bilanciamento costo-copertura | Configurazione complessa |
Il logging registra eventi individuali con livelli di gravità (info, warn, error) ma non li collega nel contesto di una singola richiesta. Il tracing, al contrario, crea un albero strutturato di operazioni appartenenti a una richiesta end-to-end. In pratica, questi due approcci non si escludono a vicenda ma si completano.
I log sono efficaci per l'analisi dettagliata di un errore specifico: uno sviluppatore vede il messaggio esatto, lo stack trace e i valori delle variabili. Il tracing risponde alla domanda "perché la richiesta impiega 5 secondi" — mostra quale microservizio o chiamata ha impiegato più tempo. Secondo Honeycomb (2024), i team che utilizzano il tracing insieme al logging trovano la causa principale degli incidenti 2,3 volte più velocemente.
L'approccio moderno — osservabilità — combina tracing, metriche e log in un unico sistema. OpenTelemetry supporta la correlazione tra questi tre segnali: ogni span può contenere collegamenti ai log correlati e le metriche possono essere etichettate con trace_id per approfondire trace specifici.
Domande frequenti
Il monitoraggio mostra metriche aggregate del sistema — tempo medio di risposta, numero di errori al minuto, carico CPU. Il tracing mostra il percorso di una singola richiesta specifica attraverso tutti i componenti. Il monitoraggio risponde "cosa sta succedendo", il tracing risponde "perché sta succedendo".
Per i sistemi di produzione, 1–5% delle richieste è sufficiente con il campionamento head-based. Se il sistema produce raramente errori, si consiglia il campionamento tail-based con focus sulla cattura di tutti i trace di errore. Per gli ambienti di staging, è accettabile tracciare il 100% delle richieste senza limitazioni.
I principali strumenti includono: Jaeger (soluzione di Uber, open source), Grafana Tempo (archiviazione scalabile di trace), Datadog APM, New Relic Distributed Tracing, AWS X-Ray e Honeycomb. Tutti supportano lo standard OpenTelemetry per l'ingestione dei dati.
Sì, il tracing locale funziona all'interno di un singolo processo. L'SDK OpenTelemetry per iOS e Android crea span per operazioni locali: lettura dal database, elaborazione immagini, richieste di rete. Questi trace non sono distribuiti ma sono utili per diagnosticare le prestazioni lato client.
Le moderne librerie di tracing aggiungono meno dell'1% di overhead con il campionamento head-based. OpenTelemetry utilizza l'esportazione asincrona dei dati che non blocca il thread principale. Per i dispositivi mobili, si consiglia di limitare la frequenza di creazione degli span e di utilizzare una strategia di campionamento adattivo.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche