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

aro*_*oth 92 logging android

默认情况下,似乎logcat会截断它认为"太长"的任何日志消息.这在Eclipse内部以及在命令行上使用logcat运行时都会发生adb -d logcat,并且会截断一些重要的调试消息.

有没有办法增加logcat支持的最大字符串长度,以使其停止截断调试信息?在官方文件意味着可能没有,但也许logcat的支持一些额外的选项不是有提及?

Tra*_*vis 85

好的,有趣的.我很失望地看到答案是"你无法真正扩展它".我最初的想法是打破它,所以我可以查看整个事情,所以我在这里与大家分享我是如何做到的(不是它有什么特别的,也不是有效的,但是它可以在紧要关头完成工作):

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());
}
Run Code Online (Sandbox Code Playgroud)

编辑显示最后一个字符串!

  • 对于非ASCII字符,这个答案是错误的.logcat支持UTF8,限制是4k*字节*,而不是字符. (4认同)
  • 你丢失了最后一个字符串:`int chunkCount = sb.length()/ 4000;`使用`int chunkCount = sb.length()/ 4000; if(chunkCount*4000 <sb.length())chunkCount ++;` (2认同)
  • 添加`else {Log.v(TAG,sb); 当消息<= 4000 chars long时,也打印日志 (2认同)

Mar*_*ema 50

递归地分解几个部分.

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);
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是迄今为止最干净的解决方案,也是我第一次在生产代码中实际使用递归. (3认同)
  • @Aggressor 为什么需要在生产中记录 4000 多条长消息? (2认同)
  • 我的用例是输出一个大的 json 内容。文件简直是一种痛苦。 (2认同)

b0t*_*0ti 39

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))
Run Code Online (Sandbox Code Playgroud)

因此,二进制和非二进制日志的实际消息大小约为4076字节.内核记录器接口强加了此LOGGER_ENTRY_MAX_PAYLOAD限制.

liblog源(由logcat使用)也说:

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

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

  • 我在哪里找到这个?它是在"logcat"代码中吗?那么,我是否必须编译自己的修改过的logcat? (6认同)
  • 什么是二进制/非二进制日志? (2认同)
  • 由于添加了元数据字段,在更新版本的Android中,"LOGGER_ENTRY_MAX_PAYLOAD"已从4076减少到4068(参见[此处](https://android.googlesource.com/platform/system/core.git/+/master) /liblog/include/log/log_read.h)). (2认同)

小智 11

for( String line : logMesg.split("\n") ) {
    Log.d( TAG, line );
}
Run Code Online (Sandbox Code Playgroud)


enl*_*now 5

这是我使用的代码-它在4000的限制处截断了行,同时还在新行而不是在行中间中断了行。使日志文件更易于阅读。

用法:

Logger.debugEntire("....");
Run Code Online (Sandbox Code Playgroud)

实现方式:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)


daz*_*zed 5

下面的代码是对 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);
    }
  }
Run Code Online (Sandbox Code Playgroud)


Riz*_*ryo 5

int i = 3000;
while (sb.length() > i) {
    Log.e(TAG, "Substring: "+ sb.substring(0, i));
    sb = sb.substring(i);
}
Log.e(TAG, "Substring: "+ sb);
Run Code Online (Sandbox Code Playgroud)