henry3260 opened a new pull request, #76369: URL: https://github.com/apache/airflow/pull/76369
## Why `PodLogsConsumer._save_incomplete_log_item` guarded on a freshly built list: ```python return [sub_chunk] if [sub_chunk] else [] ``` `[sub_chunk]` is a one-element list, so the condition is always true and the empty remainder left when a stream chunk ends on `\n` is kept. That item is yielded once the stream ends, and it carries no timestamp, so `PodManager.fetch_container_logs` takes it as a continuation of the buffered message. Two things reach the task log as a result: - Every stream that ends on a newline gains a trailing newline on its last message, so the log picks up a blank line at each read boundary. - When nothing is buffered yet, the continuation branch formatted the empty buffer into the message, so a read window whose only content is empty container writes logged a literal `[base] None`. A line that genuinely has no parsable timestamp hit the same branch, so its text was logged behind a `None` prefix — and because the prefix came first, `_parse_log_level` and the group-marker check looked at `None` rather than at the real text. | Stream | Before | After | | --- | --- | --- | | `<ts> a\n`, `<ts> b\n` | `'a'`, `'b\n'` | `'a'`, `'b'` | | `<ts> \n` (only an empty container write) | `'None\n'` | nothing | | `ERROR: boom\n` (no timestamp) | `'None\nERROR: boom\n'`, at INFO | `'ERROR: boom'`, at ERROR | ## What `providers/cncf/kubernetes/src/airflow/providers/cncf/kubernetes/utils/pod_manager.py` - `_save_incomplete_log_item` now tests `sub_chunk`, so the empty remainder is dropped and no empty item is yielded once the stream ends. - The continuation branch in `fetch_container_logs` is split in two. A buffered message is still appended to; a line with no parsable timestamp that arrives before any message is buffered now opens a message of its own instead of being formatted onto the empty buffer. It is stripped of the trailing newline that `parse_log_line` leaves on an unparsable line, and a bare newline is dropped rather than emitted as an orphan `[base] ` row. - `AsyncPodManager._emit_container_logs` already guards its own continuation branch, and drops such a line; the deferrable path is left as it is. `providers/cncf/kubernetes/tests/unit/cncf/kubernetes/utils/test_pod_manager.py` - Two `test_chunks` cases for a stream that ends on a newline, with and without an earlier complete line. - `test_leading_line_without_timestamp_keeps_its_text`, parametrized over the line with and without its newline, and `test_leading_blank_line_without_timestamp_is_dropped`. Both assert on the `progress_callback` kwargs rather than on log text. - Every new case fails on `main` and passes with the fix. --- ##### Was generative AI tooling used to co-author this PR? - [X] Yes — Claude Code (Opus 5) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
