Add 4 FileWriters implementions
parent
00fcb49366
commit
f961e1bcd8
@ -0,0 +1,42 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
)
|
||||
|
||||
// AlwaysNewFileWriter create new log for every process
|
||||
type AlwaysNewFileWriter struct {
|
||||
Name string
|
||||
file *os.File
|
||||
}
|
||||
|
||||
func (w *AlwaysNewFileWriter) Write(p []byte) (n int, err error) {
|
||||
if w.file == nil {
|
||||
w.openFile()
|
||||
}
|
||||
|
||||
return w.file.Write(p)
|
||||
}
|
||||
|
||||
func (w *AlwaysNewFileWriter) openFile() (err error) {
|
||||
name := fmt.Sprintf("%s.%s", w.Name, time.Now().Format("20060102_150405"))
|
||||
|
||||
// remove symbol link if exist
|
||||
os.Remove(w.Name)
|
||||
|
||||
// create symbol
|
||||
err = os.Symlink(path.Base(name), w.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.file, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAlwaysNewFileWriter(t *testing.T) {
|
||||
log := New(&AlwaysNewFileWriter{
|
||||
Name: "/tmp/test.log",
|
||||
})
|
||||
log.SetTimeLayout("15:04:05.999")
|
||||
log.SetName("main")
|
||||
for i := 0; i < 100; i++ {
|
||||
log.Info("i = %d", i)
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type CompositeWriters []io.Writer
|
||||
|
||||
func (ws *CompositeWriters) Write(p []byte) (n int, err error) {
|
||||
for _, w := range *ws {
|
||||
n, err = w.Write(p)
|
||||
}
|
||||
return
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCompositeWriters(t *testing.T) {
|
||||
log := New(&CompositeWriters{
|
||||
os.Stdout,
|
||||
&DailyFileWriter{
|
||||
Name: "/tmp/test.log",
|
||||
},
|
||||
})
|
||||
log.SetTimeLayout("15:04:05.999")
|
||||
log.SetName("main")
|
||||
for i := 0; i < 5; i++ {
|
||||
log.Info("i = %d", i)
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DailyFileWriter create new log for every day
|
||||
type DailyFileWriter struct {
|
||||
Name string
|
||||
file *os.File
|
||||
nextDayTime int64
|
||||
}
|
||||
|
||||
func (w *DailyFileWriter) Write(p []byte) (n int, err error) {
|
||||
now := time.Now()
|
||||
|
||||
if w.file == nil {
|
||||
w.openFile(&now)
|
||||
} else if now.Unix() >= w.nextDayTime {
|
||||
w.file.Close()
|
||||
w.openFile(&now)
|
||||
}
|
||||
|
||||
return w.file.Write(p)
|
||||
}
|
||||
|
||||
func (w *DailyFileWriter) openFile(now *time.Time) (err error) {
|
||||
name := fmt.Sprintf("%s.%s", w.Name, now.Format("2006-01-02"))
|
||||
|
||||
// remove symbol link if exist
|
||||
os.Remove(w.Name)
|
||||
|
||||
// create symbol
|
||||
err = os.Symlink(path.Base(name), w.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.file, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
year, month, day := now.Date()
|
||||
w.nextDayTime = time.Date(year, month, day+1, 0, 0, 0, 0, now.Location()).Unix()
|
||||
|
||||
return nil
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDailyFileWriter(t *testing.T) {
|
||||
log := New(&DailyFileWriter{
|
||||
Name: "/tmp/test.log",
|
||||
})
|
||||
log.SetTimeLayout("15:04:05.999")
|
||||
log.SetName("main")
|
||||
for i := 0; i < 100; i++ {
|
||||
log.Info("i = %d", i)
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
// FixedSizeFileWriter create new log if log size exceed
|
||||
type FixedSizeFileWriter struct {
|
||||
Name string
|
||||
MaxSize int64
|
||||
MaxCount int
|
||||
|
||||
file *os.File
|
||||
currentSize int64
|
||||
}
|
||||
|
||||
func (w *FixedSizeFileWriter) Write(p []byte) (n int, err error) {
|
||||
if w.file == nil {
|
||||
w.openCurrentFile()
|
||||
} else if w.currentSize > w.MaxSize {
|
||||
w.file.Close()
|
||||
w.openNextFile()
|
||||
}
|
||||
|
||||
w.currentSize += int64(len(p))
|
||||
|
||||
return w.file.Write(p)
|
||||
}
|
||||
|
||||
func (w *FixedSizeFileWriter) openCurrentFile() error {
|
||||
name, err := os.Readlink(w.Name)
|
||||
if err != nil {
|
||||
name = w.getAvailableFileName()
|
||||
|
||||
// create a symlink
|
||||
err = os.Symlink(path.Base(name), w.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// convert to abs path
|
||||
name = path.Join(path.Dir(w.Name), name)
|
||||
}
|
||||
|
||||
w.file, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stat, err := w.file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.currentSize = stat.Size()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *FixedSizeFileWriter) openNextFile() (err error) {
|
||||
name := w.getAvailableFileName()
|
||||
|
||||
// remove symbol link
|
||||
err = os.Remove(w.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create symbol
|
||||
err = os.Symlink(path.Base(name), w.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.file, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.currentSize = 0
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// get available file or oldest file
|
||||
func (w *FixedSizeFileWriter) getAvailableFileName() string {
|
||||
var oldestTime int64 = math.MaxInt64
|
||||
var oldestName string
|
||||
|
||||
for i := 0; i < w.MaxCount; i++ {
|
||||
name := fmt.Sprintf("%s.%d", w.Name, i)
|
||||
stat, err := os.Stat(name)
|
||||
if err != nil {
|
||||
return name
|
||||
}
|
||||
|
||||
if fTime := stat.ModTime().Unix(); fTime < oldestTime {
|
||||
oldestTime = fTime
|
||||
oldestName = name
|
||||
}
|
||||
}
|
||||
|
||||
return oldestName
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFixedSizeFileWriter(t *testing.T) {
|
||||
log := New(&FixedSizeFileWriter{
|
||||
Name: "/tmp/test.log",
|
||||
MaxSize: 1024 * 3,
|
||||
MaxCount: 5,
|
||||
})
|
||||
log.SetTimeLayout("15:04:05.999")
|
||||
log.SetName("main")
|
||||
for i := 0; i < 100; i++ {
|
||||
log.Info("i = %d", i)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue