qoobing.com/gomod/log@v1.2.8/writer.go (about) 1 package log 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9 "sync" 10 ) 11 12 type baseWriter struct { 13 logw *os.File 14 stdw *os.File 15 errw *os.File 16 17 logFilename string 18 logPreBackupTag string 19 } 20 21 type cacheWriter struct { 22 cache bytes.Buffer 23 cacheing bool 24 cacheLock *sync.Mutex 25 baseWriter io.Writer 26 } 27 28 func NewBaseWriter(logw, stdw, errw *os.File) *baseWriter { 29 return &baseWriter{ 30 logw: logw, 31 stdw: stdw, 32 errw: errw, 33 } 34 } 35 36 // OpenLogFile 37 func (w *baseWriter) OpenLogFile(logDir, logName string, optLogDirs []string) { 38 // Step 1. try get available log dir 39 if _, err := os.Stat(logDir); err == nil { 40 logDir = logDir 41 } else if dir, err := tryOptLogDirs(optLogDirs); err == nil { 42 logDir = dir 43 } else if err := os.Mkdir(logDir, 0755); err == nil { 44 logDir = logDir 45 } else { 46 errstr := fmt.Sprintf("all path not exist:\n "+ 47 "a.[%s]\n b.[%s]\n c.[%s]\n", 48 logDir, "./log/", "./logs/") 49 panic("failed initlog:" + errstr) 50 } 51 52 // Step 2. open base writer logfile 53 filename := filepath.Join(logDir, logName+".log") 54 w.logFilename = filename 55 w.logPreBackupTag = "" 56 w.ReopenLogFile() 57 } 58 59 // ReopenLogFile 60 func (w *baseWriter) ReopenLogFile() { 61 var fil, err = os.OpenFile(w.logFilename, 62 os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModePerm) 63 if err != nil { 64 panic("open log file failed:" + err.Error()) 65 } 66 w.logw.Close() 67 w.logw = fil 68 } 69 70 // BackupLogFile 71 func (w *baseWriter) TryBackupLogFile(tag string) bool { 72 if w.logPreBackupTag == "" { 73 w.logPreBackupTag = tag 74 return false 75 } else if w.logPreBackupTag == tag { 76 return false 77 } 78 79 w.logPreBackupTag = tag 80 newname := w.logFilename + "." + tag 81 if err := os.Rename(w.logFilename, newname); err != nil { 82 return false 83 } 84 85 w.ReopenLogFile() 86 return true 87 } 88 89 func NewCacheWriter(basewriter io.Writer) *cacheWriter { 90 return &cacheWriter{ 91 cache: bytes.Buffer{}, 92 cacheing: false, 93 cacheLock: new(sync.Mutex), 94 baseWriter: basewriter, 95 } 96 } 97 98 func (w *baseWriter) Write(p []byte) (n int, err error) { 99 if w.errw != nil { 100 n, err = w.errw.Write(p) 101 } 102 if w.stdw != nil { 103 n, err = w.stdw.Write(p) 104 } 105 if w.logw != nil { 106 n, err = w.logw.Write(p) 107 } 108 return n, err 109 } 110 111 func (w *cacheWriter) Write(p []byte) (n int, err error) { 112 if w.cacheing { 113 w.cache.Write(p) 114 } 115 return w.baseWriter.Write(p) 116 } 117 118 func (w *cacheWriter) GetCacheLog() string { 119 if w.cacheing != true { 120 panic("GetCacheLog MUST call after StartCacheLog called") 121 } 122 return w.cache.String() 123 } 124 125 func (w *cacheWriter) StartCacheLog() { 126 w.cacheLock.Lock() 127 w.cacheing = true 128 w.cache.Reset() 129 } 130 131 func (w *cacheWriter) StopCacheLog() { 132 w.cacheLock.Unlock() 133 w.cacheing = true 134 }