diff --git a/app/androidApp/src/main/kotlin/com/example/devupdater/DevLog.kt b/app/androidApp/src/main/kotlin/com/example/devupdater/DevLog.kt index 727fd78..c4839af 100644 --- a/app/androidApp/src/main/kotlin/com/example/devupdater/DevLog.kt +++ b/app/androidApp/src/main/kotlin/com/example/devupdater/DevLog.kt @@ -193,7 +193,7 @@ fun forwardDevLog( val status = devLogStatus(resolver, authority) ?: return DevLogForward(null, 0) val stored = devLogCursor(context, key, component) val since = if (status.newestSeq >= 0 && status.newestSeq + 1 < stored) 0 else stored - val lines = devLogLines(resolver, authority, since) + val lines = devLogLines(resolver, authority, since).take(MAX_LINES_PER_POLL) if (lines.isEmpty()) { // Still worth writing back, so a reset is not re-decided every // second while an app that restarted says nothing. @@ -215,6 +215,18 @@ fun forwardDevLog( return DevLogForward(status, lines.size) } +/** + * How much one poll will forward, leaving the rest for the next one. + * + * An app's ring can hold thousands of lines, and two things routinely hand this the whole of it at + * once: the first poll after the tab opens, and every restart of the app being read, since an + * in-memory ring starts again at zero. Unbounded, that is one request, one append and one redraw of + * the whole log per second — measured on the emulator as an ANR in this app while the app it was + * reading crash-looped. The cursor advances by what was actually sent, so nothing is lost; a + * backlog simply drains over a few polls. + */ +private const val MAX_LINES_PER_POLL = 500 + /** What one poll found: the ring as a whole, and how many lines it forwarded. */ data class DevLogForward(val status: DevLogStatus?, val sent: Int)