Comment activer / désactiver les niveaux de log dans Android?

j'ai beaucoup d'instructions de journalisation à déboguer par exemple.

Log.v(TAG, "Message here");
Log.w(TAG, " WARNING HERE");

pendant le déploiement de cette application sur le téléphone périphérique, je veux désactiver la journalisation verbeuse d'où je peux activer/désactiver la journalisation.

145
demandé sur Frank Kusters 2010-01-07 07:48:45

16 réponses

Une façon courante est de faire un int nommé loglevel, et de définir son niveau de débogage basé sur loglevel.

public static int LOGLEVEL = 2;
public static boolean ERROR = LOGLEVEL > 0;
public static boolean WARN = LOGLEVEL > 1;
...
public static boolean VERBOSE = LOGLEVEL > 4;

    if (VERBOSE) Log.v(TAG, "Message here"); // Won't be shown
    if (WARN) Log.w(TAG, "WARNING HERE");    // Still goes through

plus tard, vous pouvez simplement changer le LOGLEVEL pour tous les niveaux de sortie de débogage.

79
répondu Cytown 2014-10-23 18:49:13

la Documentation Android dit ce qui suit sur les niveaux de Log :

Verbose ne doit jamais être compilé dans une application sauf pendant le développement. Les journaux de débogage sont compilés mais dépouillés à l'exécution. Erreur, avertissement et informations des journaux sont toujours conservés.

donc vous pouvez envisager de retirer les énoncés de journalisation verbeuse, peut-être en utilisant ProGuard comme suggéré dans une autre réponse .

selon la documentation, vous pouvez configurer la journalisation sur un périphérique de développement en utilisant les propriétés du système. La propriété à définir est log.tag.<YourTag> et il doit être réglé sur l'une des valeurs suivantes: VERBOSE , DEBUG , INFO , WARN , ERROR , ASSERT , ou SUPPRESS . vous trouverez de plus amples renseignements à ce sujet dans la documentation relative à la méthode isLoggable() .

vous pouvez définir les propriétés temporairement en utilisant la commande setprop . Par exemple:

C:\android>adb shell setprop log.tag.MyAppTag WARN
C:\android>adb shell getprop log.tag.MyAppTag
WARN

alternativement, vous pouvez les spécifier dans le fichier '/data/local.prop' comme suit:

log.tag.MyAppTag=WARN

les versions ultérieures D'Android semblent exiger que / data / local.prop être en lecture seule . Ce fichier est lu au démarrage, vous devrez donc le redémarrer après l'avoir mis à jour. Si /data/local.prop est monde accessible en écriture, il sera probablement ignoré.

enfin, vous pouvez les programmer en utilisant la System.setProperty() méthode .

188
répondu Dave Webb 2017-05-23 11:47:08

la façon la plus simple est probablement d'exécuter votre JAR compilé à travers ProGuard avant le déploiement, avec une configuration comme:

-assumenosideeffects class android.util.Log {
    public static int v(...);
}

qui - en dehors de toutes les autres optimisations ProGuard-supprimera toutes les déclarations verbeuses log directement du bytecode.

88
répondu Christopher Orr 2010-01-07 08:10:06

j'ai pris une route simple - créer une classe wrapper qui utilise également des listes de paramètres variables.

 public class Log{
        public static int LEVEL = android.util.Log.WARN;


    static public void d(String tag, String msgFormat, Object...args)
    {
        if (LEVEL<=android.util.Log.DEBUG)
        {
            android.util.Log.d(tag, String.format(msgFormat, args));
        }
    }

    static public void d(String tag, Throwable t, String msgFormat, Object...args)
    {
        if (LEVEL<=android.util.Log.DEBUG)
        {
            android.util.Log.d(tag, String.format(msgFormat, args), t);
        }
    }

    //...other level logging functions snipped
18
répondu kdahlhaus 2015-07-16 08:21:21

la meilleure façon est d'utiliser L'API SLF4J + une partie de son implémentation.

pour les applications Android, vous pouvez utiliser ce qui suit:

  1. Android Logger est l'implémentation SLF4J légère mais facile à configurer (< 50 Kb).
  2. LOGBack est l'implémentation la plus puissante et optimisée, mais sa taille est d'environ 1 Mo.
  3. toute autre à votre goût: slf4j-android, slf4android.
10
répondu Fortess Nsk 2013-03-16 17:41:13

vous devez utiliser

    if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "my log message");
    }
