Comprendre la journalisation

Cet article couvre le processus de journalisation, y compris les normes de journalisation, les directives de niveau, les classes, les objectifs et les approximations multistack.

Normes de journalisation

La connexion sous Android est complexe en raison de la combinaison de normes utilisées et combinées dans logcat . Les principales normes utilisées sont détaillées ci-dessous :

Source Exemples Conseils au niveau de la pile
RFC 5424 (norme syslog ) Noyau Linux, nombreuses applications Unix Noyau, démons système
android.util.Log Framework Android + journalisation des applications Framework Android et application système
java.util.logging.Level Journalisation générale en Java application non système

Figure 1 : Normes de niveau de journalisation.

Bien que chacune de ces normes ait un niveau de construction similaire, leur granularité varie. Les équivalents approximatifs entre les normes sont les suivants :

Niveau RFC 5424 RFC 5424 Gravité RFC5424 descriptif android.util.Log java.util.logging.Level
0 Urgence Le système est inutilisable Log.e / Log.wtf SEVERE
1 Alerte Des mesures doivent être prises immédiatement Log.e / Log.wtf SEVERE
2 Critique Conditions critiques Log.e / Log.wtf SEVERE
3 Erreur Conditions d'erreur Log.e SEVERE
4 Avertissement Conditions d'avertissement Log.w WARNING
5 Avis Normal mais significatif Log.w WARNING
6 Info Messagerie d'informations Log.i INFO
7 Déboguer Messages de niveau débogage Log.d CONFIG , FINE
- - Messagerie verbeuse Log.v PLUS FINER / FINEST

Figure 2 : niveaux de journalisation syslog , Android et Java.

Directives relatives au niveau de journalisation

Il existe des lignes directrices existantes données pour chaque norme de journal. Le niveau de journalisation choisi suit la norme appropriée utilisée, comme l'utilisation de la norme syslog pour le développement du noyau.

Les ordres au niveau des journaux, du plus petit au plus grand, sont présentés dans les trois figures ci-dessous :

ERROR Ces journaux sont toujours conservés.
WARN Ces journaux sont toujours conservés.
INFO Ces journaux sont toujours conservés.
DEBUG Ces journaux sont compilés mais supprimés au moment de l'exécution.
VERBOSE Ces journaux ne sont jamais compilés dans une application sauf lors du développement.

Figure 3 : android.util.Log

CONFIG Niveau de message pour les messages de configuration statique
FINE Niveau de message fournissant des informations de traçage
FINER Indique un message de traçage assez détaillé
FINEST Indique un message de traçage très détaillé
INFO Niveau de message pour les messages d'information
SEVERE Niveau de message indiquant une panne grave
WARNING Niveau de message indiquant un problème potentiel

Figure 4 : java.util.Logging.Level .

0 Urgence Le système est inutilisable
1 Alerte Des mesures doivent être prises immédiatement
2 Critique Conditions critiques
3 Erreur Conditions d'erreur
4 Avertissement Conditions d'avertissement
5 Avis Etat normal mais significatif
6 Informatif Messages d'information
7 Déboguer Messages de niveau débogage

Figure 5 : RFC 5424 – Section 6.2.1 .

Journalisation des applications

La journalisation sélective est effectuée avec TAG par la classe android.util.Log en utilisant Log#isLoggable , comme indiqué ci-dessous :

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

Les journaux peuvent être ajustés au moment de l'exécution pour fournir un niveau de journalisation sélectionné, comme indiqué ci-dessous :

adb shell setprop log.tag.FOO_TAG VERBOSE

Les propriétés log.tag.* sont réinitialisées au redémarrage. Il existe également des variantes persistantes qui subsistent lors des redémarrages. Voir ci-dessous:

adb shell setprop persist.log.tag.FOO_TAG VERBOSE

Les vérifications Log#isLoggable laissent des traces de journal dans le code de l'application. Les indicateurs booléens DEBUG contournent les traces de journal à l'aide des optimisations du compilateur définies sur false , comme indiqué ci-dessous :

private final static boolean DEBUG = false;

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

La journalisation peut être supprimée par APK via les ensembles de règles ProGuard par R8 au moment de la compilation. L'exemple suivant supprime tout ce qui se trouve sous la journalisation au niveau INFO pour 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

