Skip to content

[rescontainerocibase] Stream stdout and stderr logs#1068

Merged
cgalibern merged 2 commits into
opensvc:mainfrom
hugobrenet:fix/container-logs-stdout
Jul 17, 2026
Merged

[rescontainerocibase] Stream stdout and stderr logs#1068
cgalibern merged 2 commits into
opensvc:mainfrom
hugobrenet:fix/container-logs-stdout

Conversation

@hugobrenet

@hugobrenet hugobrenet commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix container log streaming so OpenSVC returns logs written to both stdout and
stderr by Docker and Podman workloads.

Before this change, the container executor only read stderr and explicitly
discarded stdout. Workloads such as Redis, which write their logs to stdout,
therefore returned an empty result through om ... container logs.

Root cause

The container executor only opened the command stderr pipe:

stderr, err := cmd.StderrPipe()

The command stdout was discarded:

cmd.Stdout = nil

Container runtimes preserve the stdout and stderr streams of the container
process. The docker logs command writes them to the corresponding stdout and
stderr streams of the Docker CLI.

Consequently:

  • container stdout was discarded by OpenSVC;
  • only container stderr could be returned;
  • workloads logging exclusively to stdout appeared to have no logs.

Fix

The executor now:

  • opens both stdout and stderr pipes;
  • consumes both streams concurrently;
  • forwards data from both streams through the existing log channel;
  • copies each block before sending it through the channel;
  • reacts to context cancellation;
  • waits for both streams to reach EOF;
  • closes the log channel only after both readers have completed.

The existing public interface remains unchanged:

Logs(context.Context, bool, int) (<-chan []byte, error)

Test environment

The fix was reproduced and validated on an OpenSVC single-node lab.

Node:      testnode
Object:    lab/svc/redis
Resource:  container#redis
Driver:    container.docker
Image:     redis:7-alpine
State:     up

Service status:

$ sudo om lab/svc/redis print status

lab/svc/redis                      up
└ instances
  └ testnode                       up  idle started
    └ resources
      └ container#redis  ...../..  up  docker redis:7-alpine

The Docker container is running with the json-file log driver:

Container:  lab..redis.container.redis
Log driver: json-file
TTY:        false

Reproduction before the fix

Docker contains Redis logs:

$ sudo docker logs --tail 10 lab..redis.container.redis

1:M 15 Jul 2026 04:36:33.106 * Increased maximum number of open files to 10032 (it was originally set to 1024).
1:M 15 Jul 2026 04:36:33.106 * monotonic clock: POSIX clock_gettime
1:M 15 Jul 2026 04:36:33.109 * Running mode=standalone, port=6379.
1:M 15 Jul 2026 04:36:33.109 * Server initialized
1:M 15 Jul 2026 04:36:33.109 * Loading RDB produced by version 7.4.9
1:M 15 Jul 2026 04:36:33.110 * RDB age 5534 seconds
1:M 15 Jul 2026 04:36:33.110 * RDB memory usage when created 0.93 Mb
1:M 15 Jul 2026 04:36:33.110 * Done loading RDB, keys loaded: 0, keys expired: 0.
1:M 15 Jul 2026 04:36:33.110 * DB loaded from disk: 0.000 seconds
1:M 15 Jul 2026 04:36:33.110 * Ready to accept connections tcp

However, OpenSVC returns no output:

$ sudo om lab/svc/redis container logs \
    --rid='container#redis' \
    --lines=10

$

This confirms that the logs exist in Docker but are lost in the OpenSVC
container executor.

Validation after the fix

The patched om binary was built without replacing the installed binary:

$ go build -o /tmp/om3-fix ./cmd/om

The same command now returns the Redis stdout logs:

$ sudo /tmp/om3-fix lab/svc/redis container logs \
    --rid='container#redis' \
    --lines=10

1:M 15 Jul 2026 04:36:33.106 * Increased maximum number of open files to 10032 (it was originally set to 1024).
1:M 15 Jul 2026 04:36:33.106 * monotonic clock: POSIX clock_gettime
1:M 15 Jul 2026 04:36:33.109 * Running mode=standalone, port=6379.
1:M 15 Jul 2026 04:36:33.109 * Server initialized
1:M 15 Jul 2026 04:36:33.109 * Loading RDB produced by version 7.4.9
1:M 15 Jul 2026 04:36:33.110 * RDB age 5534 seconds
1:M 15 Jul 2026 04:36:33.110 * RDB memory usage when created 0.93 Mb
1:M 15 Jul 2026 04:36:33.110 * Done loading RDB, keys loaded: 0, keys expired: 0.
1:M 15 Jul 2026 04:36:33.110 * DB loaded from disk: 0.000 seconds
1:M 15 Jul 2026 04:36:33.110 * Ready to accept connections tcp

The result now matches docker logs.

Automated regression test

A regression test starts a helper process that writes distinct messages to
stdout and stderr:

log from stdout
log from stderr

The test consumes the returned log channel and verifies that both messages are
present.

This test would fail with the previous implementation because the stdout marker
was discarded.

Validation commands

Package tests:

$ go test ./drivers/rescontainerocibase -count=1

ok github.com/opensvc/om3/v3/drivers/rescontainerocibase

Race detector:

$ CGO_ENABLED=1 go test -race \
    ./drivers/rescontainerocibase \
    -run TestExecutorDoExecRunLogs \
    -count=1

ok github.com/opensvc/om3/v3/drivers/rescontainerocibase

Static analysis:

$ go vet ./drivers/rescontainerocibase

No race was detected.

Screenshots

Before the fix

image (3)

After the fix

image (4)

@cgalibern cgalibern left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello Hugo, many thanks for this pr 👍
Can you just test the error first in the read stream function ?

Comment thread drivers/rescontainerocibase/executor.go Outdated
return
}
}
if err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May you test first the err value (move this block to the line 407)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks for the review

@cgalibern
cgalibern merged commit a450dd8 into opensvc:main Jul 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants