From dbea8c3e504f4074608ab860d9bd7bc478d525ae Mon Sep 17 00:00:00 2001 From: Dan Kortschak <90160302+efd6@users.noreply.github.com> Date: Mon, 25 Jul 2022 20:09:02 +0930 Subject: [PATCH] file: allow configuration of log filename extension (#68) --- CHANGELOG.md | 4 ++++ file/rotator.go | 21 ++++++++++++++++----- file/rotator_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1859d186..b9c53e62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- Add option to `file.NewFileRotator` to allow setting file extension. #68 + ### Changed ### Deprecated @@ -14,6 +16,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed +- Fix filename logging in `file.NewFileRotator`. #68 + ## [0.2.9] ### Changed diff --git a/file/rotator.go b/file/rotator.go index 2f423058..fed02b9e 100644 --- a/file/rotator.go +++ b/file/rotator.go @@ -18,6 +18,7 @@ package file import ( + "errors" "fmt" "os" "path/filepath" @@ -25,8 +26,6 @@ import ( "strconv" "sync" "time" - - "errors" ) const ( @@ -55,6 +54,7 @@ type Rotator struct { triggers []trigger filename string + extension string maxSizeBytes uint maxBackups uint interval time.Duration @@ -84,6 +84,14 @@ func MaxSizeBytes(n uint) RotatorOption { } } +// Extension configures the file extension to use for the log file. +// The default is "ndjson". +func Extension(ext string) RotatorOption { + return func(r *Rotator) { + r.extension = ext + } +} + // MaxBackups configures the maximum number of backup files to save (not // counting the active file). The upper limit is 1024 on this value is. // The default is 7. @@ -142,6 +150,8 @@ func WithClock(clock clock) RotatorOption { // NewFileRotator returns a new Rotator. func NewFileRotator(filename string, options ...RotatorOption) (*Rotator, error) { r := &Rotator{ + filename: filename, + extension: "ndjson", maxSizeBytes: 10 * 1024 * 1024, // 10 MiB maxBackups: 7, permissions: 0600, @@ -168,7 +178,7 @@ func NewFileRotator(filename string, options ...RotatorOption) (*Rotator, error) return nil, errors.New("the minimum time interval for log rotation is 1 second") } - r.rot = newDateRotater(r.log, filename, r.clock) + r.rot = newDateRotater(r.log, filename, r.extension, r.clock) shouldRotateOnStart := r.rotateOnStartup if _, err := os.Stat(r.rot.ActiveFile()); os.IsNotExist(err) { @@ -180,6 +190,7 @@ func NewFileRotator(filename string, options ...RotatorOption) (*Rotator, error) if r.log != nil { r.log.Debugw("Initialized file rotator", "filename", r.filename, + "extension", r.extension, "max_size_bytes", r.maxSizeBytes, "max_backups", r.maxBackups, "permissions", r.permissions, @@ -408,12 +419,12 @@ type dateRotator struct { logOrderCache map[string]logOrder } -func newDateRotater(log Logger, filename string, clock clock) rotater { +func newDateRotater(log Logger, filename, extension string, clock clock) rotater { d := &dateRotator{ log: log, clock: clock, filenamePrefix: filename + "-", - extension: ".ndjson", + extension: "." + extension, format: DateFormat, logOrderCache: make(map[string]logOrder), } diff --git a/file/rotator_test.go b/file/rotator_test.go index 46b8b950..0cc6d020 100644 --- a/file/rotator_test.go +++ b/file/rotator_test.go @@ -254,6 +254,44 @@ func TestRotate(t *testing.T) { AssertDirContents(t, dir, secondFile, thirdFile) } +func TestRotateExtension(t *testing.T) { + dir := t.TempDir() + + const ( + logname = "beatname" + extension = "log" + ) + filename := filepath.Join(dir, logname) + + c := &testClock{time.Date(2021, 11, 11, 0, 0, 0, 0, time.Local)} + r, err := file.NewFileRotator(filename, file.Extension(extension), file.MaxBackups(1), file.WithClock(c)) + if err != nil { + t.Fatal(err) + } + defer r.Close() + + WriteMsg(t, r) + + firstFile := fmt.Sprintf("%s-%s."+extension, logname, c.Now().Format(file.DateFormat)) + AssertDirContents(t, dir, firstFile) + + c.time = time.Date(2021, 11, 13, 0, 0, 0, 0, time.Local) + secondFile := fmt.Sprintf("%s-%s."+extension, logname, c.Now().Format(file.DateFormat)) + + Rotate(t, r) + WriteMsg(t, r) + + AssertDirContents(t, dir, firstFile, secondFile) + + c.time = time.Date(2021, 11, 15, 0, 0, 0, 0, time.Local) + thirdFile := fmt.Sprintf("%s-%s."+extension, logname, c.Now().Format(file.DateFormat)) + + Rotate(t, r) + WriteMsg(t, r) + + AssertDirContents(t, dir, secondFile, thirdFile) +} + func CreateFile(t *testing.T, filename string) { t.Helper() f, err := os.Create(filename)