Log Level nello sviluppo di app: definizione, tipi di livelli e configurazione

Autore: IT Sectr Pubblicato: 2026-05-28 Tempo di lettura: 8 min

Log Level — classificazione dei messaggi di log in base al livello di criticità, che consente agli sviluppatori di controllare il volume delle informazioni emesse in diverse fasi dell’applicazione. Secondo Google Android Developers, 2024, la scelta del giusto livello di logging riduce il volume dei log in produzione del 85–95% e accelera la diagnosi degli errori. Ogni livello svolge il suo compito — dal debugging in fase di sviluppo al monitoraggio dei guasti critici in produzione.

Punti chiave

  • Log Level — una scala standardizzata di criticità da Verbose (debugging dettagliato) a Error (guasti critici)
  • Verbose e Debug — livelli per lo sviluppo, disattivati nelle build di produzione per prestazioni
  • Info — messaggi informativi sugli eventi chiave: avvio, autenticazione, navigazione
  • Warn — avvisi su problemi potenziali che non causano un guasto immediato
  • Error — errori critici che richiedono attenzione e analisi immediate dallo sviluppatore

Cos’è Log Level?

Log Level è un attributo di ogni messaggio di log che ne determina l’importanza e l’urgenza di elaborazione. Le piattaforme moderne iOS e Android supportano una scala unificata di 6–7 livelli: dal più dettagliato (Verbose/Trace) al critico (Error/Assert). La scelta del livello determina se il messaggio verrà scritto nel log con la configurazione corrente dell’applicazione.

Il concetto di Log Level si basa sul principio della piramide di criticità: più alto è il livello, meno messaggi vengono emessi a quel livello. Secondo Semaphore CI, 2024, in un’applicazione di produzione la distribuzione è la seguente: Info — 60% dei messaggi, Warn — 25%, Error — 10%, Debug — 5%. I messaggi Verbose devono essere completamente disattivati in produzione.

Ogni piattaforma implementa Log Level attraverso la propria API. Android utilizza android.util.Log con i metodi v(), d(), i(), w(), e(). Apple utilizza OSLog con i livelli default, info, debug, error, fault. Librerie come Timber e CocoaLumberjack aggiungono funzionalità supplementari sopra queste API standard.

Secondo Google I/O 2023, la scelta errata del Log Level è la causa del 40% dei problemi di prestazioni in produzione. Gli sviluppatori lasciano log Debug nelle build di rilascio, causando scritture eccessive su disco e un consumo accelerato della batteria.

Tipi di livelli di logging: da Verbose ad Assert

Verbose (TRACE) — il livello più dettagliato, destinato esclusivamente allo sviluppo. A questo livello vengono emessi tutti i calcoli intermedi, le iterazioni dei cicli e i risultati di ogni passo dell’algoritmo. Su Android, questo livello corrisponde a Log.v(), su iOS — OSLog di tipo debug (prima di iOS 14, veniva utilizzato os_trace).

Debug — messaggi di debug utili durante lo sviluppo e il testing. Contengono informazioni sullo stato degli oggetti chiave, risultati di query SQL e parametri di chiamate API. A differenza di Verbose, i messaggi Debug sono strutturati e semanticamente significativi. Su iOS, questo livello corrisponde a OSLogType.debug.

Info — messaggi informativi sugli eventi normali dell’applicazione: inizializzazione SDK, autenticazione riuscita, apertura schermata, ricezione dati dal server. I messaggi Info non devono contenere dati personali degli utenti e devono essere sicuri per l’analisi in produzione. Su iOS viene utilizzato OSLogType.info, su Android — Log.i().

Warn — avvisi su problemi potenziali. L’applicazione continua a funzionare, ma la situazione richiede attenzione: dimensione della cache vicina al limite, versione API obsoleta, risposta di rete lenta, tentativo di riconnessione. Su Android — Log.w(), su iOS — OSLogType.default (per avvisi).

Error — errori critici in cui l’applicazione non può eseguire l’operazione richiesta ma continua a funzionare: richiesta API fallita, perdita di connessione, errore di scrittura nel database, mancanza di autorizzazioni. Su iOS, per gli errori viene utilizzato OSLogType.error, su Android — Log.e().

Assert (WTF) — il livello più alto, che indica una situazione che “non può accadere.” Utilizzato per registrare bug che violano gli invarianti fondamentali del sistema. Su Android, i messaggi Assert non vengono visualizzati nelle build di rilascio per impostazione predefinita. Su iOS, WTF (What a Terrible Failure) viene gestito tramite OSLogType.fault.