8
répondu Diego Torres Milano 2010-01-07 14:32:08

supprimer la journalisation avec proguard (voir la réponse de @Christopher ) a été facile et rapide, mais cela a causé des traces de pile de la production pour ne pas correspondre à la source s'il y avait une journalisation de débogage dans le fichier.

au lieu de cela, Voici une technique qui utilise différents niveaux de diagraphie dans le développement par rapport à la production, en supposant que proguard est utilisé seulement dans la production. Il reconnaît production en voyant si proguard a renommé un nom de classe (dans l'exemple, j'utilise "COM.foo.Bar " --vous remplaceriez ceci par un nom de classe entièrement qualifié qui, vous le savez, sera renommé par proguard).

cette technique utilise l'enregistrement des biens communs.

private void initLogging() {
    Level level = Level.WARNING;
    try {
        // in production, the shrinker/obfuscator proguard will change the
        // name of this class (and many others) so in development, this
        // class WILL exist as named, and we will have debug level
        Class.forName("com.foo.Bar");
        level = Level.FINE;
    } catch (Throwable t) {
        // no problem, we are in production mode
    }
    Handler[] handlers = Logger.getLogger("").getHandlers();
    for (Handler handler : handlers) {
        Log.d("log init", "handler: " + handler.getClass().getName());
        handler.setLevel(level);
    }
}
4
répondu larham1 2013-10-30 16:44:01

Log4j ou slf4j peut également être utilisé comme cadres de journalisation sous Android avec logcat. Voir le projet android-logging-log4j ou log4j prise en charge sous android

3
répondu Rolf Kulemann 2017-05-23 12:02:17

Il ya un petit drop-in de remplacement pour la classe standard android Log - https://github.com/zserge/log

Fondamentalement, tout ce que vous avez à faire est de remplacer les importations de android.util.Log à trikita.log.Log . Puis, dans votre Application.onCreate() ou dans un quelconque initaliseur Statique, vérifiez le BuilConfig.DEBUG ou tout autre drapeau et utilisez Log.level(Log.D) ou Log.level(Log.E) pour changer le niveau minimal du journal. Vous pouvez utiliser Log.useLog(false) pour désactiver la journalisation.

3
répondu Eric Weyant 2015-06-14 07:47:56

peut être vous pouvez voir cette classe D'extension de Log: https://github.com/dbauduin/Android-Tools/tree/master/logs .

il vous permet d'avoir une commande fine sur les rondins. Vous pouvez par exemple désactiver tous les journaux ou les journaux de certains paquets ou des classes.

