web-dev-qa-db-fra.com

Android - Définir la longueur maximale des messages logcat

Par défaut, il semble que logcat tronque tout message de journal qu’il considère comme "trop ​​long". Cela se produit à la fois dans Eclipse et lors de l'exécution de logcat sur la ligne de commande à l'aide de adb -d logcat, et tronque certains messages de débogage importants. 

Existe-t-il un moyen d'augmenter la longueur de chaîne maximale prise en charge par logcat pour qu'il arrête de tronquer les informations de débogage? La documentation officielle implique qu'il peut ne pas en exister, mais peut-être que logcat prend en charge des options supplémentaires non mentionnées ici?

81
aroth

Logcat contient un tampon de taille fixe pour les journaux binaires (/dev/log/events) et cette limite est fixée à 1024 octets. Pour les journaux non binaires, il existe également une limite:

#define LOGGER_ENTRY_MAX_LEN        (4*1024)
#define LOGGER_ENTRY_MAX_PAYLOAD (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))

Ainsi, la taille réelle des messages pour les journaux binaires et non binaires est de ~ 4076 octets . L'interface de journalisation du noyau impose cette limite LOGGER_ENTRY_MAX_PAYLOAD.

Les sources de liblog (utilisées par logcat) disent aussi:

  • Le message peut avoir été tronqué par le pilote de journal du noyau.

Je vous recommanderais l'outil nxlog qui n'utilise pas le binaire logcat, mais en raison des limitations du noyau, je doute que cela résolve votre problème. Néanmoins, cela pourrait valoir la peine d'essayer. (disclaimer: je suis l'auteur.)

34
b0ti

Ok, intéressant. J'ai été déçu de voir que la réponse était "vous ne pouvez pas vraiment l'étendre". Ma pensée initiale était de diviser pour que je puisse voir le tout. Alors, ici, je partage avec vous comment je fais exactement cela (pas que ce soit quelque chose d'extraordinaire ni d'efficacité, mais que le travail soit fait à la rigueur): 

if (sb.length() > 4000) {
    Log.v(TAG, "sb.length = " + sb.length());
    int chunkCount = sb.length() / 4000;     // integer division
    for (int i = 0; i <= chunkCount; i++) {
        int max = 4000 * (i + 1);
        if (max >= sb.length()) {
            Log.v(TAG, "chunk " + i + " of " + chunkCount + ":" + sb.substring(4000 * i));
        } else {
            Log.v(TAG, "chunk " + i + " of " + chunkCount + ":" + sb.substring(4000 * i, max));
        }
    }
} else {
    Log.v(TAG, sb.toString());
}

Edité pour montrer la dernière chaîne!

84
Travis

Le casser en plusieurs morceaux récursivement.

public static void largeLog(String tag, String content) {
   if (content.length() > 4000) {
       Log.d(tag, content.substring(0, 4000));
       largeLog(tag, content.substring(4000));
   } else {
       Log.d(tag, content);
   }
}
45
Mark Buikema
for( String line : logMesg.split("\n") ) {
    Log.d( TAG, line );
}
10
user2085092

Voici le code que j'utilise - il tronque les lignes à la limite de 4000 tout en coupant la ligne à de nouvelles lignes plutôt qu'au milieu de la ligne. Facilite la lecture du fichier journal.

Usage:

Logger.debugEntire("....");

La mise en oeuvre:

package ...;

import Android.util.Log;

import Java.util.Arrays;

public class Logger {

    private static final String LOG_TAG = "MyRockingApp";

    /** @see <a href="http://stackoverflow.com/a/8899735" /> */
    private static final int ENTRY_MAX_LEN = 4000;

    /**
     * @param args If the last argument is an exception than it prints out the stack trace, and there should be no {}
     *             or %s placeholder for it.
     */
    public static void d(String message, Object... args) {
        log(Log.DEBUG, false, message, args);
    }

    /**
     * Display the entire message, showing multiple lines if there are over 4000 characters rather than truncating it.
     */
    public static void debugEntire(String message, Object... args) {
        log(Log.DEBUG, true, message, args);
    }

    public static void i(String message, Object... args) {
        log(Log.INFO, false, message, args);
    }

    public static void w(String message, Object... args) {
        log(Log.WARN, false, message, args);
    }

    public static void e(String message, Object... args) {
        log(Log.ERROR, false, message, args);
    }

    private static void log(int priority, boolean ignoreLimit, String message, Object... args) {
        String print;
        if (args != null && args.length > 0 && args[args.length-1] instanceof Throwable) {
            Object[] truncated = Arrays.copyOf(args, args.length -1);
            Throwable ex = (Throwable) args[args.length-1];
            print = formatMessage(message, truncated) + '\n' + Android.util.Log.getStackTraceString(ex);
        } else {
            print = formatMessage(message, args);
        }
        if (ignoreLimit) {
            while (!print.isEmpty()) {
                int lastNewLine = print.lastIndexOf('\n', ENTRY_MAX_LEN);
                int nextEnd = lastNewLine != -1 ? lastNewLine : Math.min(ENTRY_MAX_LEN, print.length());
                String next = print.substring(0, nextEnd /*exclusive*/);
                Android.util.Log.println(priority, LOG_TAG, next);
                if (lastNewLine != -1) {
                    // Don't print out the \n twice.
                    print = print.substring(nextEnd+1);
                } else {
                    print = print.substring(nextEnd);
                }
            }
        } else {
            Android.util.Log.println(priority, LOG_TAG, print);
        }
    }

