github.com/JohanShen/go-utils@v1.1.4-0.20201117124024-901319a2b2a0/logger/time_writer.go (about) 1 package logger 2 3 import ( 4 "fmt" 5 "github.com/JohanShen/go-utils/utils" 6 "os" 7 "path/filepath" 8 "sync" 9 "time" 10 ) 11 12 type TimeWriter struct { 13 dir, fileName string 14 lastMakeTime time.Time 15 fileMode os.FileMode 16 CurrentPath string 17 PathTemplate string 18 files map[string]*fileObject 19 locker *sync.Mutex 20 } 21 22 type fileObject struct { 23 file *os.File 24 writeLen int 25 createTime time.Time 26 } 27 28 func NewTimeWriter(logTemplate string) (obj *TimeWriter) { 29 obj = &TimeWriter{ 30 PathTemplate: logTemplate, 31 locker: &sync.Mutex{}, 32 fileMode: 0666, 33 files: make(map[string]*fileObject), 34 } 35 return obj 36 } 37 38 // 创建新的文件对象 39 func (l *TimeWriter) makeNewFile(logPath string) (file *os.File, err error) { 40 //now := time.Now() 41 //logPath := utils.XTime(now).Format(l.PathTemplate) 42 l.dir, l.fileName = filepath.Split(logPath) 43 if ok, _ := utils.IsDirExists(l.dir); !ok { 44 if err := os.MkdirAll(l.dir, l.fileMode); err != nil { 45 return nil, err 46 } 47 } 48 49 file, err = os.OpenFile(logPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, l.fileMode) 50 return file, err 51 } 52 53 func (l *TimeWriter) Write(p []byte) (n int, err error) { 54 l.locker.Lock() 55 defer l.locker.Unlock() 56 57 now := time.Now() 58 logPath := utils.XTime(now).Format(l.PathTemplate) 59 60 var file *fileObject 61 ok := false 62 for { 63 if file, ok = l.files[logPath]; ok { 64 break 65 } 66 if obj, err := l.makeNewFile(logPath); err == nil { 67 l.files[logPath] = &fileObject{file: obj, createTime: now} 68 l.CurrentPath = logPath 69 l.lastMakeTime = now 70 } else { 71 fmt.Printf("write fail, msg(%s)\n", err) 72 return 0, err 73 } 74 go l.closeFile() 75 } 76 77 n, err = file.file.Write(p) 78 file.writeLen += n 79 return n, err 80 } 81 82 func (l *TimeWriter) closeFile() { 83 84 if len(l.files) > 1 { 85 now := time.Now() 86 closeFiles := make([]string, 0, len(l.files)) 87 // 需要将之前的文件句柄关闭 88 for key, item := range l.files { 89 // 将非当前文件,且超过15分钟的文件句柄关闭 90 if key == l.CurrentPath || item.createTime.Sub(now) > time.Minute*-15 { 91 continue 92 } 93 closeFiles = append(closeFiles, key) 94 if err := item.file.Sync(); err != nil { 95 //有问题但是不处理 96 println("写入文件时 closeFile() ", err) 97 } 98 if err := item.file.Close(); err != nil { 99 //有问题但是不处理 100 println("关闭文件时 closeFile() ", err) 101 } 102 } 103 if len(closeFiles) > 0 { 104 l.locker.Lock() 105 for _, v := range closeFiles { 106 delete(l.files, v) 107 } 108 l.locker.Unlock() 109 } 110 } 111 } 112 113 func (l *TimeWriter) Close() error { 114 l.locker.Lock() 115 defer l.locker.Unlock() 116 117 for _, item := range l.files { 118 if err := item.file.Sync(); err != nil { 119 //有问题但是不处理 120 println("写入文件时 Close() ", err) 121 } 122 if err := item.file.Close(); err != nil { 123 //有问题但是不处理 124 println("关闭文件时 Close() ", err) 125 } 126 } 127 return nil 128 }