2012-01-17 11 views
71

Per impostazione predefinita, sembra che logcat tronchi qualsiasi messaggio di log che considera "troppo lungo". Ciò accade sia all'interno di Eclipse che durante l'esecuzione di logcat sulla riga di comando utilizzando adb -d logcat e sta troncando alcuni importanti messaggi di debug.Android - Imposta la lunghezza massima dei messaggi logcat

C'è un modo per aumentare la lunghezza massima della stringa supportata da logcat per impedirgli di troncare le informazioni di debug? Lo official documentation implica che potrebbe non esserci, ma forse logcat supporta alcune opzioni aggiuntive non menzionate lì?

+0

analogo: http://stackoverflow.com/questions/6321555/what-is-the-size-limit-for-logcat –

+0

Simili: [come visualizzare lunghi messaggi in logcat] (https: // stackoverflow.com/questions/7606077/how-to-display-long-messages-in-logcat) – chancyWu

risposta

29

C'è un buffer di dimensioni fisse in logcat per i registri binari (/dev/log/events) e questo limite è 1024 byte. per i registri non binari c'è anche un limite:

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

Quindi la dimensione del messaggio vero per entrambi i log binari e non binari è ~ 4076 byte. L'interfaccia del logger del kernel impone questo limite LOGGER_ENTRY_MAX_PAYLOAD.

Le fonti liblog (utilizzate da logcat) dicono anche:

  • Il messaggio potrebbe essere stato troncato dal driver log del kernel.

ti consiglierei lo strumento nxlog che non utilizza il binario logcat, ma a causa delle limitazioni nel kernel dubito che possa risolvere il problema. Tuttavia, potrebbe valere la pena provare. (disclaimer: io sono l'autore.)

+5

Dove trovo questo? È nel codice "logcat"? Quindi, dovrei compilare il mio logcat modificato? – d4Rk

+1

Che cos'è il registro binario/non binario? – fobbymaster

+0

A causa dell'aggiunta dei campi di metadati, 'LOGGER_ENTRY_MAX_PAYLOAD' è stato ridotto da 4076 a 4068 nelle versioni più recenti di Android (vedere [qui] (https://android.googlesource.com/platform/system/core.git/+/ master/liblog/include/log/log_read.h)). – mhsmith

0

Non conosco alcuna opzione per aumentare la lunghezza del logcat, ma possiamo trovare i vari registri come il registro principale, il registro eventi ecc. Il registro principale di solito contiene tutto la sua lunghezza va fino a 4Mb .. Quindi è possibile ottenere ciò che hai perso nel terminale di registro. Il percorso è: \ data \ logger.

79

Ok, interessante. Sono rimasto deluso nel vedere che la risposta era "non puoi davvero espanderlo". Il mio primo pensiero è stato di suddividerlo in modo che potessi vedere il tutto, quindi qui condivido con voi come faccio (non che sia di fantasia o di efficienza, ma il lavoro viene svolto in un colpo):

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()); 
} 

Modificato per mostrare l'ultima stringa!

+0

grazie per quello! Avevo anche intenzione di mordere i dati lunghi –

+0

Nessun problema! Spero che ti abbia aiutato – Travis

+0

Sono abbastanza sicuro che c'è un errore in questo caso. Ho dovuto usare "i Dan

1

fornendo il mio introito sulla soluzione di 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; 
    } 
} 

approfittare del fatto che Log.println() restituisce il numero di byte scritti per evitare hardcoding "4000". quindi, ricorsivamente, ti chiami sulla parte del messaggio che non può essere registrata finché non rimane nulla.

+0

Sfortunatamente, println restituisce # di byte scritti e caratteri! = Byte. – gnuf

+1

bene, funziona. presumo perché sto solo registrando testo ascii. –

2

noi questa logica di paging

/* 
    * 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)); 
      } 
     } 
    } 

} 
10
for(String line : logMesg.split("\n")) { 
    Log.d(TAG, line); 
} 
4

ecco il codice che uso - è tronca le righe al limite 4000, mentre anche rompere la linea a nuove linee piuttosto che nelle parti centrali della linea . Rende un file di registro più semplice da leggere.

Usage:

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

Implementazione:

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; 
    } 
} 
+0

Funziona perfettamente! –

+0

Prego :) – enl8enmentnow

28

disgregare in vari pezzi in modo ricorsivo.

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); 
    } 
} 
+3

Questa è di gran lunga la soluzione più pulita e la prima volta che ho effettivamente utilizzato la ricorsione nel codice di produzione. – Aggressor

+1

@Aggressor perché è necessario registrare 4000+ lunghi messaggi in produzione? – TWiStErRob

+0

@TWiStErRob Oggetti molto grandi che devono essere rafforzati. Per esempio. un array con migliaia di posizioni. – Aggressor

1

Se il registro è molto lungo (ad es. La registrazione dell'intero dump del database per il debug di motivi, ecc) può accadere che logcat impedisce disboscamento eccessivo. Per ovviare a ciò è possibile aggiungere un timeout evry x millisecondi.

/** 
* 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); 
} 

Attenzione, utilizzare questo solo per scopi di debug in quanto potrebbe arrestare il thread principale dei blocchi.

0

Il codice di seguito è un raffinamento di ciò che è stato pubblicato da Mark Buikema. Rompe la corda a nuove linee. Utile per la registrazione di lunghe stringhe 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); 
    } 
    } 
Problemi correlati