    private static String formatMessage(String message, Object... args) {
        String formatted;
        try {
            /*
             * {} is used by SLF4J so keep it compatible with that as it's easy to forget to use %s when you are
             * switching back and forth between server and client code.
             */
            formatted = String.format(message.replaceAll("\\{\\}", "%s"), args);
        } catch (Exception ex) {
            formatted = message + Arrays.toString(args);
        }
        return formatted;
    }
}
4
enl8enmentnow

Le code ci-dessous est un raffinement de ce qui a été posté par Mark Buikema. Il casse la chaîne à de nouvelles lignes. Utile pour la journalisation de longues chaînes JSON.

  public static void dLong(String theMsg)
  {
    final int MAX_INDEX = 4000;
    final int MIN_INDEX = 3000;

    // String to be logged is longer than the max...
    if (theMsg.length() > MAX_INDEX)
    {
      String theSubstring = theMsg.substring(0, MAX_INDEX);
      int    theIndex = MAX_INDEX;

      // Try to find a substring break at a line end.
      theIndex = theSubstring.lastIndexOf('\n');
      if (theIndex >= MIN_INDEX)
      {
        theSubstring = theSubstring.substring(0, theIndex);
      }
      else
      {
        theIndex = MAX_INDEX;
      }

      // Log the substring.
      Log.d(APP_LOG_TAG, theSubstring);

      // Recursively log the remainder.
      dLong(theMsg.substring(theIndex));
    }

    // String to be logged is shorter than the max...
    else
    {
      Log.d(APP_LOG_TAG, theMsg);
    }
  }
3
dazed

nous cette logique de pagination

    /*
     * StringBuffer sb - long text which want to show in multiple lines 
     * int lenth - lenth of line need
     */

public static void showInPage(StringBuffer sb, int lenth) {
    System.out.println("sb.length = " + sb.length());
    if (sb.length() > lenth) {

        int chunkCount = sb.length() / lenth; // integer division
        if ((chunkCount % lenth) > 1)
            chunkCount++;
        for (int i = 0; i < chunkCount; i++) {
            int max = lenth * (i + 1);
            if (max >= sb.length()) {
                System.out.println("");
                System.out.println("chunk " + i + " of " + chunkCount + ":"
                        + sb.substring(lenth * i));
            } else {
                System.out.println("");
                System.out.println("chunk " + i + " of " + chunkCount + ":"
                        + sb.substring(lenth * i, max));
            }
        }
    }

}
2
neeraj t

fournir ma propre solution à la solution de Travis, 

void d(String msg) {
  println(Log.DEBUG, msg);
}

private void println(int priority, String msg) {
    int l = msg.length();
    int c = Log.println(priority, TAG, msg);
    if (c < l) {
        return c + println(priority, TAG, msg.substring(c+1));
    } else {
        return c;
    }
}

tirez profit du fait que Log.println() renvoie le nombre d'octets écrits pour éviter le codage en dur "4000". puis, appelez-vous récursivement dans la partie du message qui n'a pas pu être enregistrée tant qu'il ne reste plus rien. 

1
Jeffrey Blattman

Si votre journal est très long (par exemple, la journalisation d'une sauvegarde complète de votre base de données pour des raisons de débogage, etc.), il peut arriver que logcat empêche la journalisation excessive. Pour contourner ce problème, vous pouvez ajouter un délai d'expiration tous les x millisecondes.

/**
 * Used for very long messages, splits it into equal chunks and logs each individual to
 * work around the logcat max message length. Will log with {@link Log#d(String, String)}.
 *
 * @param tag     used in for logcat
 * @param message long message to log
 */
public static void longLogDebug(final String tag, @NonNull String message) {
    int i = 0;

    final int maxLogLength = 1000;
    while (message.length() > maxLogLength) {
        Log.d(tag, message.substring(0, maxLogLength));
        message = message.substring(maxLogLength);
        i++;

        if (i % 100 == 0) {
            StrictMode.noteSlowCall("wait to flush logcat");
            SystemClock.sleep(32);
        }
    }
    Log.d(tag, message);
}

Attention, utilisez-le uniquement à des fins de débogage car il peut arrêter le thread principal. 

1
patrickf
int i = 3000;
while (sb.length() > i) {
    Log.e(TAG, "Substring: "+ sb.substring(0, i));
    sb = sb.substring(i);
}
Log.e(TAG, "Substring: "+ sb);
0
Rizki Sunaryo

Je ne connais aucune option pour augmenter la longueur de logcat, mais nous pouvons trouver les différents journaux tels que le journal principal, le journal des événements, etc. dans le terminal de journal. Le chemin est:\data\logger.

0
Vins