Skip to content

Commit

Permalink
prevent active log from being overwritten when agent starts (#11386)
Browse files Browse the repository at this point in the history
  • Loading branch information
lgfa29 committed Nov 15, 2021
1 parent d6c2f2e commit 5a5b44a
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 7 deletions.
3 changes: 3 additions & 0 deletions .changelog/11386.txt
@@ -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
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
@@ -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
@@ -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
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
@@ -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()
}

0 comments on commit 5a5b44a

Please sign in to comment.