You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Streamed log redirection guesses levels from any substring and drops in-flight lines on async stop #1180
Two differences from the JS client in StreamedLog / StreamedLogAsync.
Log level. Python logs each redirected message at a level guessed by searching the whole message for CRITICAL, FATAL, ERROR, WARN, and so on, in that order (_streamed_log.py#L98-L108). An info line such as INFO Saved ERROR_PAGE screenshot is logged as ERROR, and a multi-line message gets one level from whatever word appears first in the list. JS logs every line at INFO, on the grounds that the original level is not available (resource_clients/log.ts#L388-L392).
Stopping. StreamedLogAsync.stop() cancels the task at once (_streamed_log.py#L290-L305). ActorClientAsync.call() stops the redirection right after the run finishes, so the run's last lines can be lost if they are still on their way. The sync stop() closes the stream and joins the thread for up to 5 s, and the thread processes the next chunk before it exits (#L159-L183). JS waits up to 1 s for lines in flight before aborting (log.ts#L254-L272).
Recommendation
Read the level only from the level token that follows the timestamp in the Apify log format (for example 2026-10-16T12:00:00.000Z ERROR ...), and fall back to INFO when there is none. Give StreamedLogAsync.stop() a short grace period (1 s, as in JS) for the stream to end before cancelling.
Activity