Android – 设置logcat消息的最大长度

默认情况下,logcat似乎会截断它认为“太长”的日志消息。 这发生在Eclipse内部,以及在命令行上使用adb -d logcat运行adb -d logcat ,并截断一些重要的debugging消息。

有什么办法来增加logcat支持的最大string长度,让它停止截断debugging信息? 官方文档意味着可能没有,但也许logcat支持一些没有提到的其他选项呢?

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字节。 内核logging器接口强加这个LOGGER_ENTRY_MAX_PAYLOAD限制。

liblog源(由logcat使用)也说:

  • 该消息可能已被内核日志驱动程序截断。

我会build议你不使用logcat二进制文件的nxlog工具,但由于内核的限制,我怀疑它会解决你的问题。 不过,这可能值得一试。 (免责声明:我是作者。)

好的,有趣的。 我感到失望的是,答案是“你不能真正扩展它”。 我最初的想法是打破它,所以我可以看到整个事情,所以在这里我与你分享我是如何做到的(不是说它是什么幻想也不是有效的,但它完成了工作):

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

编辑显示最后一个string!

recursion地分解成几个部分。

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

提供我自己的Travis的解决scheme,

 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”的事实。 然后recursion地调用自己的消息部分,直到没有任何东西可以被logging。

如果你的日志非常长(例如,出于debugging原因logging数据库的整个转储等),logcat可能会阻止过多的日志logging。 要解决这个问题,你可以添加一个超时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); } 

当心,只能用于debugging目的,因为它可能会阻塞主线程。

我不知道增加logcat的长度的任何选项,但我们可以find不同的日志,如主日志,事件日志等。主日志通常包含所有的长度高达4Mb ..所以你可能能够得到你失去了什么在日志terminal。 path是:\ data \ logger。