Comprendre la journalisation

Cet article décrit le processus de journalisation, y compris les normes, les consignes de niveau, les classes, les objectifs et les approximations multistack.

Normes de journalisation

La journalisation dans Android est complexe en raison du mélange de normes utilisées et combinées dans logcat. Les principales normes utilisées sont détaillées ci-dessous :

Source Exemples Conseils sur les niveaux de pile
RFC 5424 (syslog standard) Noyau Linux, nombreuses applications Unix Noyau, daemons système
android.util.Log Journalisation du framework Android et de l'application Framework Android et application système
java.util.logging.Level Journalisation générale dans Java application non système

Figure 1 : Normes de niveau de journalisation.

Bien que ces normes aient une structure de niveau similaire, elles varient en termes de précision. Voici les équivalents approximatifs entre les normes :

Niveau RFC 5424 Gravité RFC 5424 Description de la norme RFC 5424 android.util.Log java.util.logging.Level
0 Urgence Le système est inutilisable Log.e / Log.wtf SEVERE
1 Alerte Action immédiate requise 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 important Log.w WARNING
6 Infos Messages d'information Log.i INFO
7 Déboguer Messages de niveau "Débogage" Log.d CONFIG, FINE
- - Messages détaillés Log.v FINER/FINEST

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

Consignes concernant les niveaux de journalisation

Des consignes existantes sont fournies pour chaque norme de journal. Le niveau de journalisation choisi suit la norme appropriée utilisée, comme la norme syslog pour le développement du noyau.

Les ordres de niveau de journalisation, du plus faible au plus élevé, sont indiqué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 lors de l'exécution.
VERBOSE Ces journaux ne sont jamais compilés dans une application, sauf pendant le 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 un échec 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 Action immédiate requise
2 Critique Conditions critiques
3 Erreur Conditions d'erreur
4 Avertissement Conditions d'avertissement
5 Avis État normal, mais important
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 à l'aide de 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 spécifique, 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 restent en place après les redémarrages. Voir ci-dessous :

adb shell setprop persist.log.tag.FOO_TAG VERBOSE

Les vérifications Log#isLoggable laissent des traces de journaux dans le code de l'application. Les indicateurs booléens DEBUG contournent les traces de journaux à l'aide d'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 pour chaque APK à l'aide des ensembles de règles ProGuard par R8 au moment de la compilation. L'exemple suivant supprime tous les journaux de niveau inférieur à 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

Cela est utile pour gérer plusieurs types de compilation d'applications (par exemple, les compilations de développement par rapport aux compilations de version) où le code sous-jacent est censé être le même, mais où les niveaux de journalisation autorisés sont différents. Une règle explicite doit être définie et suivie pour que les applications (en particulier les applications système) puissent déterminer l'impact des types de compilation et des attentes de publication sur la sortie du journal.

Journalisation système dans Android Runtime (ART)

Plusieurs classes sont disponibles pour les applications et services système :

Cours Finalité
android.telephony.Rlog Journalisation 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 la plate-forme

Figure 6 : Classes et objectifs des 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 plate-forme. 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 la norme syslog, avec syslog(2) correspondant au noyau Linux syslog qui contrôle le tampon printk, et syslog(3) correspondant au journaliseur système général. Android utilise la bibliothèque liblog pour la journalisation générale du système.

liblog fournit des wrappers pour les groupes de sous-journaux à l'aide de la forme macro suivante :

[Sublog Buffer ID] LOG [Log Level ID]

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

Classe Wrapper 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 journalisation de niveau supérieur qui sont préférées à l'utilisation directe de liblog, comme indiqué ci-dessous :

Bibliothèque Utilisation
async_safe Bibliothèque uniquement pour la journalisation à partir d'environnements async-signal-safe
libbase Bibliothèque de journalisation qui fournit une interface de flux C++ pour la journalisation, semblable à la journalisation de style Google (glog). libbase est utilisable dans les projets externes et est disponible dans les applications utilisant libbase_ndk.

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

Approximations multistack

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

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 ce cas, utilisez la norme individuelle pour déterminer le niveau à appliquer.

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

Sécurité et confidentialité

Ne consignez pas d'informations permettant d'identifier personnellement les utilisateurs. Cela inclut des détails tels que :

  • Adresses e-mail
  • Numéros de téléphone
  • Les noms

De même, certains détails sont considérés comme sensibles, même s'ils ne permettent pas explicitement d'identifier personnellement l'utilisateur.

Par exemple, bien que les informations sur le fuseau horaire ne soient pas considérées comme des informations permettant d'identifier personnellement un utilisateur, elles donnent une indication de sa position approximative.

La stratégie 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.

les journaux de l'appareil.

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

  • Si une application en arrière-plan demande à accéder à 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).
    • Fuseau horaire : DropBoxManager.
    • Accède uniquement à la mémoire 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 à accéder aux journaux de l'appareil, le système invite l'utilisateur à approuver ou à refuser la demande d'accès.