package logger import ( "fmt" "io" "log" "os" "path" "runtime" "runtime/debug" "strings" "repositories.action2quare.com/ayo/gocommon/flagx" ) var stdlogger *log.Logger var UseLogFile = flagx.Bool("logfile", false, "") var logprefix = flagx.Int("logprefix", 3, "0 : no_prefix, 1 : date, 2 : time, 3 : datetime") func init() { binpath, _ := os.Executable() binname := path.Base(strings.ReplaceAll(binpath, "\\", "/")) var outWriter io.Writer outWriter = os.Stdout if *UseLogFile { ext := path.Ext(binname) if len(ext) > 0 { binname = binname[:len(binname)-len(ext)] } logFile, err := os.Create(fmt.Sprintf("%s.log", binname)) if err != nil { os.Stdout.Write([]byte(err.Error())) panic(err) } outWriter = io.MultiWriter(outWriter, logFile) } if *logprefix < 4 { stdlogger = log.New(outWriter, "", *logprefix) } else { stdlogger = log.New(outWriter, "", log.LstdFlags) } } func Println(v ...interface{}) { stdlogger.Output(2, fmt.Sprintln(v...)) } func Printf(format string, v ...interface{}) { stdlogger.Output(2, fmt.Sprintf(format, v...)) } func Error(v ...interface{}) { stdlogger.Output(2, fmt.Sprintln(v...)) stdlogger.Output(2, string(debug.Stack())) } func Errorf(format string, v ...interface{}) { stdlogger.Output(2, fmt.Sprintf(format, v...)) stdlogger.Output(2, string(debug.Stack())) } func Fatal(v ...interface{}) { stdlogger.Output(2, fmt.Sprint(v...)) stdlogger.Output(2, string(debug.Stack())) os.Exit(1) } func Fatalln(v ...interface{}) { stdlogger.Output(2, fmt.Sprintln(v...)) stdlogger.Output(2, string(debug.Stack())) os.Exit(1) } func Panic(v ...interface{}) { s := fmt.Sprint(v...) stdlogger.Output(2, s) stdlogger.Output(2, string(debug.Stack())) panic(s) } func Panicf(format string, v ...interface{}) { s := fmt.Sprintf(format, v...) stdlogger.Output(2, s) stdlogger.Output(2, string(debug.Stack())) panic(s) } func Panicln(v ...interface{}) { s := fmt.Sprintln(v...) stdlogger.Output(2, s) stdlogger.Output(2, string(debug.Stack())) panic(s) } type errWithCallstack struct { inner error frames []*runtime.Frame } func (ecs *errWithCallstack) Error() string { if ecs.frames == nil { return ecs.inner.Error() } out := make([]string, 0, len(ecs.frames)+1) out = append(out, ecs.inner.Error()) for i := len(ecs.frames) - 1; i >= 0; i-- { frame := ecs.frames[i] out = append(out, fmt.Sprintf("%s\n\t%s:%d", frame.Function, frame.File, frame.Line)) } return strings.Join(out, "\n") } func ErrorWithCallStack(err error) error { var frames []*runtime.Frame if recur, ok := err.(*errWithCallstack); ok { err = recur.inner frames = recur.frames } pc, _, _, ok := runtime.Caller(1) if ok { curframes := runtime.CallersFrames([]uintptr{pc}) f, _ := curframes.Next() frames = append(frames, &f) } return &errWithCallstack{ inner: err, frames: frames, } }