Structured Logging è un approccio alla registrazione dei log in cui ogni messaggio è rappresentato in un formato leggibile dalla macchina con coppie chiave-valore, anziché come testo non strutturato. A differenza delle stringhe piatte, i log strutturati contengono metadati: timestamp, livello, modulo, ID richiesta — e possono essere indicizzati da sistemi di analisi. Secondo O'Reilly Effective Logging, il passaggio a formati strutturati riduce i tempi di ricerca degli incidenti da ore a minuti grazie alla possibilità di filtrare per campi. Questo è lo standard de facto nello sviluppo mobile e server moderno: JSON e logfmt consentono di elaborare i log con programmi, non con gli occhi.
Punti chiave
Structured Logging è un metodo di registrazione dei log in cui ogni messaggio contiene campi nominati con valori tipizzati. Invece di una stringa come User 42 logged in from device ABC, un log strutturato appare come un insieme di campi: user_id=42, event=login, device_id=ABC, timestamp=2026-07-04T10:30:00Z.
Il vantaggio principale dei log strutturati rispetto a quelli testuali è la possibilità di elaborazione programmatica. L’analisi dei log testuali richiede espressioni regolari e ipotesi sul formato della stringa. I log strutturati vengono analizzati senza perdite: ogni campo ha un tipo e un nome noti, consentendo di costruire query come trovare tutti gli errori di autenticazione nell’ultima ora per l’utente 42 senza elaborazione aggiuntiva.
Secondo Honeycomb.io (2023), i team che utilizzano structured logging in produzione rilevano gli incidenti in media 4 volte più velocemente rispetto ai team che si affidano a log testuali e grep.
Structured Logging supporta diversi formati di serializzazione. La scelta del formato dipende dall’infrastruttura: JSON è comodo per l’integrazione con Elasticsearch e sistemi cloud, logfmt per la visualizzazione in console tramite tail e grep, Protocol Buffers per sistemi ad alte prestazioni con limiti di larghezza di banda.
| Formato | Esempio | Quando usarlo |
|---|---|---|
| JSON | {"event":"login","user_id":42} | ELK Stack, raccoglitori cloud, microservizi |
| Logfmt | event=login user_id=42 duration_ms=150 | Console, tail, heroku logs |
| MessagePack | Equivalente binario di JSON | Sistemi ad alto carico, IoT |
JSON è il formato più comune per i log strutturati. È nativamente supportato da tutti i sistemi di raccolta: Logstash, Fluentd, Amazon CloudWatch, Google Cloud Logging. I log JSON sono facili da leggere per gli umani e da analizzare con qualsiasi linguaggio di programmazione senza librerie aggiuntive. Lo svantaggio principale è la verbosità: ogni coppia chiave-valore richiede virgolette e due punti, aumentando il volume dei dati memorizzati del 30–50% rispetto a logfmt.
Logfmt è stato sviluppato in Heroku per la visibilità in console. È più compatto di JSON, mantiene la leggibilità umana e può essere facilmente elaborato con cut e awk. Esempio: ts=2026-07-04T10:30:00Z level=error module=api status=500. Logfmt non richiede l’escape della maggior parte dei caratteri ed è adatto per il logging su stdout nei container.
Nelle applicazioni mobili, Structured Logging risolve tre problemi chiave: trovare le cause dei crash senza riproduzione sul dispositivo, tracciare le sessioni utente e analizzare le prestazioni per versione dell’app.
I log testuali sui dispositivi mobili sono quasi inutili — uno sviluppatore non può fare grep sui log del dispositivo dell’utente. I log strutturati vengono inviati a sistemi cloud (Firebase, Sentry, Datadog) e lì indicizzati. Si può costruire una query come mostra tutti i crash con iOS 17.4, versione app 3.2, nel modulo checkout e ottenere una selezione precisa in secondi.
Secondo Sentry (2024), le app che utilizzano breadcrumbs strutturati hanno il 60% in più di contesto in ogni report di crash rispetto alle app che registrano solo il testo dell’errore. Questo influisce direttamente sulla velocità di correzione dei bug.
ELK Stack — Elasticsearch, Logstash, Kibana — rimane l’infrastruttura standard per lavorare con log strutturati. Logstash riceve i log in JSON, li trasforma e li invia a Elasticsearch per l’indicizzazione, Kibana fornisce un’interfaccia visiva per query e dashboard.
Per le applicazioni mobili, le soluzioni cloud sono popolari: Firebase Crashlytics con log personalizzati, Sentry con breadcrumbs, Datadog con monitoraggio APM. Accettano log strutturati direttamente dall’SDK mobile e non richiedono la distribuzione di un backend proprio. Firebase offre un pacchetto gratuito per i report di crash, Sentry aggiunge tracing distribuito e Datadog si integra con APM per tracciare le prestazioni delle richieste sia sul client che sul server contemporaneamente.
Grafana Loki — un’alternativa a Elasticsearch ottimizzata per i log. Loki non indicizza il contenuto dei messaggi per impostazione predefinita ma utilizza etichette (labels) per il filtraggio. Ciò è significativamente più economico in termini di archiviazione e più veloce per query su un insieme fisso di campi.
// Logging strutturato tramite Swift Logger in JSON
struct StructuredLog {
let event: String
let attributes: [String: Any]
let level: String
func serialize() -> String {
var base = "event=\(event) level=\(level)"
for (key, value) in attributes {
base += " \(key)=\(value)"
}
return base
}
}
La prima regola del logging strutturato: ogni messaggio deve contenere un identificatore di richiesta o sessione. Senza contesto, un singolo log è inutile — è impossibile sapere a quale utente o richiesta appartiene. Aggiungi un correlation ID all’inizio della sessione e passalo attraverso tutti i livelli dell’applicazione.
La seconda regola: tipizzazione dei campi. I campi numerici (duration_ms, status_code, retry_count) devono essere trasmessi come numeri, non come stringhe. Elasticsearch e sistemi simili indicizzano numeri e stringhe in modo diverso: i numeri possono essere aggregati (media, mediana, percentile), le stringhe supportano la ricerca full-text. Una tipizzazione errata impedisce la creazione di dashboard analitiche.
La terza regola: evita oggetti annidati. I log JSON con profondità di annidamento superiore a 2 livelli sono difficili da filtrare e visualizzare. Invece di {"user": {"name": "Alice", "role": "admin"}}, usa chiavi piatte: user_name=Alice user_role=admin.
// Logging strutturato su Android tramite Timber + logfmt
class StructuredTree : Timber.Tree() {
override fun log(priority: Int, tag: String?,
message: String?, t: Throwable?) {
val level = priorityToLevel(priority)
val logfmt = "level=$level tag=$tag message=$message"
sendToRemote(logfmt)
}
}
L’insieme minimo di campi per ogni messaggio strutturato: timestamp in formato ISO 8601, level (debug/info/warn/error/fatal), logger (nome del modulo o classe), message (descrizione leggibile dell’evento). Inoltre: correlation_id, user_id (se noto), version (versione dell’app), platform (iOS/Android), environment (dev/staging/prod).
Senza correlation_id, i log strutturati diventano un insieme di record scollegati che non possono essere legati in un unico scenario utente. Genera un UUID all’avvio dell’applicazione e aggiungilo a tutti i log di sessione. In pratica, il correlation_id deve essere trasmesso attraverso tutti i livelli: dagli eventi UI alle richieste di rete e ai task in background — altrimenti alcuni log rimarranno senza contesto e non parteciperanno all’analisi. Con il monitoraggio end-to-end, un singolo UUID consente di raccogliere il quadro completo del percorso dell’utente.
Su iOS, il logging strutturato può essere implementato tramite un wrapper su os_log che serializza i campi in formato logfmt. Su Android, tramite Timber con un Tree personalizzato che converte i messaggi in JSON o logfmt prima di inviarli al server.
import OSLog
struct StructuredLogger {
let subsystem: String
let category: String
func log(level: OSLogType,
event: String,
context: [String: Any]) {
let oslogger = Logger(
subsystem: subsystem,
category: category
)
let fields = context.map {
"\($0.key)=\($0.value)"
}.joined(separator: " ")
oslogger.log(level: level,
"\(event) \(fields)")
}
}
La scelta tra log strutturati e testuali dipende dalla fase del progetto. Nelle fasi iniziali dello sviluppo, i log testuali sono più semplici e veloci — lo sviluppatore scrive un messaggio direttamente senza wrapper aggiuntivi. Ma quando il progetto supera i limiti di un singolo team o server, i log strutturati diventano obbligatori.
| Criterio | Log testuali | Log strutturati |
|---|---|---|
| Leggibilità | Alta in console | Media (richiede pretty-print) |
| Ricerca | grep per sottostringa | Query per campi e valori |
| Aggregazione | Non supportata | Media, mediana, percentili |
| Integrazione | Richiede analisi | Nativa in ELK/Loki/Datadog |
| Volume di archiviazione | Minore (senza metadati) | Maggiore (campi + valori) |
Domande frequenti
Per l’invio al server, usa JSON — è nativamente supportato da Firebase Crashlytics, Sentry e Datadog. Per la visualizzazione locale nei log di Xcode o Android Studio, usa logfmt — è più compatto e leggibile senza formattazione.
Sì, i log strutturati sul client consentono di aggiungere contesto a ogni report di crash: versione del SO, stato della rete, ultime azioni dell’utente. Senza breadcrumbs strutturati, un report di crash contiene solo lo stack delle chiamate senza lo scenario utente.
Logfmt è più compatto (30–50% di volume in meno) e più facile da leggere in un terminale. JSON supporta oggetti e array annidati ma richiede l’escape delle virgolette. La scelta dipende dall’infrastruttura: per ELK — JSON, per la visualizzazione in console — logfmt.
Crea una singola istanza di UUID all’avvio dell’applicazione, memorizzala in un singleton o contenitore DI e passala a tutti i logger tramite il costruttore. Alternativa — usa l’archiviazione locale del thread o Continuation Local Storage nelle coroutine Kotlin.
Si può, ma non è raccomandato — mescolando si perde la capacità di indicizzazione automatica. Se alcuni log sono testuali, devono essere analizzati con espressioni regolari, riducendo le prestazioni e l’affidabilità della ricerca. È meglio migrare tutti i log al formato strutturato.
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