MailHog/vendor/github.com/ian-kent/go-log/appenders/rollingfile.go
2016-08-10 07:56:48 +01:00

122 lines
2.3 KiB
Go

package appenders
import (
"fmt"
"github.com/ian-kent/go-log/layout"
"github.com/ian-kent/go-log/levels"
"os"
"strconv"
"strings"
"sync"
)
type rollingFileAppender struct {
Appender
layout layout.Layout
MaxFileSize int64
MaxBackupIndex int
filename string
file *os.File
append bool
writeMutex sync.Mutex
bytesWritten int64
}
func RollingFile(filename string, append bool) *rollingFileAppender {
a := &rollingFileAppender{
layout: layout.Default(),
MaxFileSize: 104857600,
MaxBackupIndex: 1,
append: append,
bytesWritten: 0,
}
err := a.SetFilename(filename)
if err != nil {
fmt.Printf("Error opening file: %s\n", err)
return nil
}
return a
}
func (a *rollingFileAppender) Close() {
if a.file != nil {
a.file.Close()
a.file = nil
}
}
func (a *rollingFileAppender) Write(level levels.LogLevel, message string, args ...interface{}) {
m := a.Layout().Format(level, message, args...)
if !strings.HasSuffix(m, "\n") {
m += "\n"
}
a.writeMutex.Lock()
a.file.Write([]byte(m))
a.bytesWritten += int64(len(m))
if a.bytesWritten >= a.MaxFileSize {
a.bytesWritten = 0
a.rotateFile()
}
a.writeMutex.Unlock()
}
func (a *rollingFileAppender) Layout() layout.Layout {
return a.layout
}
func (a *rollingFileAppender) SetLayout(layout layout.Layout) {
a.layout = layout
}
func (a *rollingFileAppender) Filename() string {
return a.filename
}
func (a *rollingFileAppender) SetFilename(filename string) error {
if a.filename != filename || a.file == nil {
a.closeFile()
a.filename = filename
err := a.openFile()
return err
}
return nil
}
func (a *rollingFileAppender) rotateFile() {
a.closeFile()
lastFile := a.filename + "." + strconv.Itoa(a.MaxBackupIndex)
if _, err := os.Stat(lastFile); err == nil {
os.Remove(lastFile)
}
for n := a.MaxBackupIndex; n > 0; n-- {
f1 := a.filename + "." + strconv.Itoa(n)
f2 := a.filename + "." + strconv.Itoa(n+1)
os.Rename(f1, f2)
}
os.Rename(a.filename, a.filename+".1")
a.openFile()
}
func (a *rollingFileAppender) closeFile() {
if a.file != nil {
a.file.Close()
a.file = nil
}
}
func (a *rollingFileAppender) openFile() error {
mode := os.O_WRONLY | os.O_APPEND | os.O_CREATE
if !a.append {
mode = os.O_WRONLY | os.O_CREATE
}
f, err := os.OpenFile(a.filename, mode, 0666)
a.file = f
return err
}