gitee.com/quant1x/gox@v1.7.6/logger/logwriter.go (about) 1 package logger 2 3 import ( 4 "compress/gzip" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9 "strconv" 10 "time" 11 ) 12 13 const ( 14 DAY DateType = iota 15 HOUR 16 ) 17 18 type LogWriter interface { 19 Write(v []byte) 20 NeedPrefix() bool 21 } 22 23 type ConsoleWriter struct { 24 } 25 26 type RollFileWriter struct { 27 logpath string 28 name string 29 num int 30 size int64 31 currSize int64 32 currFile *os.File 33 openTime int64 34 } 35 36 type DateWriter struct { 37 logpath string 38 name string 39 dateType DateType 40 num int 41 currDate string 42 currFile *os.File 43 openTime int64 44 } 45 46 type HourWriter struct { 47 } 48 49 type DateType uint8 50 51 func reOpenFile(path string, currFile **os.File, openTime *int64) { 52 *openTime = currUnixTime 53 if *currFile != nil { 54 (*currFile).Close() 55 } 56 of, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666) 57 if err == nil { 58 *currFile = of 59 } else { 60 fmt.Println("open log file error", err) 61 } 62 } 63 64 func (w *ConsoleWriter) Write(v []byte) { 65 _, _ = os.Stdout.Write(v) 66 } 67 68 func (w *ConsoleWriter) NeedPrefix() bool { 69 return true 70 } 71 72 func (w *RollFileWriter) Write(v []byte) { 73 if w.currFile == nil || w.openTime+10 < currUnixTime { 74 fullPath := filepath.Join(w.logpath, w.name+".log") 75 reOpenFile(fullPath, &w.currFile, &w.openTime) 76 } 77 if w.currFile == nil { 78 return 79 } 80 n, _ := w.currFile.Write(v) 81 w.currSize += int64(n) 82 if w.currSize >= w.size { 83 w.currSize = 0 84 for i := w.num - 1; i >= 1; i-- { 85 var n1, n2 string 86 if i > 1 { 87 n1 = strconv.Itoa(i - 1) 88 } 89 n2 = strconv.Itoa(i) 90 p1 := filepath.Join(w.logpath, w.name+n1+".log") 91 p2 := filepath.Join(w.logpath, w.name+n2+".log") 92 if _, err := os.Stat(p1); !os.IsNotExist(err) { 93 _ = os.Rename(p1, p2) 94 } 95 } 96 fullPath := filepath.Join(w.logpath, w.name+".log") 97 reOpenFile(fullPath, &w.currFile, &w.openTime) 98 } 99 } 100 101 func NewRollFileWriter(logpath, name string, num, sizeMB int) *RollFileWriter { 102 w := &RollFileWriter{ 103 logpath: logpath, 104 name: name, 105 num: num, 106 size: int64(sizeMB) * 1024 * 1024, 107 } 108 fullPath := filepath.Join(logpath, name+".log") 109 st, _ := os.Stat(fullPath) 110 if st != nil { 111 w.currSize = st.Size() 112 } 113 return w 114 } 115 116 func (w *RollFileWriter) NeedPrefix() bool { 117 return true 118 } 119 120 // 压缩 使用gzip压缩成tar.gz 121 func gzipFile(source string) error { 122 dest := source + ".gz" 123 os.Remove(dest) 124 newfile, err := os.Create(dest) 125 if err != nil { 126 return err 127 } 128 defer newfile.Close() 129 130 file, err := os.Open(source) 131 if err != nil { 132 return err 133 } 134 135 zw := gzip.NewWriter(newfile) 136 137 filestat, err := file.Stat() 138 if err != nil { 139 return nil 140 } 141 142 zw.Name = filestat.Name() 143 zw.ModTime = filestat.ModTime() 144 _, err = io.Copy(zw, file) 145 if err != nil { 146 return nil 147 } 148 149 zw.Flush() 150 if err := zw.Close(); err != nil { 151 return nil 152 } 153 return nil 154 } 155 156 func (w *DateWriter) Write(v []byte) { 157 fullPath := filepath.Join(w.logpath, w.name+".log") 158 //isNewFile := false 159 if w.currFile == nil || w.openTime+10 < currUnixTime { 160 reOpenFile(fullPath, &w.currFile, &w.openTime) 161 w.currDate = w.getFileDate() 162 } 163 if w.currFile == nil { 164 return 165 } 166 167 currDate := w.getCurrDate() 168 if w.currDate != currDate { 169 // 文件改名 170 sourceFile := fullPath 171 destFile := filepath.Join(w.logpath, w.name+".log."+w.currDate) 172 // 删除已有的目标文件 173 w.currFile.Close() 174 w.currFile = nil 175 err := os.Remove(destFile) 176 err = os.Rename(sourceFile, destFile) 177 if err != nil { 178 // 改名失败 179 } else { 180 // 改名成功 181 } 182 w.currDate = currDate 183 184 gzipFile(destFile) 185 w.cleanOldLogs() 186 reOpenFile(fullPath, &w.currFile, &w.openTime) 187 // 清理旧文件 [wangfeng on 2018/12/25 12:39] 188 os.Remove(destFile) 189 } 190 w.currFile.Write(v) 191 } 192 193 func (w *DateWriter) NeedPrefix() bool { 194 return true 195 } 196 197 func NewDateWriter(logpath, name string, dateType DateType, num int) *DateWriter { 198 w := &DateWriter{ 199 logpath: logpath, 200 name: name, 201 num: num, 202 dateType: dateType, 203 } 204 w.currDate = w.getCurrDate() 205 return w 206 } 207 208 func (w *DateWriter) getFotmat() string { 209 format := "20060102" 210 if w.dateType == HOUR { 211 format = "2006010215" 212 } 213 return format 214 } 215 216 func (w *DateWriter) cleanOldLogs() { 217 format := "20060102" 218 duration := -time.Hour * 24 219 if w.dateType == HOUR { 220 format = "2006010215" 221 duration = -time.Hour 222 } 223 224 t := time.Now() 225 t = t.Add(duration * time.Duration(w.num)) 226 for i := 0; i < 30; i++ { 227 t = t.Add(duration) 228 k := t.Format(format) 229 fullPath := filepath.Join(w.logpath, w.name+".log."+k+".gz") 230 if _, err := os.Stat(fullPath); !os.IsNotExist(err) { 231 os.Remove(fullPath) 232 } 233 } 234 return 235 } 236 237 func (w *DateWriter) getCurrDate() string { 238 if w.dateType == HOUR { 239 return currDateHour 240 } 241 return currDateDay // DAY 242 } 243 244 func (w *DateWriter) getFileDate() string { 245 fi, err := w.currFile.Stat() 246 if err == nil { 247 return fi.ModTime().Format(w.getFotmat()) 248 } else { 249 return "" 250 } 251 }