When running the Runner with stdout logs (via ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1), multiline log messages (e.g. JSON objects) for some reason have a header/timestamp appended for every single line of the log. This makes parsing these logs back to a multiline payload (or e.g. JSON object) nearly impossible, as you can't just scan lines until you see a new timestamp header to work out when the multiline message ends (which is how Fluentbit, as one example of a log forwarding tool, handles multiline logs like Java stack traces).
Example output:
[RUNNER 2026-05-06 13:23:59Z INFO Runner] Using BrokerMessageListener
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] Using provided settings
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] {
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] "AgentId": 2,
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] "AgentName": "fishtin",
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] "PoolId": 1,
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] "PoolName": "Default",
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] "ServerUrl": "https://pipelinesghubeus24.actions.githubusercontent.com/REDACTED/",
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] "GitHubUrl": "https://github.com/nuclearpidgeon/actions-runner-testing",
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] "WorkFolder": "_work",
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] "UseV2Flow": true,
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] "ServerUrlV2": "https://broker.actions.githubusercontent.com/"
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] }
[RUNNER 2026-05-06 13:23:59Z INFO BrokerMessageListener] Loading Credentials
[RUNNER 2026-05-06 13:23:59Z INFO ConfigurationStore] HasCredentials()
[RUNNER 2026-05-06 13:23:59Z INFO ConfigurationStore] stored True
This is behaviour unique to the stdout logging. If the stdout logging is not enabled, the default logging into files in a _diag directory doesn't have the same line behaviour:
[2026-05-15 12:16:34Z INFO BrokerMessageListener] Using provided settings
[2026-05-15 12:16:34Z INFO BrokerMessageListener] {
"AgentId": 2,
"AgentName": "fishtin",
"PoolId": 1,
"PoolName": "Default",
"ServerUrl": "https://pipelinesghubeus24.actions.githubusercontent.com/REDACTED/",
"GitHubUrl": "https://github.com/nuclearpidgeon/actions-runner-testing",
"WorkFolder": "_work",
"UseV2Flow": true,
"ServerUrlV2": "https://broker.actions.githubusercontent.com/"
}
[2026-05-15 12:16:34Z INFO BrokerMessageListener] Loading Credentials
[2026-05-15 12:16:34Z INFO ConfigurationStore] HasCredentials()
[2026-05-15 12:16:34Z INFO ConfigurationStore] stored True
The relevant code behind this stdout-only behaviour is here:
|
var messageLines = message.Split(Environment.NewLine); |
|
foreach (var messageLine in messageLines) |
|
{ |
|
WriteHeader(source, eventType, id); |
|
WriteLine(messageLine); |
|
WriteFooter(eventCache); |
|
} |
...which was added back in late 2022 via #2291
Multiline log parsing is a problem that basically every log forwarding agent has a similar feature for handling. For some more examples:
To Reproduce
Steps to reproduce the behavior:
- Configure the Runner to target a repo
- Run Runner with no special env vars and submit a job for handling
- Observe logs in
_diag folder have no multiline prefixing
- Re-run Runner with
ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT env var set to 1 and submit another job for handling
- Observe that the logs on stdout do have this multiline prefixing
Expected behavior
Multiline logs do not have a timestamp and component prefix for every single line of the log / extra config option added to disable this bevahiour.
Runner Version and Platform
I produced the above samples using actions-runner-linux-x64-2.334.0 on Arch Linux.
When running the Runner with stdout logs (via
ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1), multiline log messages (e.g. JSON objects) for some reason have a header/timestamp appended for every single line of the log. This makes parsing these logs back to a multiline payload (or e.g. JSON object) nearly impossible, as you can't just scan lines until you see a new timestamp header to work out when the multiline message ends (which is how Fluentbit, as one example of a log forwarding tool, handles multiline logs like Java stack traces).Example output:
This is behaviour unique to the stdout logging. If the stdout logging is not enabled, the default logging into files in a
_diagdirectory doesn't have the same line behaviour:The relevant code behind this stdout-only behaviour is here:
runner/src/Runner.Common/StdoutTraceListener.cs
Lines 29 to 35 in d36839b
...which was added back in late 2022 via #2291
Multiline log parsing is a problem that basically every log forwarding agent has a similar feature for handling. For some more examples:
To Reproduce
Steps to reproduce the behavior:
_diagfolder have no multiline prefixingACTIONS_RUNNER_PRINT_LOG_TO_STDOUTenv var set to 1 and submit another job for handlingExpected behavior
Multiline logs do not have a timestamp and component prefix for every single line of the log / extra config option added to disable this bevahiour.
Runner Version and Platform
I produced the above samples using
actions-runner-linux-x64-2.334.0on Arch Linux.