en outre, il ajoute quelques fonctionnalités utiles (par exemple, vous n'avez pas à passer une étiquette pour chaque log).

2
répondu Donkey 2013-05-15 14:58:21

j'ai créé un utilitaire/Wrapper qui résout ce problème + d'autres problèmes courants autour de la journalisation.

un utilitaire de débogage avec les caractéristiques suivantes:

  • les caractéristiques habituelles fournies par la classe Log enveloppée par LogMode S.
  • méthode entrée-sortie logs: peut être désactivé par un interrupteur
  • Debugging sélectif: classes de débogage spécifiques.
  • Exécution de la méthode-mesure du temps: mesure du temps d'exécution pour des méthodes individuelles ainsi que du temps collectif consacré à toutes les méthodes d'une classe.

Comment Utiliser?

  • incluez la catégorie dans votre projet.
  • utilisez-le comme vous utilisez android.util.Journal des méthodes pour commencer.
  • utilisez la fonction Entry-Exit logs en plaçant les appels vers les méthodes entry_log()-exit_log() au début et à la fin de méthodes dans votre application.

j'ai essayé de rendre la documentation autosuffisante.

les Suggestions pour améliorer cette utilité sont les bienvenues.

gratuit à utiliser / Partager.

Téléchargez-le de GitHub .

2
répondu Vinay Wadhwa 2013-10-23 07:35:32

Voici une solution plus complexe. Vous obtiendrez la trace complète de la pile et la méthode toString () ne sera appelée que si nécessaire (Performance). L'attribut BuildConfig.Le débogage sera false dans le mode de production donc tous les journaux de trace et de débogage seront supprimés. Le compilateur de points chauds a la chance de supprimer les appels parce que les propriétés statiques finales.

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import android.util.Log;

public class Logger {

    public enum Level {
        error, warn, info, debug, trace
    }

    private static final String DEFAULT_TAG = "Project";

    private static final Level CURRENT_LEVEL = BuildConfig.DEBUG ? Level.trace : Level.info;

    private static boolean isEnabled(Level l) {
        return CURRENT_LEVEL.compareTo(l) >= 0;
    }

    static {
        Log.i(DEFAULT_TAG, "log level: " + CURRENT_LEVEL.name());
    }

    private String classname = DEFAULT_TAG;

    public void setClassName(Class<?> c) {
        classname = c.getSimpleName();
    }

    public String getClassname() {
        return classname;
    }

    public boolean isError() {
        return isEnabled(Level.error);
    }

    public boolean isWarn() {
        return isEnabled(Level.warn);
    }

    public boolean isInfo() {
        return isEnabled(Level.info);
    }

    public boolean isDebug() {
        return isEnabled(Level.debug);
    }

    public boolean isTrace() {
        return isEnabled(Level.trace);
    }

    public void error(Object... args) {
        if (isError()) Log.e(buildTag(), build(args));
    }

    public void warn(Object... args) {
        if (isWarn()) Log.w(buildTag(), build(args));
    }

    public void info(Object... args) {
        if (isInfo()) Log.i(buildTag(), build(args));
    }

    public void debug(Object... args) {
        if (isDebug()) Log.d(buildTag(), build(args));
    }

    public void trace(Object... args) {
        if (isTrace()) Log.v(buildTag(), build(args));
    }

    public void error(String msg, Throwable t) {
        if (isError()) error(buildTag(), msg, stackToString(t));
    }

    public void warn(String msg, Throwable t) {
        if (isWarn()) warn(buildTag(), msg, stackToString(t));
    }

    public void info(String msg, Throwable t) {
        if (isInfo()) info(buildTag(), msg, stackToString(t));
    }

    public void debug(String msg, Throwable t) {
        if (isDebug()) debug(buildTag(), msg, stackToString(t));
    }

    public void trace(String msg, Throwable t) {
        if (isTrace()) trace(buildTag(), msg, stackToString(t));
    }

    private String buildTag() {
        String tag ;
        if (BuildConfig.DEBUG) {
            StringBuilder b = new StringBuilder(20);
            b.append(getClassname());

            StackTraceElement stackEntry = Thread.currentThread().getStackTrace()[4];
            if (stackEntry != null) {
                b.append('.');
                b.append(stackEntry.getMethodName());
                b.append(':');
                b.append(stackEntry.getLineNumber());
            }
            tag = b.toString();
        } else {
            tag = DEFAULT_TAG;
        }
    }

    private String build(Object... args) {
        if (args == null) {
            return "null";
        } else {
            StringBuilder b = new StringBuilder(args.length * 10);
            for (Object arg : args) {
                if (arg == null) {
                    b.append("null");
                } else {
                    b.append(arg);
                }
            }
            return b.toString();
        }
    }

    private String stackToString(Throwable t) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(500);
        baos.toString();
        t.printStackTrace(new PrintStream(baos));
        return baos.toString();
    }
}

utiliser comme ceci:

Loggor log = new Logger();
Map foo = ...
List bar = ...
log.error("Foo:", foo, "bar:", bar);
// bad example (avoid something like this)
// log.error("Foo:" + " foo.toString() + "bar:" + bar); 
2
répondu Andreas Mager 2014-08-16 13:58:57

dans un scénario de journalisation très simple, où vous êtes littéralement en train d'essayer d'écrire sur la console pendant le développement à des fins de débogage, il pourrait être plus facile de faire une recherche et de remplacer avant votre construction de production et de commenter tous les appels à la Log ou au système.hors.println.

par exemple, en supposant que vous n'avez pas utilisé le" Log."n'importe où en dehors d'un appel à Journaux.D ou Log.e, etc, Vous pouvez simplement faire une recherche et remplacer à travers toute la solution pour remplacer "Log." avec "//Journal."pour commenter tous vos appels de journalisation, ou dans mon cas j'utilise juste le système.hors.println partout, donc avant d'aller en production, je vais simplement faire une recherche complète et de le remplacer par "le Système de.hors.println" et remplacer par "//Système.hors.println".

