Skip to content

Commit 484d04b

Browse files
yzjyzj
authored andcommitted
add log configuration And ingore linter G302
1 parent 949046a commit 484d04b

3 files changed

Lines changed: 264 additions & 1 deletion

File tree

.github/workflows/actions.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
- name: golangci-lint
1515
uses: reviewdog/action-golangci-lint@v1
1616
with:
17-
golangci_lint_flags: "--enable-all --timeout=10m --exclude-use-default=false --tests=false --disable=gochecknoinits,gochecknoglobals,exhaustive,nakedret,wrapcheck"
17+
golangci_lint_flags: "--enable-all --timeout=10m --exclude-use-default=false --tests=false --disable=gochecknoinits,gochecknoglobals,exhaustive,nakedret,wrapcheck -D G302"
1818

1919
test:
2020
name: test

log/logger.go

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@
1818
package log
1919

2020
import (
21+
"compress/gzip"
2122
"errors"
2223
"fmt"
2324
"io"
25+
"io/ioutil"
2426
"os"
2527
"path/filepath"
2628
"runtime/debug"
29+
"sort"
30+
"strconv"
2731
"strings"
2832
"sync"
2933
"time"
@@ -205,6 +209,7 @@ func (l *Logger) start() error {
205209
l.create = time.Now()
206210
}
207211
l.writer = file
212+
l.mill()
208213
l.once.Do(l.startRotate) // start rotate, only once
209214
}
210215
}
@@ -247,6 +252,7 @@ func (l *Logger) handler() {
247252
}
248253
}
249254
case buf := <-l.writeBufferChan:
255+
250256
l.Write(buf.Bytes())
251257
PutLogBuffer(buf)
252258
}
@@ -276,6 +282,7 @@ func (l *Logger) reopen() error {
276282
if err := closer.Close(); err != nil {
277283
fmt.Fprintf(os.Stderr, "logger %s close error when restart, error: %v", l.output, err)
278284
}
285+
l.mill()
279286
return l.start()
280287
}
281288
return ErrReopenUnsupported
@@ -471,3 +478,203 @@ func parseSyslogAddress(location string) *syslogAddress {
471478

472479
return nil
473480
}
481+
482+
const (
483+
compressSuffix = ".gz"
484+
)
485+
486+
// millRunOnce performs compression and removal of stale log files.
487+
// Log files are compressed if enabled via configuration and old log
488+
// files are removed, keeping at most l.MaxBackups files, as long as
489+
// none of them are older than MaxAge.
490+
func (l *Logger) millRunOnce() error {
491+
files, err := l.oldLogFiles()
492+
if err != nil {
493+
return err
494+
}
495+
496+
compress, remove := l.screeningCompressFile(files)
497+
498+
for _, f := range remove {
499+
_ = os.Remove(filepath.Join(l.dir(), f.FileName))
500+
}
501+
502+
for _, f := range compress {
503+
var fnCompress string
504+
fnCompress, err = l.findCompressFile(f.FileName)
505+
if err != nil {
506+
return err
507+
}
508+
errCompress := l.compressLogFile(f.FileName, fnCompress)
509+
if err != nil && errCompress != nil {
510+
err = errCompress
511+
}
512+
}
513+
514+
return err
515+
}
516+
517+
func (l *Logger) screeningCompressFile(files []LoggerInfo) (compress, remove []LoggerInfo) {
518+
resFiles, removeByMaxAge := l.screeningCompressFileByMaxAge(files)
519+
resFiles, remove = l.screeningCompressFileByMaxBackups(resFiles, removeByMaxAge)
520+
521+
if l.roller.Compress {
522+
for i := range resFiles {
523+
if !strings.HasSuffix(resFiles[i].FileName, compressSuffix) {
524+
compress = append(compress, resFiles[i])
525+
}
526+
}
527+
}
528+
return
529+
}
530+
531+
func (l *Logger) screeningCompressFileByMaxAge(files []LoggerInfo) (resFiles, remove []LoggerInfo) {
532+
if l.roller.MaxAge > 0 {
533+
diff := time.Duration(int64(maxRotateHour*time.Hour) * int64(l.roller.MaxAge))
534+
cutoff := time.Now().Add(-1 * diff)
535+
536+
for i := range files {
537+
if files[i].CreateTime.Before(cutoff) {
538+
remove = append(remove, files[i])
539+
} else {
540+
resFiles = append(resFiles, files[i])
541+
}
542+
}
543+
} else {
544+
resFiles = files
545+
}
546+
return
547+
}
548+
549+
func (l *Logger) screeningCompressFileByMaxBackups(files, remove []LoggerInfo) (resFiles, resRemove []LoggerInfo) {
550+
if l.roller.MaxBackups > 0 && l.roller.MaxBackups < len(files) {
551+
preserved := make(map[string]bool)
552+
553+
for i := range files {
554+
// Only count the uncompressed log file or the
555+
// compressed log file, not both.
556+
fn := files[i].FileName
557+
558+
preserved[strings.TrimSuffix(fn, compressSuffix)] = true
559+
560+
if len(preserved) > l.roller.MaxBackups {
561+
remove = append(remove, files[i])
562+
} else {
563+
resFiles = append(resFiles, files[i])
564+
}
565+
}
566+
} else {
567+
resFiles = files
568+
}
569+
resRemove = remove
570+
return
571+
}
572+
573+
func (l *Logger) findCompressFile(fileName string) (string, error) {
574+
num := 1
575+
statName := fileName
576+
577+
for i := 0; i < 10; i++ {
578+
if _, err := os.Stat(l.dir() + statName + compressSuffix); os.IsNotExist(err) {
579+
return statName + compressSuffix, nil
580+
}
581+
statName = fileName + "." + strconv.Itoa(num)
582+
num++
583+
}
584+
return fileName, errors.New("findCompressFile failed")
585+
}
586+
587+
func (l *Logger) mill() {
588+
if l.roller.MaxBackups != 0 || l.roller.MaxAge != 0 || l.roller.Compress {
589+
_ = l.millRunOnce()
590+
}
591+
}
592+
593+
// oldLogFiles returns the list of backup log files stored in the same
594+
// directory as the current log file, sorted by ModTime
595+
func (l *Logger) oldLogFiles() ([]LoggerInfo, error) {
596+
files, err := ioutil.ReadDir(l.dir())
597+
if err != nil {
598+
return nil, err
599+
}
600+
logFiles := []LoggerInfo{}
601+
602+
for _, f := range files {
603+
if f.IsDir() {
604+
continue
605+
}
606+
if !strings.HasPrefix(f.Name(), filepath.Base(l.output)+".") {
607+
continue
608+
}
609+
//use modTime replace createTime
610+
logFiles = append(logFiles, LoggerInfo{*l.roller, f.Name(), f.ModTime()})
611+
}
612+
sort.Sort(byFormatTime(logFiles))
613+
614+
return logFiles, nil
615+
}
616+
617+
// dir returns the directory for the current filename.
618+
func (l *Logger) dir() string {
619+
return filepath.Dir(l.output)
620+
}
621+
622+
// compressLogFile compresses the given log file, removing the
623+
// uncompressed log file if successful.
624+
func (l *Logger) compressLogFile(srcFile, dstFile string) error {
625+
f, err := os.Open(filepath.Join(l.dir(), filepath.Clean(srcFile)))
626+
if err != nil {
627+
return err
628+
}
629+
630+
defer func() {
631+
_ = f.Close()
632+
}()
633+
634+
gzf, err := os.OpenFile(filepath.Join(l.dir(), filepath.Clean(dstFile)), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
635+
if err != nil {
636+
return err
637+
}
638+
639+
defer func() {
640+
_ = gzf.Close()
641+
if err != nil {
642+
_ = os.Remove(filepath.Join(l.dir(), filepath.Clean(dstFile)))
643+
}
644+
}()
645+
646+
gz := gzip.NewWriter(gzf)
647+
648+
if _, err = io.Copy(gz, f); err != nil {
649+
return err
650+
}
651+
652+
if err = gz.Close(); err != nil {
653+
return err
654+
}
655+
656+
if err = gzf.Close(); err != nil {
657+
return err
658+
}
659+
660+
if err = f.Close(); err != nil {
661+
return err
662+
}
663+
664+
return os.Remove(filepath.Join(l.dir(), filepath.Clean(srcFile)))
665+
}
666+
667+
// byFormatTime sorts by newest time formatted in the name.
668+
type byFormatTime []LoggerInfo
669+
670+
func (b byFormatTime) Less(i, j int) bool {
671+
return b[i].CreateTime.After(b[j].CreateTime)
672+
}
673+
674+
func (b byFormatTime) Swap(i, j int) {
675+
b[i], b[j] = b[j], b[i]
676+
}
677+
678+
func (b byFormatTime) Len() int {
679+
return len(b)
680+
}

log/logger_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,3 +400,59 @@ WAIT:
400400
t.Logf("received %d reopens", reopens)
401401
close(l.stopRotate)
402402
}
403+
404+
func TestLogRollerTimeAndCompress(t *testing.T) {
405+
logName := "/tmp/mosn_bench/defaultCompress.log"
406+
rollerName := logName + "." + time.Now().Format("2006-01-02_15")
407+
os.Remove(logName)
408+
os.Remove(rollerName)
409+
// replace rotate interval for test
410+
doRotate = testRotateByKeep
411+
defer func() {
412+
doRotate = testRotateByKeep
413+
}()
414+
logger, err := GetOrCreateLogger(logName, &Roller{MaxTime: 2, Handler: rollerHandler, Compress: true})
415+
if err != nil {
416+
t.Fatal(err)
417+
}
418+
// 1111 will be rotated to rollerName
419+
logger.Print(newLogBufferString("1111111"), false)
420+
time.Sleep(2 * time.Second)
421+
// 2222 will be writed in logName
422+
logger.Print(newLogBufferString("2222222"), false)
423+
time.Sleep(1 * time.Second)
424+
logger.Close() // stop the rotate
425+
426+
if !exists(rollerName + compressSuffix) {
427+
t.Fatalf("compress is failed")
428+
}
429+
}
430+
431+
func testRotateByKeep(l *Logger, interval time.Duration) {
432+
doRotateFunc(l, 1*time.Second)
433+
}
434+
func TestLogRollerTimeAndKeep(t *testing.T) {
435+
logName := "/tmp/mosn_bench/defaultKeep.log"
436+
rollerName := logName + "." + time.Now().Format("2006-01-02_15")
437+
os.Remove(logName)
438+
os.Remove(rollerName)
439+
// replace rotate interval for test
440+
doRotate = testRotateByKeep
441+
defer func() {
442+
doRotate = testRotateByKeep
443+
}()
444+
logger, err := GetOrCreateLogger(logName, &Roller{MaxTime: 2, Handler: rollerHandler, MaxBackups: 1})
445+
if err != nil {
446+
t.Fatal(err)
447+
}
448+
logger.Print(newLogBufferString("1111111"), false)
449+
time.Sleep(2 * time.Second)
450+
logger.Print(newLogBufferString("2222222"), false)
451+
time.Sleep(2 * time.Second)
452+
logger.Print(newLogBufferString("3333333"), false)
453+
time.Sleep(1 * time.Second)
454+
logger.Close() // stop the rotate
455+
if exists(rollerName) {
456+
t.Fatalf(" %s is exists", rollerName)
457+
}
458+
}

0 commit comments

Comments
 (0)