Skip to content

Commit fd27d19

Browse files
committed
implement client log roation
resolves #227
1 parent cdcf3ca commit fd27d19

File tree

7 files changed

+188
-4
lines changed

7 files changed

+188
-4
lines changed

cmd/device-agent/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func main() {
6262
handleSignals(programCancel)
6363

6464
logDir := filepath.Join(cfg.ConfigDir, "logs")
65-
logger.SetupLogger(cfg.LogLevel, logDir, "agent.log")
65+
logger.SetupLogger(cfg.LogLevel, logDir, "agent")
6666

6767
cfg.PopulateAgentConfiguration()
6868

cmd/helper/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func main() {
3838

3939
osConfigurator := helper.New(cfg)
4040

41-
logger.SetupLogger(cfg.LogLevel, config.LogDir, "helper.log")
41+
logger.SetupLogger(cfg.LogLevel, config.LogDir, "helper")
4242

4343
log.Infof("naisdevice-helper %s starting up", version.Version)
4444
log.Infof("configuration: %+v", cfg)

cmd/systray/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func main() {
6262
flag.Parse()
6363

6464
logDir := filepath.Join(cfg.ConfigDir, "logs")
65-
logger.SetupLogger(cfg.LogLevel, logDir, "systray.log")
65+
logger.SetupLogger(cfg.LogLevel, logDir, "systray")
6666

6767
conn, err := net.Dial("unix", cfg.GrpcAddress)
6868
if err != nil {

pkg/logger/agent_2020-12-31.log

Whitespace-only changes.

pkg/logger/logger.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,31 @@ import (
44
"io"
55
"os"
66
"path/filepath"
7+
"time"
78

89
log "github.com/sirupsen/logrus"
910
easy "github.com/t-tomalak/logrus-easy-formatter"
1011
)
1112

12-
func SetupLogger(level, logDir, filename string) {
13+
const logfileMaxAge = time.Hour * 24 * 7
14+
15+
func SetupLogger(level, logDir, name string) {
1316
err := os.MkdirAll(logDir, 0o755)
1417
if err != nil {
1518
log.Fatalf("Creating log dir: %v", err)
1619
}
1720

21+
err = deleteOldLogFiles(logDir, time.Now().Add(-logfileMaxAge))
22+
if err != nil {
23+
log.Errorf("unable to delete old log files: %v", err)
24+
}
25+
26+
// clean up old log file without date
27+
_ = os.Remove(filepath.Join(logDir, name+".log"))
28+
29+
filename := createLogFileName(name, time.Now())
1830
logFilePath := filepath.Join(logDir, filename)
31+
1932
logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o664)
2033
if err != nil {
2134
log.Fatalf("unable to open log file %s, error: %v", logFilePath, err)

pkg/logger/logger_test.go

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package logger
2+
3+
import (
4+
"os"
5+
"testing"
6+
"time"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestRotate(t *testing.T) {
12+
13+
now, err := time.Parse(time.DateOnly, "2021-01-05")
14+
15+
week := time.Hour * 24 * 7
16+
17+
tests := []struct {
18+
name string
19+
expectDelete []string
20+
expectKeep []string
21+
}{
22+
{
23+
name: "don't touch other files",
24+
expectDelete: []string{},
25+
expectKeep: []string{
26+
"other_file.log",
27+
"other_file.log",
28+
"agent_2021-01-05.log",
29+
"agent_2019-99-99.log",
30+
createLogFileName("other_systray", now.Add(-3*week)),
31+
},
32+
},
33+
{
34+
name: "keep young files",
35+
expectDelete: []string{},
36+
expectKeep: []string{
37+
createLogFileName("agent", now.Add(-time.Hour*24*2)),
38+
createLogFileName("systray", now.Add(-time.Hour*24*3)),
39+
createLogFileName("helper", now.Add(-time.Hour*24*4)),
40+
createLogFileName("helper", now.Add(-time.Hour*24*4)),
41+
},
42+
},
43+
{
44+
name: "delete old files",
45+
expectDelete: []string{
46+
createLogFileName("agent", now.Add(-2*week)),
47+
createLogFileName("systray", now.Add(-3*week)),
48+
createLogFileName("helper", now.Add(-512*week)),
49+
},
50+
expectKeep: []string{},
51+
},
52+
{
53+
name: "mix of old and new files",
54+
expectDelete: []string{
55+
createLogFileName("agent", now.Add(-2*week)),
56+
createLogFileName("systray", now.Add(-3*week)),
57+
createLogFileName("helper", now.Add(-4*week)),
58+
},
59+
expectKeep: []string{
60+
createLogFileName("agent", now.Add(-time.Hour*24*2)),
61+
createLogFileName("systray", now.Add(-time.Hour*24*3)),
62+
createLogFileName("helper", now.Add(-time.Hour*24*4)),
63+
},
64+
},
65+
}
66+
67+
for _, tt := range tests {
68+
t.Run(tt.name, func(t *testing.T) {
69+
testDir := t.TempDir()
70+
assert.NoError(t, err)
71+
72+
err := os.Chdir(testDir)
73+
assert.NoError(t, err)
74+
75+
defer os.Chdir("..")
76+
77+
for _, fileName := range tt.expectDelete {
78+
_, err = os.Create(fileName)
79+
assert.NoError(t, err)
80+
}
81+
82+
for _, fileName := range tt.expectKeep {
83+
_, err = os.Create(fileName)
84+
assert.NoError(t, err)
85+
}
86+
87+
deleteOldLogFiles(testDir, now.Add(-time.Hour*24*7))
88+
89+
logdirFiles, err := os.ReadDir(".")
90+
for _, shouldBeDeleted := range tt.expectDelete {
91+
for _, f := range logdirFiles {
92+
if f.Name() == shouldBeDeleted {
93+
t.Errorf("file %q should be deleted", shouldBeDeleted)
94+
}
95+
}
96+
}
97+
outer:
98+
for _, shouldBeKept := range tt.expectKeep {
99+
for _, f := range logdirFiles {
100+
if f.Name() == shouldBeKept {
101+
continue outer
102+
}
103+
}
104+
t.Errorf("file %q should be kept", shouldBeKept)
105+
}
106+
})
107+
}
108+
109+
}

pkg/logger/rotate.go

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package logger
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
"regexp"
8+
"time"
9+
10+
log "github.com/sirupsen/logrus"
11+
)
12+
13+
func deleteOldLogFiles(logDirPath string, treshold time.Time) error {
14+
logFiles, err := os.ReadDir(logDirPath)
15+
if err != nil {
16+
return fmt.Errorf("open log dir: %w", err)
17+
}
18+
19+
filesBeforeTreshold, err := filterOldFilesByDate(logFiles, treshold)
20+
if err != nil {
21+
return fmt.Errorf("filter old files: %w", err)
22+
}
23+
24+
for _, logFile := range filesBeforeTreshold {
25+
err := os.Remove(filepath.Join(logDirPath, logFile.Name()))
26+
if err != nil {
27+
return fmt.Errorf("remove log file: %w", err)
28+
}
29+
}
30+
31+
return nil
32+
}
33+
34+
func filterOldFilesByDate(files []os.DirEntry, treshold time.Time) ([]os.DirEntry, error) {
35+
var filesBeforeTreshold []os.DirEntry
36+
filenameFormat := regexp.MustCompile(`^(agent|helper|systray)_(\d{4}-\d{2}-\d{2})\.log$`)
37+
38+
for _, logFile := range files {
39+
matches := filenameFormat.FindAllStringSubmatch(logFile.Name(), -1)
40+
if len(matches) != 1 || len(matches[0]) != 3 {
41+
log.Debug("ignoring file: ", logFile)
42+
continue
43+
}
44+
45+
date := matches[0][2]
46+
logDate, err := time.Parse(time.DateOnly, date)
47+
if err != nil {
48+
log.Errorf("filter old log files: unable to parse date: %q, err: %v", date, err)
49+
continue
50+
}
51+
52+
if logDate.Before(treshold) {
53+
filesBeforeTreshold = append(filesBeforeTreshold, logFile)
54+
}
55+
}
56+
57+
return filesBeforeTreshold, nil
58+
}
59+
60+
func createLogFileName(prefix string, t time.Time) string {
61+
return fmt.Sprintf("%s_%s.log", prefix, t.Format(time.DateOnly))
62+
}

0 commit comments

Comments
 (0)