Informazioni sul logging

Questo articolo illustra la procedura di registrazione, inclusi standard dei log, linee guida per i livelli, classi, finalità e approssimazioni multistack.

Standard di log

Il logging in Android è complesso a causa della combinazione di standard utilizzati in logcat. Di seguito sono descritti i principali standard utilizzati:

Source Esempi Indicazioni a livello di stack
RFC 5424 (syslog standard) Kernel Linux, molte app Unix Kernel, demoni di sistema
android.util.Log Framework Android + logging delle app Framework e app di sistema Android
java.util.logging.Level Log generali in Java app non di sistema

Figura 1: standard dei livelli di log.

Sebbene ciascuno di questi standard abbia una struttura di livello simile, la granularità varia. Gli equivalenti approssimativi tra gli standard sono i seguenti:

Livello RFC 5424 Gravità RFC 5424 Descrizione di RFC 5424 android.util.Log java.util.logging.Level
0 Emergenza Il sistema non è utilizzabile Log.e / Log.wtf SEVERE
1 Avviso È necessario intervenire immediatamente Log.e / Log.wtf SEVERE
2 Critico Condizioni critiche Log.e / Log.wtf SEVERE
3 Errore Condizioni di errore Log.e SEVERE
4 Avviso Condizioni di avviso Log.w WARNING
5 Avviso Normale, ma significativo Log.w WARNING
6 Informazioni Messaggistica informativa Log.i INFO
7 Debug Messaggi a livello di debug Log.d CONFIG, FINE
- - Messaggistica dettagliata Log.v FINER/FINEST

Figura 2: livelli di logging di syslog, Android e Java.

Linee guida per i livelli di log

Esistono linee guida per ogni standard di log. Il livello di log scelto segue lo standard appropriato in uso, ad esempio lo standard syslog per lo sviluppo del kernel.

Gli ordini dei livelli di log, dal più basso al più alto, sono mostrati nelle tre figure seguenti:

ERROR Questi log vengono sempre conservati.
WARN Questi log vengono sempre conservati.
INFO Questi log vengono sempre conservati.
DEBUG Questi log vengono compilati, ma rimossi in fase di esecuzione.
VERBOSE Questi log non vengono mai compilati in un'app, tranne durante lo sviluppo.

Figura 3: android.util.Log

CONFIG Livello di messaggio per i messaggi di configurazione statica
FINE A livello di messaggio fornisce informazioni di tracciamento
FINER Indica un messaggio di tracciamento abbastanza dettagliato
FINEST Indica un messaggio di monitoraggio molto dettagliato
INFO Livello di messaggio per i messaggi informativi
SEVERE Livello del messaggio che indica un errore grave
WARNING Livello del messaggio che indica un potenziale problema

Figura 4: java.util.Logging.Level.

0 Emergenza Il sistema non è utilizzabile
1 Avviso È necessario intervenire immediatamente
2 Critico Condizioni critiche
3 Errore Condizioni di errore
4 Avviso Condizioni di avviso
5 Avviso Condizione normale, ma significativa
6 Informative Messaggi informativi
7 Debug Messaggi a livello di debug

Figura 5: RFC 5424 - Sezione 6.2.1.

Logging delle app

Il logging selettivo viene eseguito con la classe TAG per android.util.Log utilizzando Log#isLoggable, come mostrato di seguito:

if (Log.isLoggable("FOO_TAG", Log.VERBOSE)) {
 Log.v("FOO_TAG", "Message for logging.");
}

I log possono essere ottimizzati in fase di runtime per fornire un livello selezionato di logging, come mostrato di seguito:

adb shell setprop log.tag.FOO_TAG VERBOSE

Le proprietà log.tag.* vengono reimpostate al riavvio. Esistono anche varianti permanenti che rimangono anche dopo i riavvii. Vedi di seguito:

adb shell setprop persist.log.tag.FOO_TAG VERBOSE

I controlli di Log#isLoggable lasciano tracce di log nel codice dell'app. I flag booleani DEBUG ignorano le tracce dei log utilizzando le ottimizzazioni del compilatore impostate su false, come mostrato di seguito:

private final static boolean DEBUG = false;

… If (DEBUG) { Log.v("FOO_TAG", "Extra debug logging."); }

La registrazione può essere rimossa su base APK tramite i set di regole di ProGuard da R8 al compilatore. L'esempio seguente rimuove tutto ciò che si trova al di sotto del livello INFO del logging per android.util.Log:

# This allows proguard to strip isLoggable() blocks containing only <=INFO log
# code from release builds.
-assumenosideeffects class android.util.Log {
  static *** i(...);
  static *** d(...);
  static *** v(...);
  static *** isLoggable(...);
}
-maximumremovedandroidloglevel 4

