diff --git a/global.go b/global.go new file mode 100644 index 0000000..41d7292 --- /dev/null +++ b/global.go @@ -0,0 +1,87 @@ +package log + +import ( + "fmt" + "os" + "runtime" +) + +func GetLogid() string { + if logidCreator != nil { + return logidCreator.GetLogid() + } + return "" +} + +func SetLogid(logid string) { + if logidCreator != nil { + logidCreator.SetLogid(logid) + } +} + +func Cleanup() { + if logidCreator != nil { + logidCreator.Cleanup() + } +} + +func SetLogLevel(newlv logLevel) (oldlv logLevel) { + return mylog.SetLogLevel(newlv) +} + +func PrintPretty(prefix string, v interface{}) { + mylog.PrintPretty(prefix, v) +} + +func DebugfWithDepth(calldepth int, format string, v ...interface{}) { + mylog.DebugfWithDepth(calldepth, format, v...) +} + +func Debugf(format string, v ...interface{}) { + mylog.Debugf(format, v...) +} + +func Noticef(format string, v ...interface{}) { + mylog.Noticef(format, v...) +} + +func NoticefWithDepth(calldepth int, format string, v ...interface{}) { + mylog.NoticefWithDepth(calldepth, format, v...) +} + +func Infof(format string, v ...interface{}) { + mylog.Infof(format, v...) +} + +func Warningf(format string, v ...interface{}) { + mylog.Warningf(format, v...) +} + +func Errorf(format string, v ...interface{}) { + mylog.Warningf(format, v...) +} + +func Panicf(format string, v ...interface{}) { + mylog.Panicf(format, v...) +} + +func Fatalf(format string, v ...interface{}) { + mylog.Fatalf(format, v...) +} + +func TraceInto(format string, v ...interface{}) string { + _, fn, line, _ := runtime.Caller(1) + strfn := fmt.Sprintf("%s:%d", fn, line) + Debugf("TRACE into ["+strfn+"]"+format+"...\r\n", v...) + + return strfn +} + +func TraceExit(strfn string, format string, v ...interface{}) { + Debugf("TRACE exit ["+strfn+"]"+format+"...\r\n", v...) +} + +func RegisterLogidCreator(idc LogidCreator) { + logidCreator = idc + SetLogid(fmt.Sprintf("sysinit(%d)", os.Getpid())) +} diff --git a/util.go b/util.go new file mode 100644 index 0000000..0290adc --- /dev/null +++ b/util.go @@ -0,0 +1,29 @@ +package log + +import ( + "fmt" + "os" + "path/filepath" +) + +// getExeFilename +func getExeFilename() string { + _, logfilename := filepath.Split(os.Args[0]) + if logfilename == "" { + panic("get exe filename failed") + } + return logfilename +} + +// tryOptLogDirs +func tryOptLogDirs(optLogDirs []string) (string, error) { + optionDirsStr := "" + for i, d := range optLogDirs { + dir := fmt.Sprintf("%s/", d) + optionDirsStr += fmt.Sprintf("%d.[%s];", i, dir) + if _, err := os.Stat(dir); err == nil { + return dir, nil + } + } + return "", fmt.Errorf("all optional dir are not exist: %s", optionDirsStr) +} diff --git a/writer.go b/writer.go new file mode 100644 index 0000000..2b30b54 --- /dev/null +++ b/writer.go @@ -0,0 +1,134 @@ +package log + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "sync" +) + +type baseWriter struct { + logw *os.File + stdw *os.File + errw *os.File + + logFilename string + logPreBackupTag string +} + +type cacheWriter struct { + cache bytes.Buffer + cacheing bool + cacheLock *sync.Mutex + baseWriter io.Writer +} + +func NewBaseWriter(logw, stdw, errw *os.File) *baseWriter { + return &baseWriter{ + logw: logw, + stdw: stdw, + errw: errw, + } +} + +// OpenLogFile +func (w *baseWriter) OpenLogFile(logDir, logName string, optLogDirs []string) { + // Step 1. try get available log dir + if _, err := os.Stat(logDir); err == nil { + logDir = logDir + } else if dir, err := tryOptLogDirs(optLogDirs); err == nil { + logDir = dir + } else if err := os.Mkdir(logDir, 0755); err == nil { + logDir = logDir + } else { + errstr := fmt.Sprintf("all path not exist:\n "+ + "a.[%s]\n b.[%s]\n c.[%s]\n", + logDir, "./log/", "./logs/") + panic("failed initlog:" + errstr) + } + + // Step 2. open base writer logfile + filename := filepath.Join(logDir, logName+".log") + w.logFilename = filename + w.logPreBackupTag = "" + w.ReopenLogFile() +} + +// ReopenLogFile +func (w *baseWriter) ReopenLogFile() { + var fil, err = os.OpenFile(w.logFilename, + os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModePerm) + if err != nil { + panic("open log file failed:" + err.Error()) + } + w.logw.Close() + w.logw = fil +} + +// BackupLogFile +func (w *baseWriter) TryBackupLogFile(tag string) bool { + if w.logPreBackupTag == "" { + w.logPreBackupTag = tag + return false + } else if w.logPreBackupTag == tag { + return false + } + + w.logPreBackupTag = tag + newname := w.logFilename + "." + tag + if err := os.Rename(w.logFilename, newname); err != nil { + return false + } + + w.ReopenLogFile() + return true +} + +func NewCacheWriter(basewriter io.Writer) *cacheWriter { + return &cacheWriter{ + cache: bytes.Buffer{}, + cacheing: false, + cacheLock: new(sync.Mutex), + baseWriter: basewriter, + } +} + +func (w *baseWriter) Write(p []byte) (n int, err error) { + if w.errw != nil { + n, err = w.errw.Write(p) + } + if w.stdw != nil { + n, err = w.stdw.Write(p) + } + if w.logw != nil { + n, err = w.logw.Write(p) + } + return n, err +} + +func (w *cacheWriter) Write(p []byte) (n int, err error) { + if w.cacheing { + w.cache.Write(p) + } + return w.baseWriter.Write(p) +} + +func (w *cacheWriter) GetCacheLog() string { + if w.cacheing != true { + panic("GetCacheLog MUST call after StartCacheLog called") + } + return w.cache.String() +} + +func (w *cacheWriter) StartCacheLog() { + w.cacheLock.Lock() + w.cacheing = true + w.cache.Reset() +} + +func (w *cacheWriter) StopCacheLog() { + w.cacheLock.Unlock() + w.cacheing = true +}