diff --git a/global.go b/global.go index 399dd10..6e7fc98 100644 --- a/global.go +++ b/global.go @@ -62,7 +62,7 @@ func Warningf(format string, v ...interface{}) { } func Errorf(format string, v ...interface{}) { - mylog.Warningf(format, v...) + mylog.Errorf(format, v...) } func Panicf(format string, v ...interface{}) { @@ -73,6 +73,14 @@ func Fatalf(format string, v ...interface{}) { mylog.Fatalf(format, v...) } +func Fatal(v ...interface{}){ + mylog.Fatal(v...) +} + +func Println(v ...interface{}){ + mylog.Println(v...) +} + func TraceInto(format string, v ...interface{}) string { _, fn, line, _ := runtime.Caller(1) strfn := fmt.Sprintf("%s:%d", fn, line) diff --git a/go.mod b/go.mod index 7a0ea95..d948e73 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,8 @@ module qoobing.com/gomod/log go 1.16 -require qoobing.com/gomod/str v1.0.1 +require ( + github.com/tylerb/gls v0.0.0-20150407001822-e606233f194d + github.com/tylerb/is v2.1.4+incompatible // indirect + qoobing.com/gomod/str v1.0.1 +) diff --git a/log.go b/log.go index 969a22d..f448f00 100644 --- a/log.go +++ b/log.go @@ -3,227 +3,244 @@ package log import ( - "encoding/json" - "fmt" - "log" - "os" - "runtime/debug" - "strings" - "sync" - "time" + "encoding/json" + "fmt" + "log" + "os" + "runtime/debug" + "strings" + "sync" + "time" - "qoobing.com/gomod/str" + "qoobing.com/gomod/str" ) const ( - PANIC LogLevel = 0 - FATAL LogLevel = 1 - ERROR LogLevel = 2 - NOTICE LogLevel = 3 - WARNING LogLevel = 4 - INFO LogLevel = 5 - DEBUG LogLevel = 9 - ErrLogLevel = "~~~~~invalid loglevel~~~~~" - ErrLogPanic = "~~~~panic~~~~~~" + PANIC LogLevel = 0 + FATAL LogLevel = 1 + ERROR LogLevel = 2 + NOTICE LogLevel = 3 + WARNING LogLevel = 4 + INFO LogLevel = 5 + DEBUG LogLevel = 9 + ErrLogLevel = "~~~~~invalid loglevel~~~~~" + ErrLogPanic = "~~~~panic~~~~~~" ) var ( - mapStrToLevel = map[string]LogLevel{ - "PANIC": PANIC, - "FATAL": FATAL, - "ERROR": ERROR, - "NOTICE": NOTICE, - "WARNING": WARNING, - "INFO": INFO, - "DEBUG": DEBUG, - } - mapLevelToStr = map[LogLevel]string{ - PANIC: "PANIC", - FATAL: "FATAL", - ERROR: "ERROR", - NOTICE: "NOTICE", - WARNING: "WARNING", - INFO: "INFO", - DEBUG: "DEBUG", - } + mapStrToLevel = map[string]LogLevel{ + "PANIC": PANIC, + "FATAL": FATAL, + "ERROR": ERROR, + "NOTICE": NOTICE, + "WARNING": WARNING, + "INFO": INFO, + "DEBUG": DEBUG, + } + mapLevelToStr = map[LogLevel]string{ + PANIC: "PANIC", + FATAL: "FATAL", + ERROR: "ERROR", + NOTICE: "NOTICE", + WARNING: "WARNING", + INFO: "INFO", + DEBUG: "DEBUG", + } ) var ( - golog *log.Logger = nil - mylog *Logger = nil - logidCreator LogidCreator = nil - modulelogs map[string]*Logger = map[string]*Logger{} + golog *log.Logger = nil + mylog *Logger = nil + logidCreator LogidCreator = nil + modulelogs map[string]*Logger = map[string]*Logger{} ) type LogLevel int type Logger struct { - module string - golog *log.Logger - loglevel LogLevel + module string + golog *log.Logger + loglevel LogLevel } type LogidCreator interface { - Cleanup() - GetLogid() string - SetLogid(logid string) + Cleanup() + GetLogid() string + SetLogid(logid string) } func New(module string) *Logger { - if module == "" { - module = "undefine" - } - if _, ok := modulelogs[module]; ok { - return modulelogs[module] - } else { - modulelogs[module] = &Logger{ - module: module, - golog: golog, - loglevel: DEBUG, - } - return modulelogs[module] - } + if module == "" { + module = "undefine" + } + if _, ok := modulelogs[module]; ok { + return modulelogs[module] + } else { + modulelogs[module] = &Logger{ + module: module, + golog: golog, + loglevel: DEBUG, + } + return modulelogs[module] + } } // SetLogLevel set new log level func (log *Logger) SetLogLevel(newlv LogLevel) (oldlv LogLevel) { - oldlv = log.loglevel - log.loglevel = newlv - return oldlv + oldlv = log.loglevel + log.loglevel = newlv + return oldlv } // SetLogLevelByName set new log level by level name func (log *Logger) SetLogLevelByName(newlv string) (oldlv string) { - if newlevel, ok := mapStrToLevel[newlv]; ok { - oldlevel := log.loglevel - log.loglevel = newlevel - return mapLevelToStr[oldlevel] - } - return ErrLogLevel + if newlevel, ok := mapStrToLevel[newlv]; ok { + oldlevel := log.loglevel + log.loglevel = newlevel + return mapLevelToStr[oldlevel] + } + return ErrLogLevel } + func (log *Logger) Print(prefix string, v interface{}) { - var str = "" - if pkg, err := json.Marshal(v); err != nil { - str = err.Error() - } else { - str = string(pkg) - } - log.logwrite(DEBUG, 3, prefix+"%s\n", str) + var str = "" + if pkg, err := json.Marshal(v); err != nil { + str = err.Error() + } else { + str = string(pkg) + } + log.logwrite(DEBUG, 3, prefix+"%s\n", str) } func (log *Logger) PrintPretty(prefix string, v interface{}) { - var preety = "" - if pkg, err := json.MarshalIndent(v, "==", " "); err != nil { - preety = err.Error() - } else { - preety = string(pkg) - } - log.logwrite(DEBUG, 3, prefix+"%s\n", preety) + var preety = "" + if pkg, err := json.MarshalIndent(v, "==", " "); err != nil { + preety = err.Error() + } else { + preety = string(pkg) + } + log.logwrite(DEBUG, 3, prefix+"%s\n", preety) } func (log *Logger) Debugf(format string, v ...interface{}) { - log.logwrite(DEBUG, 3, format, v...) + log.logwrite(DEBUG, 3, format, v...) } func (log *Logger) DebugfWithDepth(calldepth int, format string, v ...interface{}) { - calldepth += 3 - log.logwrite(DEBUG, calldepth, format, v...) + calldepth += 3 + log.logwrite(DEBUG, calldepth, format, v...) } func (log *Logger) Noticef(format string, v ...interface{}) { - log.logwrite(NOTICE, 3, format, v...) + log.logwrite(NOTICE, 3, format, v...) } func (log *Logger) NoticefWithDepth(calldepth int, format string, v ...interface{}) { - calldepth += 3 - log.logwrite(NOTICE, calldepth, format, v...) + calldepth += 3 + log.logwrite(NOTICE, calldepth, format, v...) } func (log *Logger) Warningf(format string, v ...interface{}) { - log.logwrite(WARNING, 3, format, v...) + log.logwrite(WARNING, 3, format, v...) } func (log *Logger) Infof(format string, v ...interface{}) { - log.logwrite(INFO, 3, format, v...) + log.logwrite(INFO, 3, format, v...) } func (log *Logger) Errorf(format string, v ...interface{}) { - log.logwrite(ERROR, 3, format, v...) + log.logwrite(ERROR, 3, format, v...) } func (log *Logger) Fatalf(format string, v ...interface{}) { - log.logwrite(FATAL, 3, format, v...) + log.logwrite(FATAL, 3, format, v...) } func (log *Logger) Panicf(format string, v ...interface{}) { - log.logwrite(PANIC, 3, format, v...) + log.logwrite(PANIC, 3, format, v...) } +func (log *Logger) Fatal(v ...interface{}){ + log.logwrite(FATAL, 3, "%s", fmt.Sprintln(v...)) +} + +func (log *Logger) Println(v ...interface{}){ + log.logwrite(DEBUG, 3, "%s", fmt.Sprintln(v...)) +} + + func (log *Logger) GetLogidStr(format string) string { - if logidCreator != nil { - return fmt.Sprintf(format, logidCreator.GetLogid()) - } - return "" + if logidCreator != nil { + return fmt.Sprintf(format, logidCreator.GetLogid()) + } + return "" } func (log *Logger) logwrite(typ LogLevel, calldepth int, format string, v ...interface{}) { - if typ > log.loglevel { - return - } + if typ > log.loglevel { + return + } - var ( - idstr = log.GetLogidStr("[%s] ") - prestr = idstr // + "[" + log.module + "] " - ) + var ( + idstr = log.GetLogidStr("[%s] ") + prestr = idstr // + "[" + log.module + "] " + ) - format = strings.Trim(format, "\n") - switch typ { - case PANIC: - log.golog.SetPrefix("\x1b[31m" + "PANI ") - case FATAL: - log.golog.SetPrefix("\x1b[31m" + "FATA ") - case WARNING: - log.golog.SetPrefix("\x1b[32m" + "WARN ") - case ERROR: - log.golog.SetPrefix("\x1b[32m" + "ERRO ") - case INFO: - log.golog.SetPrefix("INFO ") - case NOTICE: - log.golog.SetPrefix("NOTI ") - case DEBUG: - log.golog.SetPrefix("DBUG ") - default: - log.golog.SetPrefix("UNKN ") - } + format = strings.Trim(format, "\n") + switch typ { + case PANIC: + log.golog.SetPrefix("\x1b[31m" + "PANI ") + case FATAL: + log.golog.SetPrefix("\x1b[31m" + "FATA ") + case WARNING: + log.golog.SetPrefix("\x1b[32m" + "WARN ") + case ERROR: + log.golog.SetPrefix("\x1b[33m" + "ERRO ") + case INFO: + log.golog.SetPrefix("INFO ") + case NOTICE: + log.golog.SetPrefix("NOTI ") + case DEBUG: + log.golog.SetPrefix("DBUG ") + default: + log.golog.SetPrefix("UNKN ") + } - if mylog == log { - calldepth = calldepth + 1 - } + if mylog == log { + calldepth = calldepth + 1 + } - if typ == FATAL || typ == WARNING || typ == ERROR { - log.golog.Output(calldepth, prestr+fmt.Sprintf(format+"\x1b[0m\n", v...)) - } else if typ == NOTICE { - calldepth = calldepth + 2 - log.golog.Output(calldepth, prestr+fmt.Sprintf(format+"\n", v...)) - } else if typ == PANIC { - stack := strings.Replace(string(debug.Stack()), "\n", "\n== ", -1) - stack = str.SkipLine(stack, calldepth*2+1) - v = append(v, stack) - panicstr := fmt.Sprintf(prestr+format+"\x1b[0m. Panic stack:\n%s\n", v...) - log.golog.Output(calldepth, panicstr) - panic(ErrLogPanic) - } else { - log.golog.Output(calldepth, prestr+fmt.Sprintf(format+"\n", v...)) - } + if typ == FATAL || typ == WARNING || typ == ERROR { + log.golog.Output(calldepth, prestr+fmt.Sprintf(format+"\x1b[0m\n", v...)) + } else if typ == NOTICE { + calldepth = calldepth + 2 + log.golog.Output(calldepth, prestr+fmt.Sprintf(format+"\n", v...)) + } else if typ == PANIC { + stack := strings.Replace(string(debug.Stack()), "\n", "\n== ", -1) + stack = str.SkipLine(stack, calldepth*2+1) + v = append(v, stack) + panicstr := fmt.Sprintf(prestr+format+"\x1b[0m. Panic stack:\n%s\n", v...) + log.golog.Output(calldepth, panicstr) + panic(ErrLogPanic) + } else { + log.golog.Output(calldepth, prestr+fmt.Sprintf(format+"\n", v...)) + } } func needWriteLogToFile() bool { - if cls, ok := os.LookupEnv("QOOLOG_CLOSE_FILELOG"); ok && cls != "N" && cls != "n" { - return false - } else if ink8s, ok := os.LookupEnv("KUBERNETES_PORT"); ok && ink8s != "" { - return false - } - return true + if cls, ok := os.LookupEnv("QOOLOG_CLOSE_FILELOG"); ok && cls != "N" && cls != "n" { + return false + } else if ink8s, ok := os.LookupEnv("KUBERNETES_PORT"); ok && ink8s != "" { + return false + } + return true +} + +func needWriteLogToStdout() bool { + if cls, ok := os.LookupEnv("QOOLOG_CLOSE_STDLOG"); ok && (cls == "Y" || cls == "y") { + return false + } + return true } // ////////////////////////////////////////////////////////////////////////////////// @@ -233,34 +250,38 @@ var once sync.Once = sync.Once{} // init func init() { - once.Do(initlog) + once.Do(initlog) } // initlog func initlog() { - // Step 1. create base writer & cache writer for ALL log - var ( - logDir = "./logs/" - logName = getExeFilename() - logDirsOptional = []string{"./log", "/var/log"} - logSplitTag = "20060102" //20060102150405 - baseWriter = NewBaseWriter(nil, os.Stdout, nil) - gologFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile - ) + // Step 1. create base writer & cache writer for ALL log + var ( + logDir = "./logs/" + logName = getExeFilename() + logDirsOptional = []string{"./log", "/var/log"} + logSplitTag = "20060102" //20060102150405 + baseWriter = NewBaseWriter(nil, os.Stdout, nil) + gologFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile + ) - // Step 2. init golog(golang std logger) & mylog(myself defined logger) - golog = log.New(NewCacheWriter(baseWriter), "", gologFlags) - mylog = New("system") + // Step 2.1 add stdout to base writer if need + if needWriteLogToStdout() { + baseWriter.stdw = os.Stdout + } + // Step 2.2 rotate log(split log ) if need + if needWriteLogToFile() { + baseWriter.OpenLogFile(logDir, logName, logDirsOptional) + go func() { + for { + tag := time.Now().Local().Format(logSplitTag) + baseWriter.TryBackupLogFile(tag) + time.Sleep(2 * time.Minute) + } + }() + } - // Step 3. backgroud split log (log rotate) if need - if needWriteLogToFile() { - go func() { - baseWriter.OpenLogFile(logDir, logName, logDirsOptional) - for { - tag := time.Now().Local().Format(logSplitTag) - baseWriter.TryBackupLogFile(tag) - time.Sleep(2 * time.Minute) - } - }() - } + // Step 3. init golog(golang std logger) & mylog(myself defined logger) + golog = log.New(NewCacheWriter(baseWriter), "", gologFlags) + mylog = New("system") } diff --git a/log_test.go b/log_test.go new file mode 100644 index 0000000..6df58ee --- /dev/null +++ b/log_test.go @@ -0,0 +1,9 @@ +package log + +import "testing" + +func TestLog(t *testing.T) { + Println("aaa", 1,3) + Fatal("aaa", 1,3) + Fatalf("aaa=%d", 1) +} diff --git a/logid+glslogid.go b/logid+glslogid.go index fcdd74e..e492378 100644 --- a/logid+glslogid.go +++ b/logid+glslogid.go @@ -1,4 +1,5 @@ // +build glslogid + package log import ( diff --git a/logid+runtimelogid.go b/logid+runtimelogid.go index 1a43844..811c324 100644 --- a/logid+runtimelogid.go +++ b/logid+runtimelogid.go @@ -1,4 +1,5 @@ // +build runtimelogid + package log //// Format writes the source file path and line number of the record to the buf. diff --git a/writer.go b/writer.go index 2b30b54..83df903 100644 --- a/writer.go +++ b/writer.go @@ -130,5 +130,5 @@ func (w *cacheWriter) StartCacheLog() { func (w *cacheWriter) StopCacheLog() { w.cacheLock.Unlock() - w.cacheing = true + w.cacheing = false }