Skip to content

NetworkLogSource: lazy/streaming load for sessions exceeding MAX_DISPLAY_LINES #126

Description

@handstandsam

Context

NetworkLogSource.parse currently caps rendered events at MAX_DISPLAY_LINES = 5_000, keeping only the most recent N via takeLast. For typical web sessions (a few hundred to low thousands of events) this is invisible; for a 30-minute test on a chatty SPA hitting tens of thousands of requests, the panel only shows the last 5_000 and the rest are silently dropped from the view.

The cap was kept deliberately for the initial wiring; this issue tracks lifting it.

Why a hard cap exists

Two reasons:

  1. LazyColumn stays responsive only up to a point; rendering 50k JSON-derived rows starts to stutter on scrub.
  2. parse() materializes the full filtered list before slicing (lineSequence().filter { … }.toList().takeLast(N)) — the upper bound on memory cost is set by the cap, not by file size.

Strategies to evaluate

A) Streaming parse with a ring buffer.
Replace lineSequence().filter{}.toList().takeLast(N) with a streaming pass that maintains an ArrayDeque<ParsedLogLine> of size N. O(1) memory per line during parse instead of O(file size). Doesn't change the cap, just stops doubling memory transiently. Cheapest win; ~5 LOC.

B) Range-based windowed parse.
Parse only events whose timestampMs falls within the user's currently scrubbed window (plus a buffer on either side). Re-parse on scrub. Requires keeping the file content in memory but materializing only the visible slice. Cap effectively becomes "N events around the cursor" rather than "last N events ever." Best UX for long sessions.

C) Pre-built index file.
At capture-write time (or first-load time), build a sidecar index of (byteOffset, timestampMs) per event. Range queries become disk-seek + parse-only-visible-bytes. Rules out re-parsing the whole file on every scrub. More machinery; pairs naturally with future response-body capture work.

D) Two-pane: counter header + paginated detail.
The header always shows the true total ("12,432 events captured"). The list shows a window with paging controls. No data is hidden, but interaction shifts from "scroll forever" to "page through ranges." Low-effort, high-clarity.

Recommendation

Start with A as a free win (no API change, no behavior change for sessions under the cap), then evaluate B as a v2 that genuinely supports long sessions. C depends on broader on-disk schema changes. D is a UX call — nice to have alongside any of the above.

Estimated diff

A: ~10 LOC. B: ~80 LOC. C: ~200 LOC + on-disk schema. D: ~50 LOC of Compose.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions