デフォルトでは、logcatは「長すぎる」と見なされるログメッセージを切り捨てるようです。これは、Eclipseの内部とadb -d logcat
を使用してコマンドラインでlogcatを実行するときに発生し、いくつかの重要なデバッグメッセージを切り捨てています。
Logcatがサポートする最大文字列長を増やして、デバッグ情報の切り捨てを停止する方法はありますか? 公式ドキュメント は存在しない可能性があることを意味しますが、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バイトです。カーネルロガーインターフェースは、このLOGGER_ENTRY_MAX_PAYLOAD
制限。
(logcatが使用する)liblogのソースも次のように述べています。
- このメッセージは、カーネルログドライバーによって切り捨てられた可能性があります。
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());
}
最後の文字列を表示するように編集されました!
再帰的にいくつかの部分に分割します。
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;
}
}
以下のコードは、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);
}
}
このページングロジック
/*
* 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));
}
}
}
}
int i = 3000;
while (sb.length() > i) {
Log.e(TAG, "Substring: "+ sb.substring(0, i));
sb = sb.substring(i);
}
Log.e(TAG, "Substring: "+ sb);
travisのソリューションに対する独自の見解を提供し、
_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 MBまでになるすべてのものが含まれています。ログ端末で。パスは\ data\loggerです。