Android - Logcat संदेशों की अधिकतम लंबाई सेट करें


101

डिफ़ॉल्ट रूप से, ऐसा लगता है कि लॉगकैट किसी भी लॉग संदेश को काट देगा जो इसे "बहुत लंबा" मानता है। यह ग्रहण के अंदर और कमांड लाइन पर लॉगकोट का उपयोग करते समय होता है adb -d logcat, और कुछ महत्वपूर्ण डिबगिंग संदेशों को काट रहा है।

डिबग सूचना को कम करने के लिए इसे प्राप्त करने के लिए लॉगकैट द्वारा समर्थित अधिकतम स्ट्रिंग लंबाई बढ़ाने का कोई तरीका है? आधिकारिक दस्तावेज का तात्पर्य है कि वहाँ नहीं हो सकता है, लेकिन शायद का समर्थन करता है logcat कुछ अतिरिक्त विकल्प वहाँ का उल्लेख नहीं किया?





1
@ जोशकोरिया मुझे नहीं लगता कि यह एक अच्छा डुप्लिकेट है, क्योंकि यह कुल बफर आकार को संदर्भित करता है, और यह प्रति लॉग संदेश है।
रयान एम

1
@RyanM आह मेरे बुरे, मैंने दूसरे प्रश्न को गलत समझा। धन्यवाद, निशान हटाने के रूप में।
जोश कोर्रेया

जवाबों:


45

बाइनरी लॉग ( /dev/log/events) के लिए logcat में एक निश्चित आकार का बफर है और यह सीमा 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 टूल की सलाह दूंगा जो लॉगकैट बाइनरी का उपयोग नहीं करता है, लेकिन कर्नेल में सीमाओं के कारण मुझे संदेह है कि यह आपकी समस्या को हल करेगा। फिर भी, यह एक कोशिश के काबिल हो सकता है। (अस्वीकरण: मैं लेखक हूं।)


6
मुझे ये कहां मिल सकता है? क्या यह "logcat" कोड में है? तो, क्या मुझे अपना संशोधित लॉगकट संकलित करना होगा?
15:

2
बाइनरी / गैर-बाइनरी लॉग क्या है?
फोबाइमास्टर

2
मेटाडेटा फ़ील्ड्स को जोड़े जाने के कारण, LOGGER_ENTRY_MAX_PAYLOADAndroid के अधिक हाल के संस्करणों में 4076 से घटाकर 4068 कर दिया गया है ( यहाँ देखें )।
mhsmith

87

ठीक है, दिलचस्प है। मुझे यह देखकर निराशा हुई कि उत्तर था "आप वास्तव में इसका विस्तार नहीं कर सकते"। मेरा प्रारंभिक विचार इसे तोड़ना था इसलिए मैं पूरी बात देख सकता था, इसलिए यहां मैं आपके साथ साझा करता हूं कि मैं ऐसा कैसे करता हूं (न कि यह कुछ फैंसी है और न ही यह कुशल के पास है, लेकिन यह चुटकी में काम हो जाता है):

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

अंतिम स्ट्रिंग दिखाने के लिए संपादित किया गया!


कोई दिक्कत नहीं है! आशा है कि यह आपकी मदद करेगा
ट्रैविस

मुझे पूरा यकीन है कि यहाँ एक त्रुटि से एक बंद है। मुझे अंतिम चंक पाने के लिए "i <chunkCount + 1" का उपयोग करना था
दान

2
आपने अंतिम तार खो दिया: int chunkCount = sb.length() / 4000;उपयोग int chunkCount = sb.length() / 4000; if (chunkCount * 4000 < sb.length()) chunkCount++;
तैमूर गिलफानोव

2
else { Log.v(TAG, sb); }संदेश जोड़ने पर लॉग को प्रिंट करने के लिए जोड़ें <= 4000 चार्ट्स लंबा
Bojan Radivojevic Bomber

4
गैर-ASCII वर्णों के लिए यह उत्तर गलत है। logcat UTF8 का समर्थन करता है और सीमा 4k बाइट्स है , वर्ण नहीं।
मिगेल

58

इसे कई टुकड़ों में पुनरावृत्ति से तोड़ दें।

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

3
यह अब तक सबसे साफ समाधान है और पहली बार मैंने वास्तव में उत्पादन कोड में पुनरावृत्ति का उपयोग किया है।
अग्रगामी

2
@ एग्रेसर आपको उत्पादन में 4000+ लंबे संदेशों को लॉग इन करने की आवश्यकता क्यों है?
टीडब्लूआरब्रोब

1
मेरा उपयोग मामला एक बड़े json सामान के उत्पादन के लिए है। फाइलें बस एक दर्द हैं।
मार्सेल फॉलियर

1
बहुत उपयोगी धन्यवाद। मैंने एक उत्तर पोस्ट किया है जो लाइन एंडिंग पर स्ट्रिंग को तोड़ता है।
स्तब्ध

1
बहुत बढ़िया सरल क्लीनर कूल और सुंदर। क्लैप्स
मुहम्मद अशफाक


5

यहाँ मैं उपयोग किया जाने वाला कोड है - यह लाइनों को 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;
    }
}

4

नीचे दिया गया कोड मार्क बुइकेमा द्वारा पोस्ट किया गया एक शोधन है। यह नई लाइनों पर स्ट्रिंग को तोड़ता है। लंबे 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

