Android-установить максимальную длину сообщений logcat



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



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

505   10  

10 ответов:

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

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

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

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

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

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);
   }
}
for( String line : logMesg.split("\n") ) {
    Log.d( TAG, line );
}

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

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

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

}

приведенный ниже код является уточнением того, что было опубликовано 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);
    }
  }

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

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

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

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

Я не знаю никакой возможности увеличить длину logcat , но мы можем найти различные журналы , такие как основной журнал, журнал событий и т. д..Основной журнал обычно содержит все, что его длина доходит до 4 мб.. Таким образом, вы можете получить то, что вы потеряли в log terminal. Путь: \data\logger.

Comments

    Ничего не найдено.