Ceci est utile pour gérer plusieurs types de build d’application (par exemple, builds de développement et builds de version) où le code sous-jacent est censé être le même, mais les niveaux de journalisation autorisés sont différents. Une politique explicite doit être définie et suivie pour les applications (en particulier les applications système) afin de décider de l'impact des types de build et des attentes de publication sur la sortie des journaux.

Journalisation du système dans le runtime Android (ART)

Il existe plusieurs classes disponibles pour les applications et services système :

Classe But
android.telephony.Rlog Enregistrement radio
android.util.Log Journalisation générale des applications
android.util.EventLog Journalisation des événements de diagnostic de l'intégrateur système
android.util.Slog Journalisation du framework de plateforme

Figure 6 : Classes et objectifs de journaux système disponibles.

Bien que android.util.Log et android.util.Slog utilisent les mêmes normes de niveau de journalisation, Slog est une classe @hide utilisable uniquement par la plateforme. Les niveaux EventLog sont mappés aux entrées du fichier event.logtags dans /system/etc/event-log-tags .

Journalisation native

La journalisation en C/C++ suit le standard syslog avec syslog (2) correspondant au syslog du noyau Linux qui contrôle le tampon printk , et syslog (3) correspondant au logger général du système. Android utilise la bibliothèque liblog pour la journalisation générale du système.

liblog fournit des wrappers pour les groupes de sous-logs en utilisant la forme de macro suivante :

[Sublog Buffer ID] LOG [Log Level ID]

RLOGD , par exemple, correspond à [Radio log buffer ID] LOG [Debug Level] . Les principaux wrappers liblog sont les suivants :

Classe d'emballage Exemples de fonctions
log_main.h ALOGV , ALOGW
log_radio.h RLOGD , RLOGE
log_system.h SLOGI , SLOGW

Figure 7 : wrappers liblog .

Android dispose d'interfaces de niveau supérieur pour la journalisation qui sont préférées à l'utilisation directe liblog , comme indiqué ci-dessous :

Bibliothèque Usage
async_safe Bibliothèque uniquement pour la journalisation à partir d'environnements sécurisés par les signaux asynchrones
libbase Bibliothèque de journalisation qui fournit une interface de flux C++ pour la journalisation, similaire à la journalisation de style Google (glog). libbase est utilisable dans les deux projets externes et est disponible dans les applications utilisant libbase_ndk .

Figure 8 : Bibliothèques de journaux de niveau supérieur.

Approximations multipile

En raison des différences de granularité et de niveau d'intention, il n'existe pas de correspondance claire ou exacte des différentes normes de journalisation. Par exemple, les niveaux java.util.logging.Level et android.util.Log pour les journaux d'erreurs ne correspondent pas 1:1 :

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

Figure 9 : Niveau d'erreur dans la journalisation Java standard par rapport à la journalisation Android.

Dans de tels cas, utilisez la norme individuelle pour déterminer le niveau à appliquer.

Lors du développement d'un système avec plusieurs composants au niveau de la pile, suivez la figure 1 pour déterminer quelle norme utiliser par composant. Pour un guide approximatif de la messagerie de niveau, suivez la figure 2.

Sécurité et confidentialité

N’enregistrez pas d’informations personnelles identifiables (PII). Cela inclut des détails tels que :

  • Adresses mail
  • Numéros de téléphone
  • Des noms

De même, certains détails sont considérés comme sensibles même s’ils ne sont pas explicitement identifiables personnellement.

Par exemple, bien que les informations sur le fuseau horaire ne soient pas considérées comme personnellement identifiables, elles donnent une indication sur l'emplacement approximatif d'un utilisateur.

La politique de journalisation et les détails acceptables doivent être traités dans le cadre de l’examen de la sécurité et de la confidentialité avant la publication.

Journaux de périphérique

L'accès à tous les journaux de l'appareil, y compris l'utilisation android.permission.READ_LOGS , est restreint :

  • Si une application en arrière-plan demande l'accès à tous les journaux de l'appareil, la demande est automatiquement refusée, sauf si l'application :
    • partage l’UID du système.
    • utilise un processus système natif ( UID < APP_UID ).
    • utilise DropBoxManager .
    • accède uniquement au tampon du journal des événements.
    • utilise l'API EventLog .
    • utilise des tests instrumentés.
  • Si une application au premier plan avec READ_LOGS demande l'accès aux journaux de l'appareil, le système invite l'utilisateur à approuver ou à refuser la demande d'accès.