Skip to content

Commit 6ab30ea

Browse files
yzjyzj
authored andcommitted
first log
1 parent 949046a commit 6ab30ea

1 file changed

Lines changed: 271 additions & 1 deletion

File tree

log/logger.go

Lines changed: 271 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
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+
"strconv"
2730
"strings"
2831
"sync"
2932
"time"
@@ -73,6 +76,9 @@ type Logger struct {
7376
reopenChan chan struct{}
7477
closeChan chan struct{}
7578
writeBufferChan chan LogBuffer
79+
size int64
80+
millCh chan struct{}
81+
mu sync.Mutex
7682
}
7783

7884
type LoggerInfo struct {
@@ -181,13 +187,36 @@ func (l *Logger) start() error {
181187
}
182188
l.writer = writer
183189
} else { // write to file
190+
fmt.Println(l.output)
184191
if err := os.MkdirAll(filepath.Dir(l.output), 0755); err != nil {
185192
return err
186193
}
187194
file, err := os.OpenFile(l.output, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
188195
if err != nil {
189196
return err
190197
}
198+
199+
if fileInfo, err := os.Stat(l.output); err == nil {
200+
l.size = fileInfo.Size()
201+
}
202+
203+
//if l.roller.MaxBackups != 0 {
204+
// fileInfoList, err := ioutil.ReadDir(filepath.Dir(l.output))
205+
// if err != nil {
206+
// return err
207+
// }
208+
// logFilesNum := 0
209+
// for i := range fileInfoList {
210+
// if strings.HasPrefix(fileInfoList[i].Name(), strings.TrimSuffix(path.Base(l.output), path.Ext(path.Base(l.output)))) {
211+
// logFilesNum++
212+
// }
213+
// }
214+
// if l.roller.MaxBackups <= logFilesNum {
215+
// l.writer = file
216+
// break
217+
// }
218+
//}
219+
191220
if l.roller.MaxTime == 0 {
192221
file.Close()
193222
l.roller.Filename = l.output
@@ -247,6 +276,7 @@ func (l *Logger) handler() {
247276
}
248277
}
249278
case buf := <-l.writeBufferChan:
279+
250280
l.Write(buf.Bytes())
251281
PutLogBuffer(buf)
252282
}
@@ -276,6 +306,7 @@ func (l *Logger) reopen() error {
276306
if err := closer.Close(); err != nil {
277307
fmt.Fprintf(os.Stderr, "logger %s close error when restart, error: %v", l.output, err)
278308
}
309+
l.mill()
279310
return l.start()
280311
}
281312
return ErrReopenUnsupported
@@ -427,7 +458,37 @@ func doRotateFunc(l *Logger, interval time.Duration) {
427458
}
428459

429460
func (l *Logger) Write(p []byte) (n int, err error) {
430-
return l.writer.Write(p)
461+
l.mu.Lock()
462+
defer l.mu.Unlock()
463+
writeLen := int64(len(p))
464+
if writeLen > l.max() {
465+
return 0, fmt.Errorf(
466+
"write length %d exceeds maximum file size %d", writeLen, l.roller.MaxSize,
467+
)
468+
}
469+
470+
if l.writer == nil {
471+
if err = l.start(); err != nil {
472+
return 0, err
473+
}
474+
}
475+
476+
if l.size+writeLen > l.max() {
477+
rollerHandler(&LoggerInfo{
478+
LogRoller: *l.roller,
479+
FileName: l.output,
480+
CreateTime: time.Now(),
481+
})
482+
if err := l.reopen(); err != nil {
483+
return 0, err
484+
}
485+
}
486+
487+
n, err = l.writer.Write(p)
488+
l.size += int64(n)
489+
490+
return n, err
491+
//return l.writer.Write(p)
431492
}
432493

433494
func (l *Logger) Close() error {
@@ -471,3 +532,212 @@ func parseSyslogAddress(location string) *syslogAddress {
471532

472533
return nil
473534
}
535+
536+
//-------------------------------------------
537+
const (
538+
compressSuffix = ".gz"
539+
megabyte = 1024 * 1024
540+
)
541+
542+
// max returns the maximum size in bytes of log files before rolling.
543+
func (l *Logger) max() int64 {
544+
if l.roller.MaxSize == 0 {
545+
return int64(defaultRotateSize * megabyte)
546+
}
547+
return int64(l.roller.MaxSize) * int64(megabyte)
548+
}
549+
550+
// millRunOnce performs compression and removal of stale log files.
551+
// Log files are compressed if enabled via configuration and old log
552+
// files are removed, keeping at most l.MaxBackups files, as long as
553+
// none of them are older than MaxAge.
554+
func (l *Logger) millRunOnce() error {
555+
if l.roller.MaxBackups == 0 && l.roller.MaxAge == 0 && !l.roller.Compress {
556+
return nil
557+
}
558+
559+
files, err := l.oldLogFiles()
560+
if err != nil {
561+
return err
562+
}
563+
564+
var compress, remove []LoggerInfo
565+
566+
if l.roller.MaxBackups > 0 && l.roller.MaxBackups < len(files) {
567+
preserved := make(map[string]bool)
568+
var remaining []LoggerInfo
569+
for _, f := range files {
570+
// Only count the uncompressed log file or the
571+
// compressed log file, not both.
572+
fn := f.FileName
573+
if strings.HasSuffix(fn, compressSuffix) {
574+
fn = fn[:len(fn)-len(compressSuffix)]
575+
}
576+
preserved[fn] = true
577+
578+
if len(preserved) > l.roller.MaxBackups {
579+
remove = append(remove, f)
580+
} else {
581+
remaining = append(remaining, f)
582+
}
583+
}
584+
files = remaining
585+
}
586+
if l.roller.MaxAge > 0 {
587+
diff := time.Duration(int64(24*time.Hour) * int64(l.roller.MaxAge))
588+
cutoff := time.Now().Add(-1 * diff)
589+
590+
var remaining []LoggerInfo
591+
for _, f := range files {
592+
if f.CreateTime.Before(cutoff) {
593+
remove = append(remove, f)
594+
} else {
595+
remaining = append(remaining, f)
596+
}
597+
}
598+
files = remaining
599+
}
600+
601+
if l.roller.Compress {
602+
for _, f := range files {
603+
if !strings.HasSuffix(f.FileName, compressSuffix) {
604+
compress = append(compress, f)
605+
}
606+
}
607+
}
608+
609+
for _, f := range remove {
610+
errRemove := os.Remove(filepath.Join(l.dir(), f.FileName))
611+
if err == nil && errRemove != nil {
612+
err = errRemove
613+
}
614+
}
615+
for _, f := range compress {
616+
fn := filepath.Join(l.dir(), f.FileName)
617+
fnCompress := compressSuffixFile(fn + compressSuffix)
618+
errCompress := compressLogFile(fn, fnCompress)
619+
if err == nil && errCompress != nil {
620+
err = errCompress
621+
}
622+
}
623+
624+
return err
625+
}
626+
627+
func compressSuffixFile(fileName string) string {
628+
var num int
629+
for {
630+
if _, err := os.Stat(fileName); !os.IsNotExist(err) {
631+
return fileName
632+
}
633+
fileName = fileName + "." + strconv.Itoa(num)
634+
num++
635+
}
636+
}
637+
638+
// mill performs post-rotation compression and removal of stale log files,
639+
// starting the mill goroutine if necessary.
640+
func (l *Logger) mill() {
641+
l.millRunOnce()
642+
}
643+
644+
// oldLogFiles returns the list of backup log files stored in the same
645+
// directory as the current log file, sorted by ModTime
646+
func (l *Logger) oldLogFiles() ([]LoggerInfo, error) {
647+
files, err := ioutil.ReadDir(l.dir())
648+
if err != nil {
649+
return nil, fmt.Errorf("can't read log file directory: %s", err)
650+
}
651+
logFiles := []LoggerInfo{}
652+
653+
for _, f := range files {
654+
if f.IsDir() {
655+
continue
656+
}
657+
if !strings.HasPrefix(f.Name(), filepath.Base(l.output)+".") {
658+
continue
659+
}
660+
//use modTime replace createTime
661+
logFiles = append(logFiles, LoggerInfo{*l.roller, f.Name(), f.ModTime()})
662+
}
663+
664+
return logFiles, nil
665+
}
666+
667+
// timeFromName extracts the formatted time from the filename by stripping off
668+
// the filename's prefix and extension. This prevents someone's filename from
669+
// confusing time.parse.
670+
func (l *Logger) timeFromName(filename, prefix, ext string) (time.Time, error) {
671+
if !strings.HasPrefix(filename, prefix) {
672+
return time.Time{}, errors.New("mismatched prefix")
673+
}
674+
if !strings.HasSuffix(filename, ext) {
675+
return time.Time{}, errors.New("mismatched extension")
676+
}
677+
return time.Now(), nil
678+
}
679+
680+
// prefixAndExt returns the filename part and extension part from the Logger's
681+
// filename.
682+
func (l *Logger) prefixAndExt() (prefix, ext string) {
683+
filename := filepath.Base(l.output)
684+
685+
prefix = filename + "."
686+
687+
return prefix, ext
688+
}
689+
690+
// dir returns the directory for the current filename.
691+
func (l *Logger) dir() string {
692+
return filepath.Dir(l.output)
693+
}
694+
695+
// compressLogFile compresses the given log file, removing the
696+
// uncompressed log file if successful.
697+
func compressLogFile(src, dst string) (err error) {
698+
f, err := os.Open(src)
699+
if err != nil {
700+
return fmt.Errorf("failed to open log file: %v", err)
701+
}
702+
defer f.Close()
703+
704+
fi, err := os.Stat(src)
705+
if err != nil {
706+
return fmt.Errorf("failed to stat log file: %v", err)
707+
}
708+
// If this file already exists, we presume it was created by
709+
// a previous attempt to compress the log file.
710+
gzf, err := os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, fi.Mode())
711+
if err != nil {
712+
return fmt.Errorf("failed to open compressed log file: %v", err)
713+
}
714+
defer gzf.Close()
715+
716+
gz := gzip.NewWriter(gzf)
717+
718+
defer func() {
719+
if err != nil {
720+
os.Remove(dst)
721+
err = fmt.Errorf("failed to compress log file: %v", err)
722+
}
723+
}()
724+
725+
if _, err := io.Copy(gz, f); err != nil {
726+
return err
727+
}
728+
if err := gz.Close(); err != nil {
729+
return err
730+
}
731+
if err := gzf.Close(); err != nil {
732+
return err
733+
}
734+
735+
if err := f.Close(); err != nil {
736+
return err
737+
}
738+
if err := os.Remove(src); err != nil {
739+
return err
740+
}
741+
742+
return nil
743+
}

0 commit comments

Comments
 (0)