log/writer.go

135 lines
2.6 KiB
Go

package log
import (
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"sync"
)
type baseWriter struct {
logw *os.File
stdw *os.File
errw *os.File
logFilename string
logPreBackupTag string
}
type cacheWriter struct {
cache bytes.Buffer
cacheing bool
cacheLock *sync.Mutex
baseWriter io.Writer
}
func NewBaseWriter(logw, stdw, errw *os.File) *baseWriter {
return &baseWriter{
logw: logw,
stdw: stdw,
errw: errw,
}
}
// OpenLogFile
func (w *baseWriter) OpenLogFile(logDir, logName string, optLogDirs []string) {
// Step 1. try get available log dir
if _, err := os.Stat(logDir); err == nil {
logDir = logDir
} else if dir, err := tryOptLogDirs(optLogDirs); err == nil {
logDir = dir
} else if err := os.Mkdir(logDir, 0755); err == nil {
logDir = logDir
} else {
errstr := fmt.Sprintf("all path not exist:\n "+
"a.[%s]\n b.[%s]\n c.[%s]\n",
logDir, "./log/", "./logs/")
panic("failed initlog:" + errstr)
}
// Step 2. open base writer logfile
filename := filepath.Join(logDir, logName+".log")
w.logFilename = filename
w.logPreBackupTag = ""
w.ReopenLogFile()
}
// ReopenLogFile
func (w *baseWriter) ReopenLogFile() {
var fil, err = os.OpenFile(w.logFilename,
os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModePerm)
if err != nil {
panic("open log file failed:" + err.Error())
}
w.logw.Close()
w.logw = fil
}
// BackupLogFile
func (w *baseWriter) TryBackupLogFile(tag string) bool {
if w.logPreBackupTag == "" {
w.logPreBackupTag = tag
return false
} else if w.logPreBackupTag == tag {
return false
}
w.logPreBackupTag = tag
newname := w.logFilename + "." + tag
if err := os.Rename(w.logFilename, newname); err != nil {
return false
}
w.ReopenLogFile()
return true
}
func NewCacheWriter(basewriter io.Writer) *cacheWriter {
return &cacheWriter{
cache: bytes.Buffer{},
cacheing: false,
cacheLock: new(sync.Mutex),
baseWriter: basewriter,
}
}
func (w *baseWriter) Write(p []byte) (n int, err error) {
if w.errw != nil {
n, err = w.errw.Write(p)
}
if w.stdw != nil {
n, err = w.stdw.Write(p)
}
if w.logw != nil {
n, err = w.logw.Write(p)
}
return n, err
}
func (w *cacheWriter) Write(p []byte) (n int, err error) {
if w.cacheing {
w.cache.Write(p)
}
return w.baseWriter.Write(p)
}
func (w *cacheWriter) GetCacheLog() string {
if w.cacheing != true {
panic("GetCacheLog MUST call after StartCacheLog called")
}
return w.cache.String()
}
func (w *cacheWriter) StartCacheLog() {
w.cacheLock.Lock()
w.cacheing = true
w.cache.Reset()
}
func (w *cacheWriter) StopCacheLog() {
w.cacheLock.Unlock()
w.cacheing = false
}