Uso di Log Level su Android

Android Log API — il meccanismo di logging integrato del pacchetto android.util.Log. Fornisce 6 metodi statici: Log.v(), Log.d(), Log.i(), Log.w(), Log.e() e Log.wtf(). Ogni metodo riceve un tag (stringa identificativa della sorgente) e msg (testo del messaggio).

kotlin
class UserRepository {
    companion object {
        private val TAG = "UserRepo"
    }

    suspend fun loadUser(id: String): User {
        Log.d(TAG, "Caricamento utente con id: $id")

        return try {
            val response = api.fetchUser(id)
            Log.i(TAG, "Utente caricato con successo")
            response.toUser()
        } catch (e: Exception) {
            Log.e(TAG, "Errore durante il caricamento dell’utente: ${e.message}")
            throw e
        }
    }
}

Filtraggio per livelli in Android Logcat viene effettuato tramite ADB: adb logcat *:E mostrerà solo i messaggi Error. Nelle build di produzione, tutte le chiamate Log.v() e Log.d() vengono rimosse da ProGuard/R8 quando la minificazione è attivata. Log.i(), Log.w() e Log.e() rimangono, quindi è importante non emettere dati sensibili attraverso questi metodi.

Per il filtraggio personalizzato in fase di esecuzione, Android fornisce Log.isLoggable(tag, level) — un metodo che verifica se il livello specificato è attivato per il tag dato. Ciò consente di attivare dinamicamente la registrazione dettagliata per un modulo specifico senza ricostruire l’applicazione.

Uso di Log Level su iOS e macOS

OSLog — il sistema di logging unificato di Apple, che ha sostituito il deprecato NSLog. OSLog fornisce 5 livelli: debug, info, default (notice), error e fault. Il vantaggio principale è il logging strutturato con supporto per stringhe formattate e filtraggio dinamico tramite console.

swift
import OSLog

let logger = Logger(
    subsystem: "com.example.app",
    category: "network"
)

func fetchData(from url: URL) {
    logger.debug("Starting request to \(url.absoluteString)")

    do {
        let data = try Data(contentsOf: url)
        logger.info("Received \(data.count) bytes")
    } catch {
        logger.error("Request failed: \(error.localizedDescription)")
    }
}

Il sistema di filtraggio di OSLog funziona a livello di sistema operativo. I messaggi Debug vengono scritti solo quando il debugger è collegato o quando l’argomento -com.apple.CoreData.Logging.debug 1 è attivato. I messaggi Info vengono raccolti nella memoria del dispositivo (fino a 512 KB) e sono accessibili tramite Console.app. I messaggi Error e fault vengono scritti continuamente e sono disponibili per la raccolta tramite sistemi di crash reporting.

Una caratteristica importante di OSLog: stringhe formattate con segnaposto. Invece dell’interpolazione di stringhe Swift (che viene sempre valutata, indipendentemente dal livello), OSLog utilizza il formato os_log con %{public}@ e %{private}@ per distinguere i dati sensibili. I parametri privati vengono mascherati nei log di produzione.

Production vs Debug: come configurare il filtraggio dei livelli

La regola principale — un insieme minimo di livelli in produzione: Info, Warn, Error, Assert. Debug e Verbose devono essere disattivati. Il motivo non è tanto la sicurezza quanto le prestazioni: ogni chiamata di log consuma tempo CPU per formattare la stringa, anche se il messaggio non viene emesso.

Formattazione pigra delle stringhe

Ottimizzazione critica — non utilizzare mai l’interpolazione di stringhe nelle chiamate di log. Se la stringa viene costruita prima della chiamata log(), il tempo CPU viene sprecato anche quando il livello è disattivato. Utilizza la formattazione pigra tramite lambda o condizioni di guardia.

Su Android, il metodo Log.isLoggable() serve a questo scopo; su OSLog, le stringhe formattate native con segnaposto sono supportate. Timber per Android risolve il problema tramite timber.log.Tree con verifica del livello all’interno dell’albero.

Cambio dinamico del livello al volo

Remote Log Level — una pratica in cui il livello di logging viene controllato dal server tramite Firebase Remote Config o un servizio simile. Se si verifica un errore complesso in produzione, lo sviluppatore può attivare da remoto il logging Debug per un modulo specifico sui dispositivi di un gruppo selezionato di utenti.

