mirror of
https://github.com/zeromicro/go-zero.git
synced 2025-01-23 09:00:20 +08:00
chore: improve logx gzip (#3332)
This commit is contained in:
parent
da81d8f774
commit
efa6940001
40
core/logx/fs.go
Normal file
40
core/logx/fs.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package logx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var fileSys realFileSystem
|
||||||
|
|
||||||
|
type (
|
||||||
|
fileSystem interface {
|
||||||
|
Close(closer io.Closer) error
|
||||||
|
Copy(writer io.Writer, reader io.Reader) (int64, error)
|
||||||
|
Create(name string) (*os.File, error)
|
||||||
|
Open(name string) (*os.File, error)
|
||||||
|
Remove(name string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
realFileSystem struct{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (fs realFileSystem) Close(closer io.Closer) error {
|
||||||
|
return closer.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs realFileSystem) Copy(writer io.Writer, reader io.Reader) (int64, error) {
|
||||||
|
return io.Copy(writer, reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs realFileSystem) Create(name string) (*os.File, error) {
|
||||||
|
return os.Create(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs realFileSystem) Open(name string) (*os.File, error) {
|
||||||
|
return os.Open(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs realFileSystem) Remove(name string) error {
|
||||||
|
return os.Remove(name)
|
||||||
|
}
|
@ -4,7 +4,6 @@ import (
|
|||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -406,7 +405,7 @@ func (l *RotateLogger) write(v []byte) {
|
|||||||
func compressLogFile(file string) {
|
func compressLogFile(file string) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
Infof("compressing log file: %s", file)
|
Infof("compressing log file: %s", file)
|
||||||
if err := gzipFile(file); err != nil {
|
if err := gzipFile(file, fileSys); err != nil {
|
||||||
Errorf("compress error: %s", err)
|
Errorf("compress error: %s", err)
|
||||||
} else {
|
} else {
|
||||||
Infof("compressed log file: %s, took %s", file, time.Since(start))
|
Infof("compressed log file: %s, took %s", file, time.Since(start))
|
||||||
@ -421,26 +420,37 @@ func getNowDateInRFC3339Format() string {
|
|||||||
return time.Now().Format(fileTimeFormat)
|
return time.Now().Format(fileTimeFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
func gzipFile(file string) error {
|
func gzipFile(file string, fsys fileSystem) (err error) {
|
||||||
in, err := os.Open(file)
|
in, err := fsys.Open(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if e := fsys.Close(in); e != nil {
|
||||||
|
Errorf("failed to close file: %s, error: %v", file, e)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
// only remove the original file when compression is successful
|
||||||
|
err = fsys.Remove(file)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
out, err := os.Create(fmt.Sprintf("%s%s", file, gzipExt))
|
out, err := fsys.Create(fmt.Sprintf("%s%s", file, gzipExt))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer out.Close()
|
defer func() {
|
||||||
|
e := fsys.Close(out)
|
||||||
|
if err == nil {
|
||||||
|
err = e
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
w := gzip.NewWriter(out)
|
w := gzip.NewWriter(out)
|
||||||
if _, err = io.Copy(w, in); err != nil {
|
if _, err = fsys.Copy(w, in); err != nil {
|
||||||
return err
|
// failed to copy, no need to close w
|
||||||
} else if err = w.Close(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
in.Close()
|
return fsys.Close(w)
|
||||||
|
|
||||||
return os.Remove(file)
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package logx
|
package logx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -429,6 +432,70 @@ func TestRotateLoggerWithSizeLimitRotateRuleWrite(t *testing.T) {
|
|||||||
logger.write([]byte(`baz`))
|
logger.write([]byte(`baz`))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGzipFile(t *testing.T) {
|
||||||
|
err := errors.New("any error")
|
||||||
|
|
||||||
|
t.Run("gzip file open failed", func(t *testing.T) {
|
||||||
|
fsys := &fakeFileSystem{
|
||||||
|
openFn: func(name string) (*os.File, error) {
|
||||||
|
return nil, err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.ErrorIs(t, err, gzipFile("any", fsys))
|
||||||
|
assert.False(t, fsys.Removed())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("gzip file create failed", func(t *testing.T) {
|
||||||
|
fsys := &fakeFileSystem{
|
||||||
|
createFn: func(name string) (*os.File, error) {
|
||||||
|
return nil, err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.ErrorIs(t, err, gzipFile("any", fsys))
|
||||||
|
assert.False(t, fsys.Removed())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("gzip file copy failed", func(t *testing.T) {
|
||||||
|
fsys := &fakeFileSystem{
|
||||||
|
copyFn: func(writer io.Writer, reader io.Reader) (int64, error) {
|
||||||
|
return 0, err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.ErrorIs(t, err, gzipFile("any", fsys))
|
||||||
|
assert.False(t, fsys.Removed())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("gzip file last close failed", func(t *testing.T) {
|
||||||
|
var called int32
|
||||||
|
fsys := &fakeFileSystem{
|
||||||
|
closeFn: func(closer io.Closer) error {
|
||||||
|
if atomic.AddInt32(&called, 1) > 2 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.NoError(t, gzipFile("any", fsys))
|
||||||
|
assert.True(t, fsys.Removed())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("gzip file remove failed", func(t *testing.T) {
|
||||||
|
fsys := &fakeFileSystem{
|
||||||
|
removeFn: func(name string) error {
|
||||||
|
return err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Error(t, err, gzipFile("any", fsys))
|
||||||
|
assert.True(t, fsys.Removed())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("gzip file everything ok", func(t *testing.T) {
|
||||||
|
fsys := &fakeFileSystem{}
|
||||||
|
assert.NoError(t, gzipFile("any", fsys))
|
||||||
|
assert.True(t, fsys.Removed())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkRotateLogger(b *testing.B) {
|
func BenchmarkRotateLogger(b *testing.B) {
|
||||||
filename := "./test.log"
|
filename := "./test.log"
|
||||||
filename2 := "./test2.log"
|
filename2 := "./test2.log"
|
||||||
@ -480,3 +547,53 @@ func BenchmarkRotateLogger(b *testing.B) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type fakeFileSystem struct {
|
||||||
|
removed int32
|
||||||
|
closeFn func(closer io.Closer) error
|
||||||
|
copyFn func(writer io.Writer, reader io.Reader) (int64, error)
|
||||||
|
createFn func(name string) (*os.File, error)
|
||||||
|
openFn func(name string) (*os.File, error)
|
||||||
|
removeFn func(name string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeFileSystem) Close(closer io.Closer) error {
|
||||||
|
if f.closeFn != nil {
|
||||||
|
return f.closeFn(closer)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeFileSystem) Copy(writer io.Writer, reader io.Reader) (int64, error) {
|
||||||
|
if f.copyFn != nil {
|
||||||
|
return f.copyFn(writer, reader)
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeFileSystem) Create(name string) (*os.File, error) {
|
||||||
|
if f.createFn != nil {
|
||||||
|
return f.createFn(name)
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeFileSystem) Open(name string) (*os.File, error) {
|
||||||
|
if f.openFn != nil {
|
||||||
|
return f.openFn(name)
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeFileSystem) Remove(name string) error {
|
||||||
|
atomic.AddInt32(&f.removed, 1)
|
||||||
|
|
||||||
|
if f.removeFn != nil {
|
||||||
|
return f.removeFn(name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeFileSystem) Removed() bool {
|
||||||
|
return atomic.LoadInt32(&f.removed) > 0
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user