हमें इस पेजिंग तर्क

    /*
     * 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

ट्रैविस के समाधान पर अपना खुद का प्रदान करना,

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" से बचने के लिए लिखे गए बाइट्स की संख्या लौटाता है। फिर, अपने आप को संदेश के उस हिस्से पर पुन: कॉल करें जो तब तक लॉग इन नहीं किया जा सकता जब तक कि कुछ भी नहीं बचा हो।


दुर्भाग्य से, प्रिंट किए गए # बाइट्स के रिटर्न, और अक्षर! = बाइट्स।
gnuf

1
ठीक है, यह काम करता है। मुझे लगता है क्योंकि मैं केवल ascii पाठ लॉगिंग कर रहा हूँ।
जेफरी ब्लाटमैन

1

यदि आपका लॉग बहुत लंबा है (उदाहरण के लिए डिबगिंग कारणों के लिए अपने डेटाबेस के पूरे डंप को लॉग करना आदि) तो ऐसा हो सकता है कि लॉगकैट लॉगिंग को रोकता है। इसके आस-पास काम करने के लिए आप एक टाइमआउट 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

जैसा कि @mhsmith ने उल्लेख किया है, LOGGER_ENTRY_MAX_PAYLOADहाल के Android संस्करणों में 4068 है। हालाँकि, यदि आप अन्य उत्तरों में दिए गए कोड स्निपेट में अधिकतम संदेश लंबाई के रूप में 4068 का उपयोग करते हैं, तो संदेश काट दिए जाएंगे। ऐसा इसलिए है क्योंकि एंड्रॉइड आपके संदेश की शुरुआत और अंत में अधिक वर्ण जोड़ता है, जो गिनती भी करता है। अन्य जवाब 4000 सीमा का उपयोग वर्कअराउंड के रूप में करते हैं। हालांकि, वास्तव में इस कोड के साथ पूरी सीमा का उपयोग करना संभव है (कोड वर्ग नाम और रेखा संख्या दिखाने के लिए स्टैक ट्रेस से एक टैग बनाता है जिसे लॉग कहा जाता है, इसे संशोधित करने के लिए स्वतंत्र महसूस करें):

private static final int MAX_MESSAGE_LENGTH = 4068;

private enum LogType {
    debug,
    info,
    warning,
    error
}

private static void logMessage(LogType logType, @Nullable String message, @Nullable String tag) {
    logMessage(logType, message, tag, Thread.currentThread().getStackTrace()[4]);
}

private static void logMessage(LogType logType, @Nullable String message, @Nullable String customTag, StackTraceElement stackTraceElement) {
    // don't use expensive String.format
    String tag = "DASHBOARDS(" + stackTraceElement.getFileName() + "." + (!TextUtils.isEmpty(customTag) ? customTag : stackTraceElement.getMethodName()) + ":" + stackTraceElement.getLineNumber() + ")";
    int maxMessageLength = MAX_MESSAGE_LENGTH - (tag.length()) - 4; // minus four because android adds a letter showing the log type before the tag, e. g. "D/" for debug, and a colon and space are added behind it, i. e. ": "
    if (message == null || message.length() <= maxMessageLength) {
        logMessageInternal(logType, message, tag);
    } else {
        maxMessageLength -= 8; // we will add counter to the beginning of the message, e. g. "(12/15) "
        int totalChunks = (int) Math.ceil((float) message.length() / maxMessageLength);
        for (int i = 1; i <= totalChunks; i++) {
            int start = (i - 1) * maxMessageLength;
            logMessageInternal(logType, "(" + i + "/" + totalChunks + ") " + message.substring(start, Math.min(start + maxMessageLength, message.length())), tag);
        }
    }
}

private static void logMessageInternal(LogType logType, String message, String tag) {
    if (message == null) {
        message = "message is null";
    }
    switch (logType) {
        case debug:
            Log.d(tag, message);
            break;
        case info:
            Log.i(tag, message);
            break;
        case warning:
            Log.w(tag, message);
            break;
        case error:
            Log.e(tag, message);
    }
}

public static void d(String debug, String tag) {
    logMessage(LogType.debug, debug, tag);
}

0

मुझे लॉगकैट की लंबाई बढ़ाने का कोई विकल्प नहीं पता है, लेकिन हम मुख्य लॉग, ईवेंट लॉग आदि जैसे विभिन्न लॉग पा सकते हैं। मुख्य लॉग में आमतौर पर सब कुछ होता है, जिसकी लंबाई 4Mb तक होती है। इसलिए आप जो खो गए हैं उसे प्राप्त करने में सक्षम हो सकते हैं। लॉग टर्मिनल में। पथ है: \ data \ logger।


0

यद्यपि अन्य प्रदान किए गए समाधान सहायक थे, मैं उनके द्वारा संतुष्ट नहीं था क्योंकि वे ऐसे मामलों को कवर नहीं करते थे जब लॉग @ b0ti द्वारा उल्लिखित LOGGER_ENTRY_MAX_LEN से दो बार से अधिक लंबा हो। इसके अलावा यहां तक ​​कि मेरा निम्नलिखित समाधान सही नहीं है क्योंकि LOGGER_ENTRY_MAX_LEN को गतिशील रूप से नहीं लाया जाता है। यदि कोई ऐसा करने का तरीका जानता है, तो मुझे टिप्पणियों में इसके बारे में सुनना अच्छा लगेगा! वैसे भी, यह वह समाधान है जो मैं अभी अपने कोड में उपयोग करता हूं:

final int loggerEntryMaxLength = 4000;
int logLength = loggerEntryMaxLength - 2 - TAG.length();
int i = 0;
while (output.length() / logLength > i) {
    int startIndex = i++ * logLength;
    int endIndex = i * logLength;
    Log.d(TAG, output.substring(startIndex, endIndex));
}
int startIndex = i * logLength;
Log.d(
        TAG,
        output.substring(
                startIndex,
                startIndex + (output.length() % logLength)
        )
);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.