Application logs mix one-line entries with multi-line ones: a stack trace or a wrapped message continues on the lines after its header. Write parse_log_events(text).
A header line is exactly: a timestamp YYYY-MM-DD HH:MM:SS, one space, a level — DEBUG, INFO, WARN or ERROR, in capitals — one space, then the message, starting at the first character of the line. Every header starts a new event.
- •Trailing whitespace is trimmed from every line (lines may end in
\r\n). - •A blank line is skipped; it belongs to nothing, but is still counted when numbering lines.
- •Any other line continues the event above it: append it to that event's message after a
\n, keeping its leading spaces. - •A non-blank line before the first header has no event to belong to: report its line number as an orphan.
Return {"events": [...], "orphans": [...]}, where each event is {"line", "ts", "level", "message"} (line is the 1-based number of its header line) and orphans is the list of 1-based line numbers, both in input order.
Python 3.13 in your browser — the standard library plus pandas and numpy; no pip installs.