Questo è utile per gestire più tipi di build dell'app (ad esempio build di sviluppo e build di release) in cui il codice sottostante dovrebbe essere lo stesso, ma i livelli di log consentiti sono diversi. Per le app (in particolare quelle di sistema) deve essere impostato e rispettato un criterio esplicito per decidere in che modo i tipi di build e le aspettative di rilascio influiscono sull'output del log.

Registrazione di sistema in Android Runtime (ART)

Esistono diversi tipi di classi disponibili per le app e i servizi di sistema:

Corso Finalità
android.telephony.Rlog Registrazione radio
android.util.Log Logging generale dell'app
android.util.EventLog Registrazione degli eventi diagnostici dell'integratore di sistema
android.util.Slog Logging del framework della piattaforma

Figura 6: classi e finalità dei log di sistema disponibili.

Sebbene android.util.Log e android.util.Slog utilizzino gli stessi standard di livello di log, Slog è una classe @hide utilizzabile solo dalla piattaforma. I livelli EventLog vengono mappati alle voci del file event.logtags in /system/etc/event-log-tags.

Logging nativo

La registrazione in C/C++ segue lo standard syslog, con syslog(2) corrispondente al kernel Linux syslog che controlla il buffer printk e syslog(3) corrispondente al logger di sistema generale. Android utilizza la libreria liblog per il logging di sistema generale.

liblog fornisce wrapper per i gruppi di blog secondari utilizzando il seguente formato della macro:

[Sublog Buffer ID] LOG [Log Level ID]

RLOGD, ad esempio, corrisponde a [Radio log buffer ID] LOG [Debug Level]. I principali wrapper liblog sono i seguenti:

Classe wrapper Funzioni di esempio
log_main.h ALOGV, ALOGW
log_radio.h RLOGD, RLOGE
log_system.h SLOGI, SLOGW

Figura 7: wrapper liblog.

Android dispone di interfacce di livello superiore per la registrazione che sono preferite all'uso direttoliblog, come mostrato di seguito:

Raccolta Utilizzo
async_safe Libreria solo per la registrazione da ambienti sicuri per gli indicatori asincroni
libbase Libreria di logging che fornisce un'interfaccia di streaming C++ per la registrazione, simile alla registrazione in stile Google (glog). libbase è utilizzabile sia nei progetti esterni sia nelle app che utilizzano libbase_ndk.

Figura 8: librerie di log di livello superiore.

Approssimazioni multistack

A causa delle differenze di granularità e intent di livello, non esistono corrispondenze chiare o precise tra i diversi standard di logging. Ad esempio, i livelli java.util.logging.Level e android.util.Log per i log di errore non corrispondono 1:1:

java.util.Logging.Level android.util.Log
GRAVE Log.wtf
GRAVE Log.e

Figura 9: livello di errore nella registrazione Java standard rispetto alla registrazione Android.

In questi casi, utilizza il singolo standard per determinare quale livello applicare.

Durante lo sviluppo del sistema con più componenti a livello di stack, segui la Figura 1 per determinare quale standard utilizzare per componente. Per una guida approssimativa ai messaggi di livello, segui la Figura 2.

Sicurezza e privacy

Non registrare informazioni che consentono l'identificazione personale (PII). Sono inclusi dettagli quali:

  • Indirizzi email
  • Numeri di telefono
  • Nomi.

Analogamente, alcuni dettagli sono considerati sensibili anche se non consentono esplicitamente l'identificazione personale.

Ad esempio, anche se le informazioni sul fuso orario non sono considerate informazioni che consentono l'identificazione personale, forniscono un'indicazione della posizione approssimativa di un utente.

Le norme relative ai log e i dettagli accettabili devono essere gestiti nell'ambito della revisione della sicurezza e della privacy prima del rilascio.

Log del dispositivo.

L'accesso a tutti i log del dispositivo, incluso l'utilizzo di android.permission.READ_LOGS, è limitato:

  • Se un'app in background richiede l'accesso a tutti i log del dispositivo, la richiesta viene automaticamente rifiutata, a meno che l'app:
    • Condivide l'UID di sistema.
    • Utilizza un processo di sistema nativo (UID < APP_UID).
    • Usa DropBoxManager.
    • Accede solo al buffer del log eventi.
    • Utilizza l'API EventLog.
    • Utilizza i test con strumenti.
  • Se un'app in primo piano con READ_LOGS richiede l'accesso ai log del dispositivo, il sistema chiede all'utente di approvare o rifiutare la richiesta di accesso.