Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prevent active log from being overwritten when agent starts #11386

Merged
merged 4 commits into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/11386.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
agent: Fixed an issue that could cause previous log lines to be overwritten
```
17 changes: 11 additions & 6 deletions command/agent/log_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,23 @@ func (l *logFile) fileNamePattern() string {
}

func (l *logFile) openNew() error {
createTime := now()
newfilePath := filepath.Join(l.logPath, l.fileName)
// Try creating a file. We truncate the file because we are the only authority to write the logs
filePointer, err := os.OpenFile(newfilePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0640)

// Try creating or opening the active log file. Since the active log file
// always has the same name, append log entries to prevent overwriting
// previous log data.
filePointer, err := os.OpenFile(newfilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0640)
if err != nil {
return err
}
stat, err := filePointer.Stat()
if err != nil {
return err
}

l.FileInfo = filePointer
// New file, new bytes tracker, new creation time :)
l.LastCreated = createTime
l.BytesWritten = 0
l.BytesWritten = stat.Size()
l.LastCreated = l.createTime(stat)
return nil
}

Expand Down
16 changes: 16 additions & 0 deletions command/agent/log_file_bsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//go:build darwin || freebsd || netbsd || openbsd
// +build darwin freebsd netbsd openbsd

package agent

import (
"os"
"syscall"
"time"
)

func (l *logFile) createTime(stat os.FileInfo) time.Time {
stat_t := stat.Sys().(*syscall.Stat_t)
createTime := stat_t.Ctimespec
return time.Unix(createTime.Sec, createTime.Nsec)
}
17 changes: 17 additions & 0 deletions command/agent/log_file_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//go:build dragonfly || linux || solaris
// +build dragonfly linux solaris

package agent

import (
"os"
"syscall"
"time"
)

func (l *logFile) createTime(stat os.FileInfo) time.Time {
stat_t := stat.Sys().(*syscall.Stat_t)
createTime := stat_t.Ctim
// Sec and Nsec are int32 in 32-bit architectures.
return time.Unix(int64(createTime.Sec), int64(createTime.Nsec)) //nolint:unconvert
}
22 changes: 21 additions & 1 deletion command/agent/log_file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,33 @@ func TestLogFile_openNew(t *testing.T) {
require.NoError(err)
defer os.Remove(tempDir)

logFile := logFile{fileName: testFileName, logPath: tempDir, duration: testDuration}
filt := LevelFilter()
filt.MinLevel = logutils.LogLevel("INFO")
logFile := logFile{
logFilter: filt,
fileName: testFileName,
logPath: tempDir,
MaxBytes: testBytes,
duration: 24 * time.Hour,
}
require.NoError(logFile.openNew())

_, err = ioutil.ReadFile(logFile.FileInfo.Name())
require.NoError(err)

require.Equal(logFile.FileInfo.Name(), filepath.Join(tempDir, testFileName))

// Check if create time and bytes written are kept when opening the active
// log file again.
bytesWritten, err := logFile.Write([]byte("test"))
require.NoError(err)

time.Sleep(2 * time.Second)
require.NoError(logFile.openNew())

timeDelta := time.Now().Sub(logFile.LastCreated)
require.GreaterOrEqual(timeDelta, 2*time.Second)
require.Equal(logFile.BytesWritten, int64(bytesWritten))
}

func TestLogFile_byteRotation(t *testing.T) {
Expand Down
14 changes: 14 additions & 0 deletions command/agent/log_file_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package agent

import (
"os"
"time"
)

func (l *logFile) createTime(stat os.FileInfo) time.Time {
// Use `ModTime` as an approximation if the exact create time is not
// available.
// On Windows, the file create time is not updated after the active log
// rotates, so use `ModTime` as an approximation as well.
return stat.ModTime()
}