2012-01-17 6 views
71

По умолчанию кажется, что logcat будет обрезать любое сообщение журнала, которое оно считает «слишком длинным». Это происходит как внутри Eclipse, так и при запуске logcat в командной строке с использованием adb -d logcat и обрезает некоторые важные отладочные сообщения.Android - установить максимальную длину сообщений logcat

Есть ли способ увеличить максимальную длину строки, поддерживаемую logcat, чтобы остановить ее отключение отладки? official documentation подразумевает, что их может не быть, но, возможно, logcat поддерживает некоторые дополнительные опции, не упомянутые там?

+0

Похожие: http://stackoverflow.com/questions/6321555/what-is-the-size-limit-for-logcat –

+0

Похожие: [как отобразить длинные сообщения в LogCat] (https: // stackoverflow.com/questions/7606077/how-to-display-long-messages-in-logcat) – chancyWu

ответ

29

Буфер фиксированного размера в logcat для двоичных журналов (/dev/log/events), и этот предел составляет 1024 байта. Для небинарных журналов существует также предел:

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

Таким образом, реальный размер сообщения для обоих бинарных и недвоичных журналов составляет ~ 4076 байт. Интерфейс регистратора ядра налагает этот предел LOGGER_ENTRY_MAX_PAYLOAD.

В liblog источники (используемые LogCat) также говорят:

  • Сообщение может быть усечен драйвером журнала ядра.

Я бы порекомендовал вам инструмент nxlog, который не использует LogCat двоичный, но из-за ограничений в ядре я сомневаюсь, что это решит вашу проблему. Тем не менее, возможно, стоит попробовать. (отказ от ответственности: я автор.)

+5

Где я могу найти это? Это в коде «logcat»? Итак, нужно ли мне скомпилировать собственный модифицированный логарифм? – d4Rk

+1

Что такое бинарный/небинный журнал? – fobbymaster

+0

Из-за добавления полей метаданных 'LOGGER_ENTRY_MAX_PAYLOAD' сокращен с 4076 до 4068 в более поздних версиях Android (см. [Здесь] (https://android.googlesource.com/platform/system/core.git/+/ ведущий/liblog/включать/журнал/log_read.h)). – mhsmith

0

Я не знаю какой-либо возможности увеличить длину logcat, но мы можем найти разные журналы, такие как основной журнал, журнал событий и т. Д. Главный журнал обычно содержит все его длины до 4 Мб. Поэтому вы можете получить то, что вы потеряли в лог-терминале. Путь: \ data \ logger.

79

Хорошо, интересно. Я был разочарован, увидев, что ответ был «вы не можете его расширить». Моя первоначальная мысль заключалась в том, чтобы разбить ее, чтобы я мог все это рассмотреть, поэтому я разделяю с вами, как я это делаю (не то, чтобы это было что-то необычное, и это не было эффективно, но это делает работу в крайнем случае):

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

Отредактировано для отображения последней строки!

+0

спасибо за это! Я также собирался объединить длинные данные –

+0

Нет проблем! Надеюсь, вам это помогло. – Travis

+0

Я уверен, что здесь одна ошибка. Мне пришлось использовать «i Dan

1

обеспечивая свой собственный взять на себя решение Тревиса,

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

пользуются преимуществом того факта, что Log.println() возвращает количество байтов, чтобы избежать жесткого кодирования «4000». затем рекурсивно называть себя частью сообщения, которое невозможно зарегистрировать, пока ничего не останется.

+0

К сожалению, println возвращает # записанных байтов и символы! = Байты. – gnuf

+1

хорошо, он работает. Я предполагаю, что я только регистрирую текст ascii. –

2

нам это пейджинговой логика

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

} 
4

Вот код, я использую - это усечение строки в 4000 пределе, а также преодолев линию на новых линиях, а не в серединах линии , Делает для более легкого для чтения файла журнала.

Использование:

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

Реализация:

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

Прекрасно работает! –

+0

Добро пожаловать :) – enl8enmentnow

28

разбить его на несколько частей рекурсивно.

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

Это, безусловно, самое чистое решение, и я впервые использовал рекурсию в производственном коде. – Aggressor

+1

@Aggressor, почему вам нужно записывать 4000+ длинных сообщений в процессе производства? – TWiStErRob

+0

@TWiStErRob Очень большие объекты, которые необходимо стягивать. Например. массив с тысячами мест. – Aggressor

1

Если ваш журнал очень долго (например, вход всего дампа базы данных для отладки причины и т.д.) может случиться так, что LogCat предотвращает чрезмерное протоколирование. Чтобы обойти это, вы можете добавить тайм-аут evry x миллисекунды.

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

Опасайтесь, используйте его только для целей отладки, так как он может остановить основной поток блоков.

0

Код, приведенный ниже, является уточнением того, что было опубликовано Mark Buikema. Он разбивает строку на новые строки. Полезно для записи длинных строк 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); 
    } 
    } 
Смежные вопросы