Secondo Firebase, 2024, questa pratica riduce il tempo di diagnosi dei bug rari del 60% e consente di ottenere un quadro completo del problema senza installare una build di debug. La limitazione principale — il logging viene attivato solo al successivo avvio dell’applicazione dopo aver ricevuto la configurazione.

Filtraggio automatico per tipo di build

BuildConfig.DEBUG su Android e #if DEBUG su Swift sono meccanismi standard di compilazione condizionale che disattivano i livelli di debug nelle build di rilascio. Per un’architettura pulita, si consiglia di spostare la selezione del Log Level in un contenitore DI o in una factory di logger per non appesantire la logica di business con direttive condizionali.

Best practice nella scelta del livello di logging

Prima regola — ogni chiamata di log dovrebbe rispondere alla domanda “chi, cosa, quando.” Chi — il componente o modulo (tag su Android, category su iOS). Cosa — l’evento specifico o il cambiamento di stato. Quando — il timestamp, aggiunto automaticamente dal sistema di logging.

Seconda regola — non registrare dati sensibili attraverso Info e superiori. Password, token, email, numeri di telefono, coordinate geografiche precise sono categoricamente vietati in qualsiasi log che finisca in produzione. Se necessario, utilizza il mascheramento: “email: us***@example.com.”

Terza regola — il livello Warn è responsabilità dello sviluppatore, Error — del team. Warn significa “qui c’è un problema potenziale, tienilo d’occhio.” Error significa “qui c’è un problema, correggilo.” Non utilizzare Error per situazioni previste e gestite (ad esempio, un errore API 404).

Quarta regola — coerenza. L’intero progetto dovrebbe utilizzare convenzioni di denominazione unificate per tag e categorie. Si raccomanda ClassName.methodName per i tag Android e module.subsystem per le categorie iOS. Ciò consente di filtrare rapidamente i log per componente.

Quinta regola — testa i tuoi log. Nei test unitari, verifica che il Log Level corretto venga chiamato in scenari specifici. Esistono liberie mock di logging per questo scopo: Mockito per Android, Cuckoo per iOS. Verificare i livelli nei test impedisce la fuga di messaggi di debug in produzione.

Domande frequenti

Cosa succede se si lasciano log Debug in produzione?

Consumo accelerato della batteria e scritture eccessive su disco. Ogni log Debug formatta una stringa e scrive dati nel buffer. Su dispositivi con memoria Flash, ciò accelera l’usura dello storage. Inoltre, i log Debug possono contenere dati sensibili che non dovrebbero essere visibili in produzione.

Quale Log Level dovrei usare per registrare le richieste di rete?

Debug — per il corpo della richiesta e risposta, intestazioni e codice di stato. Info — per il fatto della richiesta completata (URL, metodo, durata). Error — per richieste fallite con codici 4xx/5xx. Non utilizzare mai Verbose per i log di rete in produzione.

Qual è la differenza tra OSLogType.default e OSLogType.info?

OSLogType.default (livello notice) — messaggi di importanza media, salvati nel log di sistema e visibili in Console.app. OSLogType.info — messaggi tecnici, non salvati permanentemente, disponibili solo durante la profilazione attiva tramite Instruments.

Come gestisce ProGuard le chiamate Log su Android?

R8/ProGuard rimuove Log.v() e Log.d() quando la minificazione è attivata nelle build di rilascio. Log.i(), Log.w() e Log.e() vengono preservati. Per la rimozione completa di tutti i log, è necessaria una regola personalizzata -assumenosideeffects class android.util.Log con tutti i livelli specificati.

Ogni metodo dovrebbe registrare il suo inizio e la sua fine?

No — la registrazione eccessiva compromette la leggibilità e le prestazioni. Registra l’ingresso solo nei metodi complessi o asincroni. Per i metodi sincroni, un singolo log al punto di ritorno o di errore è sufficiente. Utilizza il livello Debug per la tracciatura delle chiamate.

Riepilogo

  • Log Level — scala di criticità da Verbose ad Assert che determina la visibilità di ogni messaggio di log
  • Verbose e Debug — destinati allo sviluppo e devono essere disattivati nelle build di produzione
  • Info — eventi chiave dell’applicazione, sicuri per l’analisi in produzione
  • Warn — problemi potenziali che non richiedono correzione immediata
  • Error — guasti critici che richiedono l’intervento del team di sviluppo
  • Android Log API utilizza tag + level; OSLog su iOS utilizza subsystem + category + level
  • Formattazione pigra e compilazione condizionale sono tecniche chiave per ottimizzare il logging in produzione

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.

Discuti il progetto

Leggi anche