je sais que ce n'est pas idéal, et ce serait bien si la capacité de trouver et de commenter les appels à Log et système.hors.println ont été construits dans Eclipse, mais jusqu'à ce que cela se produit la plus facile et la plus rapide et la meilleure façon de le faire est commentaire par rechercher et remplacer. Si vous faites cela, vous n'avez pas à vous soucier de la mauvaise correspondance des numéros de ligne de trace de la pile, parce que vous éditez votre code source, et vous n'ajoutez pas de frais généraux en vérifiant une certaine configuration au niveau du journal, etc.

1
répondu Jim 2013-03-28 19:54:49

dans Mes applications, j'ai une classe qui enveloppe la classe Log qui a un var booléen statique appelé "état". Tout au long de mon code, je vérifie la valeur de la variable "state" en utilisant une méthode statique avant d'écrire dans le journal. J'ai alors une méthode statique pour définir la variable "state" qui assure que la valeur est commune à toutes les instances créées par l'application. Cela signifie que je peux activer ou désactiver toute journalisation pour L'application en un seul appel - même lorsque l'application est en cours d'exécution. Utile pour les appels de soutien... Cela signifie que vous devez vous en tenir à vos armes lors du débogage et ne pas régresser à l'utilisation de la classe de Log standard...

il est également utile (pratique) que Java interprète un var booléen comme false s'il n'a pas reçu de valeur, ce qui signifie qu'il peut être laissé comme false jusqu'à ce que vous ayez besoin d'activer la journalisation: -)

1
répondu Darnst 2013-09-19 15:25:34

nous pouvons utiliser la classe Log dans notre composant local et définir les méthodes comme v/i/e/D. En fonction du besoin de nous pouvons faire appel plus loin.

exemple est montré ci-dessous.

    public class Log{
        private static boolean TAG = false;
        public static void d(String enable_tag, String message,Object...args){
            if(TAG)
            android.util.Log.d(enable_tag, message+args);
        }
        public static void e(String enable_tag, String message,Object...args){
            if(TAG)
            android.util.Log.e(enable_tag, message+args);
        }
        public static void v(String enable_tag, String message,Object...args){
            if(TAG)
            android.util.Log.v(enable_tag, message+args);
        }
    }
    if we do not need any print(s), at-all make TAG as false for all else 
    remove the check for type of Log (say Log.d).
    as 
    public static void i(String enable_tag, String message,Object...args){
    //      if(TAG)
            android.util.Log.i(enable_tag, message+args);
    }

ici, le message est pour string et et args est la valeur que vous souhaitez imprimer.

1
répondu Gyanendra Tripathi 2015-08-06 13:05:22

pour moi, il est souvent utile de pouvoir définir différents niveaux de log pour chaque étiquette.

j'utilise cette classe d'emballage très simple:

public class Log2 {

    public enum LogLevels {
        VERBOSE(android.util.Log.VERBOSE), DEBUG(android.util.Log.DEBUG), INFO(android.util.Log.INFO), WARN(
                android.util.Log.WARN), ERROR(android.util.Log.ERROR);

        int level;

        private LogLevels(int logLevel) {
            level = logLevel;
        }

        public int getLevel() {
            return level;
        }
    };

    static private HashMap<String, Integer> logLevels = new HashMap<String, Integer>();

    public static void setLogLevel(String tag, LogLevels level) {
        logLevels.put(tag, level.getLevel());
    }

    public static int v(String tag, String msg) {
        return Log2.v(tag, msg, null);
    }

    public static int v(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.VERBOSE) {
                return -1;
            }
        }
        return Log.v(tag, msg, tr);
    }

    public static int d(String tag, String msg) {
        return Log2.d(tag, msg, null);
    }

    public static int d(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.DEBUG) {
                return -1;
            }
        }
        return Log.d(tag, msg);
    }

    public static int i(String tag, String msg) {
        return Log2.i(tag, msg, null);
    }

    public static int i(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.INFO) {
                return -1;
            }
        }
        return Log.i(tag, msg);
    }

    public static int w(String tag, String msg) {
        return Log2.w(tag, msg, null);
    }

    public static int w(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.WARN) {
                return -1;
            }
        }
        return Log.w(tag, msg, tr);
    }

    public static int e(String tag, String msg) {
        return Log2.e(tag, msg, null);
    }

    public static int e(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.ERROR) {
                return -1;
            }
        }
        return Log.e(tag, msg, tr);
    }

}

maintenant, il suffit de définir le niveau log par étiquette au début de chaque classe:

Log2.setLogLevel(TAG, LogLevels.INFO);
0
répondu Jack Miller 2015-02-02 14:31:22