package errutil import ( "bytes" "fmt" "io" "os" "strings" ) // LoggerType declare general log types type LoggerType interface { Debug(v ...interface{}) Print(v ...interface{}) Error(v ...interface{}) Trace(errin error) TraceSkip(errin error, skip int) } // Logger return default LoggerType instance func Logger() LoggerType { return defaultLogger } // NewLogger create LoggerType instance func NewLogger(opt LoggerOptions) LoggerType { opt.check() return loggerImpl{ opt: opt, } } // LoggerOptions for Logger type LoggerOptions struct { DefaultOutput io.Writer ErrorOutput io.Writer HideFile bool ShortFile bool HideLine bool ReplacePackages map[string]string TraceFormatter TraceFormatter } func (t *LoggerOptions) check() { if t.DefaultOutput == nil { t.DefaultOutput = os.Stdout } if t.ErrorOutput == nil { t.ErrorOutput = os.Stderr } if t.TraceFormatter == nil { t.TraceFormatter = &ConsoleFormatter{ Seperator: "; ", TimeFormat: "2006-01-02 15:04:05 ", LongFile: true, Line: true, } } } var defaultLogger = NewLogger(LoggerOptions{}) // SetDefaultLogger set default LoggerType func SetDefaultLogger(logger LoggerType) { defaultLogger = logger } type loggerImpl struct { opt LoggerOptions } func (t loggerImpl) Debug(v ...interface{}) { t.log(t.opt.DefaultOutput, 1, v...) } func (t loggerImpl) Print(v ...interface{}) { t.log(t.opt.DefaultOutput, 1, v...) } func (t loggerImpl) Error(v ...interface{}) { t.log(t.opt.ErrorOutput, 1, v...) } func (t loggerImpl) log(output io.Writer, skip int, v ...interface{}) { errtext := fmt.Sprint(v...) if errtext == "" { return } opt := t.opt if !opt.HideFile { buffer := &bytes.Buffer{} callinfo, _ := RuntimeCaller(skip + 1) if _, err := WriteCallInfo(buffer, callinfo, !opt.ShortFile, !opt.HideLine, opt.ReplacePackages); err != nil { panic(err) } errtext = buffer.String() + " " + errtext } if !strings.HasSuffix(errtext, "\n") { errtext += "\n" } if _, err := output.Write([]byte(errtext)); err != nil { panic(err) } } func (t loggerImpl) Trace(errin error) { TraceSkip(errin, 1) } func (t loggerImpl) TraceSkip(errin error, skip int) { var errtext string var errfmt error if errtext, errfmt = t.opt.TraceFormatter.FormatSkip(errin, skip+1); errfmt != nil { panic(errfmt) } if errtext == "" { return } if !strings.HasSuffix(errtext, "\n") { errtext += "\n" } if _, errfmt = t.opt.ErrorOutput.Write([]byte(errtext)); errfmt != nil { panic(errfmt) } }