Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timber.debugTree splite lose word #339

Open
imcloud opened this issue Oct 22, 2018 · 9 comments
Open

Timber.debugTree splite lose word #339

imcloud opened this issue Oct 22, 2018 · 9 comments
Labels

Comments

@imcloud
Copy link

imcloud commented Oct 22, 2018

// Split by line, then ensure each line can fit into Log's maximum length.
      for (int i = 0, length = message.length(); i < length; i++) {
        int newline = message.indexOf('\n', i);
        newline = newline != -1 ? newline : length;
        do {
          int end = Math.min(newline, i + MAX_LOG_LENGTH);
          String part = message.substring(i, end);
          if (priority == Log.ASSERT) {
            Log.wtf(tag, part);
          } else {
            Log.println(priority, tag, part);
          }
          i = end;
        } while (i < newline);
      }
// the beginning index, inclusive.
// the ending index, exclusive
// while i == 0
message.substring(0, 4000);
// while i == 1
message.substring(4001, 8001);

// lost 4000
@imcloud
Copy link
Author

imcloud commented Oct 23, 2018

and, android studio 3.2 default line size less then 4000
MAX_LOG_LENGTH should be set 3000 or other

@JakeWharton
Copy link
Owner

JakeWharton commented Oct 23, 2018 via email

@taichushouwang
Copy link

Now the latest version of Android Studio is 4.1.1。It still can't properly display more than 3000. I hope the MAX_LOG_LENGTH should change to 3000 or make it can change.

Now in my project, I extend the DebugTree, only change the MAX_LOG_LENGTH, and copy and paste the fun of log

@JakeWharton
Copy link
Owner

Sounds like a Studio bug then. File it on their project?

@imcloud
Copy link
Author

imcloud commented Dec 25, 2020

Now the latest version of Android Studio is 4.1.1。It still can't properly display more than 3000. I hope the MAX_LOG_LENGTH should change to 3000 or make it can change.

Now in my project, I extend the DebugTree, only change the MAX_LOG_LENGTH, and copy and paste the fun of log

class MyDebugTree : Timber.DebugTree() {

    private val MAX_LOG_LENGTH = 2048

    override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
        if (message.length < MAX_LOG_LENGTH) {
            if (priority == Log.ASSERT) {
                Log.wtf(tag, message)
            } else {
                Log.println(priority, tag, message)
            }
            return
        }

        // Split by line, then ensure each line can fit into Log's maximum length.
        var i = 0
        val length = message.length
        while (i < length) {
            var newline = message.indexOf('\n', i)
            newline = if (newline != -1) newline else length
            do {
                val end = Math.min(newline, i + MAX_LOG_LENGTH)
                val part = message.substring(i, end)
                if (priority == Log.ASSERT) {
                    Log.wtf(tag, part)
                } else {
                    Log.println(priority, tag, part)
                }
                i = end
            } while (i < newline)
            i = if (i == newline) i + 1 else i
        }
    }
}

我做了一些改动,这样就没问题了

@imcloud
Copy link
Author

imcloud commented Mar 10, 2021

I think I know the reason. It should be the Chinese character problem. The three byte Chinese makes the calculation error

@JakeWharton
Copy link
Owner

You're saying the kernel header is in utf-8(?) bytes but Timber is erroneously counting chars? That sounds like a plausible explanation!

@gmk57
Copy link

gmk57 commented Jun 1, 2021

The same happens for Cyrillic text, approximately half of it is lost. :(

@Neirokan
Copy link

Yes, kernel is counting text size in utf-8, so...
If you want to use the above code for simplicity, keep in mind that 1 utf-16 code unit can produce 3 utf-8 code units in worst case, not 2, and at least check for surrogate pairs.
Here's code that splits message by calculating text size in utf-8 and preserves grapheme clusters. Unfortunately, android.icu requires minSdk = 24.

import android.icu.text.BreakIterator
import android.icu.util.ULocale
import timber.log.Timber

class CountingDebugTree(private val locale: ULocale = ULocale.getDefault()) : Timber.DebugTree() {
    override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
        if (message.length <= PESSIMISTIC_MAX_LOG_LENGTH) {
            return super.log(priority, tag, message, t)
        }

        val iterator = BreakIterator.getCharacterInstance(locale)
        iterator.setText(message)

        var count = 0
        var begin = iterator.first()
        var end = begin

        while (end < message.length) {
            if (message[end] == '\n') {
                super.log(priority, tag, message.substring(begin, end), t)
                count = 0
                begin = iterator.next()
                end = iterator.next()
                continue
            }

            val next = iterator.next()
            val bytes = message.utf8Length(end, next)

            if (count + bytes > MAX_LOG_BYTES) {
                super.log(priority, tag, message.substring(begin, end), t)
                count = 0
                begin = end
            }

            count += bytes
            end = next
        }
        if (count > 0) {
            super.log(priority, tag, message.substring(begin), t)
        }
    }

    private fun String.utf8Length(from: Int, to: Int): Int {
        var i = from
        var count = 0
        while (i < to) {
            val bytes = when {
                this[i] <= '\u007F' -> 1
                this[i] <= '\u07FF' -> 2
                this[i].isHighSurrogate() -> 4
                else -> 3
            }
            count += bytes
            i += if (bytes == 4) 2 else 1
        }
        return count
    }

    companion object {
        private const val MAX_LOG_BYTES = 4000
        private const val PESSIMISTIC_MAX_LOG_LENGTH = MAX_LOG_BYTES / 3
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants