Skip to content

Multiline runner stdout logs are extremely difficult to parse due to repeated line headers #4423

@nuclearpidgeon

Description

@nuclearpidgeon

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:

  1. Configure the Runner to target a repo
  2. Run Runner with no special env vars and submit a job for handling
  3. Observe logs in _diag folder have no multiline prefixing
  4. Re-run Runner with ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT env var set to 1 and submit another job for handling
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions