Commit graph

525 commits

Author SHA1 Message Date
Sebastiaan van Stijn
ab35df454d
remove pre-go1.17 build-tags
Removed pre-go1.17 build-tags with go fix;

    go mod init
    go fix -mod=readonly ./...
    rm go.mod

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-05-19 20:38:51 +02:00
cui fliter
f66684fdeb fix some comments
Signed-off-by: cui fliter <imcusg@gmail.com>
2023-04-25 13:39:28 +08:00
Wesley Pettit
c8f8d11ac4
awslogs: fix non-blocking log drop bug
Previously, the AWSLogs driver attempted to implement
non-blocking itself. Non-blocking is supposed to
implemented solely by the Docker RingBuffer that
wraps the log driver.

Please see issue and explanation here:
https://github.com/moby/moby/issues/45217

Signed-off-by: Wesley Pettit <wppttt@amazon.com>
2023-04-04 17:03:06 -07:00
Cory Snider
e66995d840 d/l/awslogs: fix ineffective Add in test
...flagged by golangci-lint v1.51.1 (staticcheck).

Signed-off-by: Cory Snider <csnider@mirantis.com>
2023-02-15 13:11:55 -05:00
Josh Chorlton
c12d7b6d21 upgrade to aws sdk go v2
Co-Authored-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Josh Chorlton <jchorlton@gmail.com>
Signed-off-by: Cory Snider <csnider@mirantis.com>
Signed-off-by: Josh Chorlton <jchorlton@gmail.com>
2023-01-07 17:27:31 +00:00
Sebastiaan van Stijn
155e39187c
daemon/logger/gcplogs: remove ensureHomeIfIAmStatic workaround
This function was added in b86e3bee5a to
work around an issue in os/user.Current(), which SEGFAULTS when compiling
statically with cgo enabled (see golang/go#13470).

We hit similar issues in other parts, and contributed a "osusergo" build-
tag in https://go-review.googlesource.com/c/go/+/330753. The "osusergo"
build tag must be set when compiling static binaries with cgo enabled.
If that build-tag is set, the cgo implementation for user.Current() won't
be used, and a pure-go implementation is used instead;
https://github.com/golang/go/blob/go1.19.4/src/os/user/cgo_lookup_unix.go#L5

With the above in place, we no longer need this workaround, and can remove
the ensureHomeIfIAmStatic() function.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-12-31 13:59:06 +01:00
Sebastiaan van Stijn
ad7f1a8dcc
daemon/logger: use strings.Cut()
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-12-21 11:09:01 +01:00
AdamKorcz
93fa093122
testing: move fuzzers over from OSS-Fuzz
Signed-off-by: AdamKorcz <adam@adalogics.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-11-30 17:31:03 +01:00
Sebastiaan van Stijn
98f36bba9a
Merge pull request #44398 from thaJeztah/daemon_logger_godoc
daemon/logger: fix godoc
2022-11-02 23:50:29 +01:00
Sebastiaan van Stijn
be1829f63d
daemon/logger: fix godoc
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-11-02 18:47:50 +01:00
Tianon Gravi
b76ccfef5f
Merge pull request #44289 from thaJeztah/windows_refactor_etwlogs
daemon/logger/etwlogs: rewrite to use go-winio/pkg/etw
2022-11-02 10:43:55 -07:00
Sebastiaan van Stijn
a9fa147a92
daemon/logger/etwlogs: rewrite to use go-winio/pkg/etw
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-15 14:14:18 +02:00
Sebastiaan van Stijn
533ecb44b1
daemon/logger: use strconv instead of fmt.Sprintf()
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-10-08 17:41:38 +02:00
Sebastiaan van Stijn
1515e02c8a
Merge pull request #44215 from corhere/fix-unlockosthread-pdeathsig
Stop subprocesses from getting unexpectedly killed
2022-10-06 20:08:53 +02:00
Austin Vazquez
6f435e0bb9 Update awslogs driver batching documentation.
Before this change, the awslogs collectBatch and processEvent
function documentation still referenced the batchPublishFrequency
constant which was removed in favor of the configurable log stream
forceFlushInterval member.

Signed-off-by: Austin Vazquez <macedonv@amazon.com>
2022-10-03 23:37:14 +00:00
Cory Snider
c3a6de9ec8 logger/journald: unlock OS threads
Managed containerd processes are executed with SysProcAttr.Pdeathsig set
to syscall.SIGKILL so that the managed containerd is automatically
killed along with the daemon. At least, that is the intention. In
practice, the signal is sent to the process when the creating _OS
thread_ dies! If a goroutine exits while locked to an OS thread, the Go
runtime will terminate the thread. If that thread happens to be the
same thread which the subprocess was started from, the subprocess will
be signaled. Prevent the journald driver from sometimes unintentionally
killing child processes by ensuring that all runtime.LockOSThread()
calls are paired with runtime.UnlockOSThread().

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-09-28 11:46:59 -04:00
Sebastiaan van Stijn
0695a910c6
daemon/logger: fix empty-lines (revive)
daemon/logger/loggertest/logreader.go:58:43: empty-lines: extra empty line at the end of a block (revive)
    daemon/logger/ring_test.go:119:34: empty-lines: extra empty line at the end of a block (revive)
    daemon/logger/adapter_test.go:37:12: empty-lines: extra empty line at the end of a block (revive)
    daemon/logger/adapter_test.go:41:44: empty-lines: extra empty line at the end of a block (revive)
    daemon/logger/adapter_test.go:170:9: empty-lines: extra empty line at the end of a block (revive)
    daemon/logger/loggerutils/sharedtemp_test.go:152:43: empty-lines: extra empty line at the end of a block (revive)
    daemon/logger/loggerutils/sharedtemp.go:124:117: empty-lines: extra empty line at the end of a block (revive)
    daemon/logger/syslog/syslog.go:249:87: empty-lines: extra empty line at the end of a block (revive)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-09-28 01:58:51 +02:00
Sebastiaan van Stijn
762fc76cf9
Merge pull request #44089 from thaJeztah/update_golangci_lint
golangci-lint: update to v1.49.0
2022-09-27 18:24:15 +02:00
Sebastiaan van Stijn
2f1c382a6d
golangci-lint: update to v1.49.0
Remove the "deadcode", "structcheck", and "varcheck" linters, as they are
deprecated:

    WARN [runner] The linter 'deadcode' is deprecated (since v1.49.0) due to: The owner seems to have abandoned the linter.  Replaced by unused.
    WARN [runner] The linter 'structcheck' is deprecated (since v1.49.0) due to: The owner seems to have abandoned the linter.  Replaced by unused.
    WARN [runner] The linter 'varcheck' is deprecated (since v1.49.0) due to: The owner seems to have abandoned the linter.  Replaced by unused.
    WARN [linters context] structcheck is disabled because of generics. You can track the evolution of the generics support by following the https://github.com/golangci/golangci-lint/issues/2649.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-09-23 23:31:27 +02:00
Sebastiaan van Stijn
f6b695d2fb
use consistent alias for gotest.tools/v3/assert/cmp
Make sure we use the same alias everywhere for easier finding,
and to prevent accidentally introducing duplicate imports with
different aliases for the same package.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-09-08 16:45:16 +02:00
Cory Snider
ef5b279887 logger/journald: implement --follow correctly
Implement --follow entirely correctly for the journald log reader, such
that it exits immediately upon reading back the last log message written
to the journal before the logger was closed. The impossibility of doing
so has been slightly exaggerated.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-07-25 16:41:38 -04:00
Cory Snider
e278d3f185 logger/*: fix reading w/ non-monotonic timestamps
Fix journald and logfile-powered (jsonfile, local) log readers
incorrectly filtering out messages with timestamps < Since which were
preceded by a message with a timestamp >= Since.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-07-25 16:41:38 -04:00
Cory Snider
342b44bf20 logger/journald: rewrite reader w/o cursors
Careful management of the journal read pointer is sufficient to ensure
that no entry is read more than once.

Unit test the journald logger without requiring a running journald by
using the systemd-journal-remote command to write arbitrary entries to
journal files.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-07-25 16:41:38 -04:00
Cory Snider
3e8405aa82 logger/journald: refactor cgo out of business logic
Wrap the libsystemd journal reading functionality in a more idiomatic Go
API and refactor the journald logging driver's ReadLogs implementation
to use the wrapper. Rewrite the parts of the ReadLogs implementation in
Go which were previously implemented in C as part of the cgo preamble.
Separating the business logic from the cgo minutiae should hopefully
make the code more accessible to a wider audience of developers for
reviewing the code and contributing improvements.

The structure of the ReadLogs implementation is retained with few
modifications. Any ignored errors were also ignored before the refactor;
the explicit error return values afforded by the sdjournal wrapper makes
this more obvious.

The package github.com/coreos/go-systemd/v22/sdjournal also provides a
more idiomatic Go wrapper around libsystemd. It is unsuitable for our
needs as it does not expose wrappers for the sd_journal_process and
sd_journal_get_fd functions.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-07-25 16:41:09 -04:00
Cory Snider
7ff4b64319 logger/journald: simplify control flow
Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-07-25 16:37:59 -04:00
Cory Snider
f7fe2c2290 logger/journald: follow the thread-safety rules
Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-07-25 16:37:59 -04:00
Cory Snider
12744335c0 logger/journald: simplify build constraints
Ensure the package can be imported, no matter the build constratints, by
adding an unconstrained doc.go containing a package statement.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-07-25 16:37:59 -04:00
Sebastiaan van Stijn
0e9a66d35a
logger/journald: remove journald_compat (for systemd < 209)
This was added in 6cdc4ba6cd in 2016, likely
because at the time we were still building for CentOS 6 and Ubuntu 14.04.

All currently supported distros appear to be on _at least_ 219 now, so it looks
safe to remove this;

```bash
docker run -it --rm centos:7

yum install -y systemd-devel

pkg-config 'libsystemd >= 209' && echo "OK" || echo "KO"
OK

pkg-config --print-provides 'libsystemd'
libsystemd = 219

pkg-config --print-provides 'libsystemd-journal'
libsystemd-journal = 219
```

And on a `debian:buster` (old stable)

```bash
docker run -it --rm debian:buster

apt-get update && apt-get install -y libsystemd-dev pkg-config

pkg-config 'libsystemd >= 209' && echo "OK" || echo "KO"
OK

pkg-config --print-provides 'libsystemd'
libsystemd = 241

pkg-config --print-provides 'libsystemd-journal'
Package libsystemd-journal was not found in the pkg-config search path.
Perhaps you should add the directory containing `libsystemd-journal.pc'
to the PKG_CONFIG_PATH environment variable
No package 'libsystemd-journal' found
```

OpenSUSE leap (I think that's built for s390x)

```bash
docker run -it --rm docker.io/opensuse/leap:15

zypper install -y systemd-devel

pkg-config 'libsystemd >= 209' && echo "OK" || echo "KO"
OK

pkg-config --print-provides 'libsystemd'
libsystemd = 246

pkg-config --print-provides 'libsystemd-journal'
Package libsystemd-journal was not found in the pkg-config search path.
Perhaps you should add the directory containing `libsystemd-journal.pc'
to the PKG_CONFIG_PATH environment variable
No package 'libsystemd-journal' found
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-07-20 18:48:00 +02:00
Sebastiaan van Stijn
75577fe7a8
logger/journald: fix SA4011: ineffective break statement
This was introduced in 906b979b88, which changed
a `goto` to a `break`, but afaics, the intent was still to break out of the loop.
(linter didn't catch this before because it didn't have the right build-tag set)

    daemon/logger/journald/read.go:238:4: SA4011: ineffective break statement. Did you mean to break out of the outer loop? (staticcheck)
                break // won't be able to write anything anymore
                ^

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-07-20 15:14:41 +02:00
Paweł Gronowski
2ec3e14c0f test: Add tests for logging
1. Add integration tests for the ContainerLogs API call
Each test handle a distinct case of ContainerLogs output.
- Muxed stream, when container is started without tty
- Single stream, when container is started with tty

2. Add unit test for LogReader suite that tests concurrent logging
It checks that there are no race conditions when logging concurrently
from multiple goroutines.

Co-authored-by: Cory Snider <csnider@mirantis.com>
Signed-off-by: Cory Snider <csnider@mirantis.com>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2022-06-10 09:26:17 +02:00
Sebastiaan van Stijn
3b94561db2
Merge pull request #43662 from vvoland/fix-logs-regression2
daemon/logger: Driver-scope buffer pools, bigger buffers
2022-06-07 22:04:14 +02:00
Paweł Gronowski
2463c40144 daemon/logger: Fix TestConcurrentLogging race test
The recent fix for log corruption changed the signature of the
NewLogFile and WriteLogEntry functions and the test wasn't adjusted to
this change.

Fix the test by adjusting to the new LogFile API.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2022-05-31 14:02:59 +02:00
Paweł Gronowski
d8a731c3aa daemon/logger: Increase initial buffers size
Make the allocated buffers bigger to allow better reusability and avoid
frequent reallocations.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2022-05-30 20:50:56 +02:00
Paweł Gronowski
98810847c4 daemon/logger: Put Message back as soon as possible
The Message is not needed after it is marshalled, so no need to hold it
for the entire function scope.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2022-05-30 20:50:56 +02:00
Paweł Gronowski
8fe2a68698 daemon/logger: Global buffer pools
Moved the buffer pools in json-file and local logging drivers to the
whole driver scope. It is more efficient to have a pool for the whole
driver rather than for each logger instance.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2022-05-30 20:50:56 +02:00
Sebastiaan van Stijn
4e09933aed
Merge pull request #43652 from thaJeztah/update_gotest_tools
vendor: gotest.tools v3.2.0
2022-05-30 13:00:29 +02:00
Sebastiaan van Stijn
a5f6500958
replace deprecated gotest.tools' env.Patch() with t.SetEnv()
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-05-28 12:12:39 +02:00
Paweł Gronowski
7493342926 daemon/logger: Share buffers by sync.Pool
Marshalling log messages by json-file and local drivers involved
serializing the message into a shared buffer. This caused a regression
resulting in log corruption with recent changes where Log may be called
from multiple goroutines at the same time.

Solution is to use a sync.Pool to manage the buffers used for the
serialization. Also removed the MarshalFunc, which the driver had to
expose to the LogFile so that it can marshal the message. This is now
moved entirely to the driver.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2022-05-27 16:44:06 +02:00
Cory Snider
a67e159909 daemon/logger: hold LogFile lock less on ReadLogs
Reduce the amount of time ReadLogs holds the LogFile fsop lock by
releasing it as soon as all the files are opened, before parsing the
compressed file headers.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-05-19 15:23:18 -04:00
Cory Snider
01915a725e daemon/logger: follow LogFile without file watches
File watches have been a source of complexity and unreliability in the
LogFile follow implementation, especially when combined with file
rotation. File change events can be unreliably delivered, especially on
Windows, and the polling fallback adds latency. Following across
rotations has never worked reliably on Windows. Without synchronization
between the log writer and readers, race conditions abound: readers can
read from the file while a log entry is only partially written, leading
to decode errors and necessitating retries.

In addition to the complexities stemming from file watches, the LogFile
follow implementation had complexity from needing to handle file
truncations, and (due to a now-fixed bug in the polling file watcher
implementation) evictions to unlock the log file so it could be rotated.
Log files are now always rotated, never truncated, so these situations
no longer need to be handled by the follow code.

Rewrite the LogFile follow implementation in terms of waiting until
LogFile notifies it that a new message has been written to the log file.
The LogFile informs the follower of the file offset of the last complete
write so that the follower knows not to read past that, preventing it
from attempting to decode partial messages and making retries
unnecessary. Synchronization between LogFile and its followers is used
at critical points to prevent missed notifications of writes and races
between file rotations and the follower opening files for read.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-05-19 15:22:22 -04:00
Cory Snider
6d5bc07189 daemon/logger: fix refcounting decompressed files
The refCounter used for sharing temporary decompressed log files and
tracking when the files can be deleted is keyed off the source file's
path. But the path of a log file is not stable: it is renamed on each
rotation. Consequently, when logging is configured with both rotation
and compression, multiple concurrent readers of a container's logs could
read logs out of order, see duplicates or decompress a log file which
has already been decompressed.

Replace refCounter with a new implementation, sharedTempFileConverter,
which is agnostic to the file path, keying off the source file's
identity instead. Additionally, sharedTempFileConverter handles the full
lifecycle of the temporary file, from creation to deletion. This is all
abstracted from the consumer: all the bookkeeping and cleanup is handled
behind the scenes when Close() is called on the returned reader value.
Only one file descriptor is used per temporary file, which is shared by
all readers.

A channel is used for concurrency control so that the lock can be
acquired inside a select statement. While not currently utilized, this
makes it possible to add support for cancellation to
sharedTempFileConverter in the future.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-05-19 15:22:22 -04:00
Cory Snider
49aa66b597 daemon/logger: rotate log files, never truncate
Truncating the current log file while a reader is still reading through
it results in log lines getting missed. In contrast, rotating the file
allows readers who have the file open can continue to read from it
undisturbed. Rotating frees up the file name for the logger to create a
new file in its place. This remains true even when max-file=1; the
current log file is "rotated" from its name without giving it a new one.

On POSIXy filesystem APIs, rotating the last file is straightforward:
unlink()ing a file name immediately deletes the name from the filesystem
and makes it available for reuse, even if processes have the file open
at the time. Windows on the other hand only makes the name available
for reuse once the file itself is deleted, which only happens when no
processes have it open. To reuse the file name while the file is still
in use, the file needs to be renamed. So that's what we have to do:
rotate the file to a temporary name before marking it for deletion.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-05-19 15:22:22 -04:00
Cory Snider
990b0e28ba daemon/logger/local: fix appending newlines
The json-file driver appends a newline character to log messages with
PLogMetaData.Last set, but the local driver did not. Alter the behavior
of the local driver to match that of the json-file driver.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-05-19 15:22:22 -04:00
Cory Snider
3844d1a3d1 daemon/logger: drain readers when logger is closed
The LogFile follower would stop immediately upon the producer closing.
The close signal would race the file watcher; if a message were to be
logged and the logger immediately closed, the follower could miss that
last message if the close signal (formerly ProducerGone) was to win the
race. Add logic to perform one more round of reading when the producer
is closed to catch up on any final logs.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-05-19 15:22:22 -04:00
Cory Snider
906b979b88 daemon/logger: remove ProducerGone from LogWatcher
Whether or not the logger has been closed is a property of the logger,
and only of concern to its log reading implementation, not log watchers.
The loggers and their reader implementations can communicate as they see
fit. A single channel per logger which is closed when the logger is
closed is plenty sufficient to broadcast the state to log readers, with
no extra bookeeping or synchronization required.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-05-19 15:22:22 -04:00
Cory Snider
ae5f664f4e daemon/logger: open log reader synchronously
The asynchronous startup of the log-reading goroutine made the
follow-tail tests nondeterministic. The Log calls in the tests which
were supposed to happen after the reader started reading would sometimes
execute before the reader, throwing off the counts. Tweak the ReadLogs
implementation so that the order of operations is deterministic.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-05-19 15:22:22 -04:00
Cory Snider
9aa9d6fafc daemon/logger: add test suite for LogReaders
Add an extensive test suite for validating the behavior of any
LogReader. Test the current LogFile-based implementations against it.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-05-19 15:22:21 -04:00
Cory Snider
961d32868c daemon/logger: improve jsonfilelog read benchmark
The jsonfilelog read benchmark was incorrectly reusing the same message
pointer in the producer loop. The message value would be reset after the
first call to jsonlogger.Log, resulting in all subsequent calls logging
a zero-valued message. This is not a representative workload for
benchmarking and throws off the throughput metric.

Reduce variation between benchmark runs by using a constant timestamp.

Write to the producer goroutine's error channel only on a non-nil error
to eliminate spurious synchronization between producer and consumer
goroutines external to the logger being benchmarked.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2022-05-19 15:22:21 -04:00
Eng Zer Jun
36049a04d2
test: use T.Setenv to set env vars in tests
This commit replaces `os.Setenv` with `t.Setenv` in tests. The
environment variable is automatically restored to its original value
when the test and all its subtests complete.

Reference: https://pkg.go.dev/testing#T.Setenv
Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2022-04-23 17:44:16 +08:00
Sebastiaan van Stijn
df650a1aeb
panic() instead of logrus.Fatal() in init funcs
Some packages were using `logrus.Fatal()` in init functions (which logs the error,
and (by default) calls `os.Exit(1)` after logging).

Given that logrus formatting and outputs have not yet been configured during the
initialization stage, it does not provide much benefits over a plain `panic()`.

This patch replaces some instances of `logrus.Fatal()` with `panic()`, which has
the added benefits of not introducing logrus as a dependency in some of these
packages, and also produces a stacktrace, which could help locating the problem
in the unlikely event an `init()` fails.

Before this change, an error would look like:

    $ dockerd
    FATA[0000] something bad happened

After this change, the same error looks like:

    $ dockerd
    panic: something bad happened

    goroutine 1 [running]:
      github.com/docker/docker/daemon/logger/awslogs.init.0()
        /go/src/github.com/docker/docker/daemon/logger/awslogs/cloudwatchlogs.go:128 +0x89

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-04-21 12:15:20 +02:00