Skip to content
Merged
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
43 changes: 27 additions & 16 deletions lib/logging/logging.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SILVER - Service Wrapper
//
// Copyright (c) 2014 PaperCut Software http://www.papercut.com/
// Copyright (c) 2014-2026 PaperCut Software http://www.papercut.com/
// Use of this source code is governed by an MIT or GPL Version 2 license.
// See the project's LICENSE file for more information.
//
Expand Down Expand Up @@ -53,6 +53,7 @@ type rollingFile struct {
bytesSinceLastFlush int64
currentSize int64
flusher *flusher
registered bool
}

type flusher struct {
Expand All @@ -71,13 +72,11 @@ type logWriter struct {

// custom Write to add timestamps with custom format
func (w logWriter) Write(bytes []byte) (int, error) {
timestamp := time.Now().Format(w.timeformat) + " "
n1, err := io.WriteString(w.Writer, timestamp)
if err != nil {
return n1, err
}
n2, err := w.Writer.Write(bytes)
return n1 + n2, err
// This buffer will be escaped to the heap since it is used for an argument of io.Writer.
// However, no additional allocation will occur unless the message length exceeds 4096 bytes.
var buffer [4096]byte
b := append(time.Now().AppendFormat(buffer[:0], w.timeformat), ' ')
return w.Writer.Write(append(b, bytes...))
}

func (f *flusher) run(rf *rollingFile) {
Expand Down Expand Up @@ -120,7 +119,10 @@ func (rf *rollingFile) Write(p []byte) (n int, err error) {
defer rf.Unlock()

if rf.currentSize+int64(len(p)) >= rf.maxSize {
rf.roll()
err = rf.roll()
if err != nil {
return
}
}
n, err = rf.bufWriter.Write(p)
rf.currentSize += int64(n)
Expand Down Expand Up @@ -149,24 +151,32 @@ func (rf *rollingFile) open() error {
return err
}
rf.currentSize = finfo.Size()
openRollingFiles = append(openRollingFiles, rf)
if !rf.registered {
openRollingFiles = append(openRollingFiles, rf)
rf.registered = true
}
return nil
}

func (rf *rollingFile) roll() error {
if rf.file == nil {
return rf.open()
}
rf.bufWriter.Flush()
name := rf.file.Name()
rf.file.Close()
rf.file = nil

// Start from the last backup file and move everything back by 1 step
for i := rf.maxBackupFiles; i > 0; i-- {
var renameFrom, renameTo string

if i == 1 {
renameFrom = rf.file.Name() // Original file
renameFrom = name // Original file
} else {
renameFrom = fmt.Sprintf("%s.%d", rf.file.Name(), i-1)
renameFrom = fmt.Sprintf("%s.%d", name, i-1)
}
renameTo = fmt.Sprintf("%s.%d", rf.file.Name(), i)
renameTo = fmt.Sprintf("%s.%d", name, i)

if err := os.Rename(renameFrom, renameTo); err == nil || errors.Is(err, os.ErrNotExist) {
// Continue if no error or if the error is 'file not found'
Expand All @@ -175,15 +185,14 @@ func (rf *rollingFile) roll() error {
// For any other error.
fmt.Fprintf(os.Stderr, "ERROR: Error renaming %s to %s. %v\n", renameFrom, renameTo, err)
}

}

// Reopen a new log file for writing
return rf.open()
}

func openLogFile(name string, owner string) (f *os.File, err error) {
f, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
f, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644)
if err != nil {
return
}
Expand Down Expand Up @@ -224,7 +233,9 @@ func NewFileLoggerWithMaxSize(file string, owner string, maxSize int64, maxBacku
func CloseAllOpenFileLoggers() {
for _, rf := range openRollingFiles {
rf.bufWriter.Flush()
rf.file.Close()
if rf.file != nil {
rf.file.Close()
}
}
openRollingFiles = []*rollingFile{}
}
Expand Down