Android - установить максимальную длину сообщений logcat - PullRequest
87 голосов
/ 17 января 2012

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

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

Ответы [ 11 ]

84 голосов
/ 21 июня 2012

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

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

Отредактировано, чтобы показать последнюю строку!

48 голосов
/ 09 сентября 2014

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

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);
   }
}
36 голосов
/ 17 января 2012

Для двоичных журналов в 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, но из-за ограничений в ядре я сомневаюсь, что он решит вашу проблему.проблема.Тем не менее, возможно, стоит попробовать.(отказ от ответственности: я автор.)

11 голосов
/ 19 февраля 2013
for( String line : logMesg.split("\n") ) {
    Log.d( TAG, line );
}
4 голосов
/ 26 июня 2013

Вот код, который я использую - он усекает строки на пределе 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;
    }
}
3 голосов
/ 16 января 2018

Код ниже является уточнением того, что написал Марк Буйкема.Это разрывает строку в новых строках.Полезно для регистрации длинных строк 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);
    }
  }
2 голосов
/ 26 сентября 2012

используя эту логику подкачки

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

}
1 голос
/ 18 января 2019
int i = 3000;
while (sb.length() > i) {
    Log.e(TAG, "Substring: "+ sb.substring(0, i));
    sb = sb.substring(i);
}
Log.e(TAG, "Substring: "+ sb);
1 голос
/ 29 марта 2017

Если ваш журнал очень длинный (например, ведение журнала всего дампа вашей базы данных по причинам отладки и т. Д.), Может случиться, что 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);
}

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

1 голос
/ 08 сентября 2012

предоставив свой собственный взгляд на решение Трэвиса,

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". затем рекурсивно назовите себя со стороны сообщения, которое не может быть зарегистрировано, пока ничего не осталось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...