package starlog import ( "fmt" "os" "path/filepath" "runtime" "strconv" "sync" "time" "github.com/fatih/color" ) const ( BLUE = color.FgBlue BLACK = color.FgBlack CYAN = color.FgCyan GREEN = color.FgGreen MAGENTA = color.FgMagenta RED = color.FgRed WHITE = color.FgWhite YELLOW = color.FgYellow GREY = color.FgHiYellow BOLD = color.Bold ) const ( LvDebug = iota LvInfo LvNotice LvWarning LvError LvCritical LvPanic LvFatal ) var ( levels = map[int]string{ LvDebug: "DEBUG", LvInfo: "INFO", LvNotice: "NOTICE", LvWarning: "WARNING", LvError: "ERROR", LvCritical: "CRITICAL", LvPanic: "PANIC", LvFatal: "FATAL", } Colors = map[int][]color.Attribute{ LvDebug: []color.Attribute{WHITE}, LvInfo: []color.Attribute{GREEN}, LvNotice: []color.Attribute{BLUE}, LvWarning: []color.Attribute{YELLOW}, LvError: []color.Attribute{MAGENTA}, LvCritical: []color.Attribute{RED, BOLD}, LvPanic: []color.Attribute{RED, BOLD}, LvFatal: []color.Attribute{RED}, } LogLevel int = 0 ShowLine, ShowLevel, DoWrite, DoShow, switching bool = true, true, true, true, false loghandle *os.File = nil HandleFunc func([]color.Attribute, string) lock sync.WaitGroup ) func write(logs string) { var i int = 0 defer lock.Done() for switching { time.Sleep(time.Millisecond * 100) i++ if i > 20 { return } } if loghandle == nil { return } loghandle.WriteString(logs) } func output(level int, showline, showlv, dowrite, doshow bool, strlog string) { var logs string if level < LogLevel { return } _, fname, line, _ := runtime.Caller(2) fname = filepath.Base(fname) date := time.Now().Format("2006-01-02 15:04:05 Mon") if showline && showlv { logs = fmt.Sprintf("%s %s %s %s", date, fname+":"+strconv.Itoa(line), `[`+levels[level]+`]`, strlog) } else if showline && !showlv { logs = fmt.Sprintf("%s %s %s", date, fname+":"+strconv.Itoa(line), strlog) } else if !showline && showlv { logs = fmt.Sprintf("%s %s %s", date, `[`+levels[level]+`]`, strlog) } else { logs = fmt.Sprintf("%s %s", date, strlog) } if doshow { for _, v := range Colors[level] { color.Set(v) } fmt.Print(logs) color.Set(color.Reset) } if HandleFunc != nil { go HandleFunc(Colors[level], logs) } if dowrite { lock.Add(1) go write(logs) } } func StdPrint(c1, c2 color.Attribute, str ...interface{}) { color.Set(c1) color.Set(c2) fmt.Print(str...) color.Set(color.Reset) } func StdPrintf(c1, c2 color.Attribute, format string, str ...interface{}) { color.Set(c1) color.Set(c2) fmt.Printf(format, str...) color.Set(color.Reset) } func StdPrintln(c1, c2 color.Attribute, str ...interface{}) { color.Set(c1) color.Set(c2) fmt.Println(str...) color.Set(color.Reset) } func Print(c1, c2 color.Attribute, str ...interface{}) { color.Set(c1) color.Set(c2) strs := fmt.Sprint(str...) fmt.Print(strs) color.Set(color.Reset) write(strs) } func Printf(c1, c2 color.Attribute, format string, str ...interface{}) { color.Set(c1) color.Set(c2) strs := fmt.Sprintf(format, str...) fmt.Print(strs) color.Set(color.Reset) write(strs) } func Println(c1, c2 color.Attribute, str ...interface{}) { color.Set(c1) color.Set(c2) strs := fmt.Sprintln(str...) fmt.Print(strs) color.Set(color.Reset) write(strs) } func Debug(str ...interface{}) { strs := fmt.Sprint(str...) output(LvDebug, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Debugf(format string, str ...interface{}) { strs := fmt.Sprintf(format, str...) output(LvDebug, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Debugln(str ...interface{}) { strs := fmt.Sprintln(str...) output(LvDebug, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Info(str ...interface{}) { strs := fmt.Sprint(str...) output(LvInfo, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Infof(format string, str ...interface{}) { strs := fmt.Sprintf(format, str...) output(LvInfo, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Infoln(str ...interface{}) { strs := fmt.Sprintln(str...) output(LvInfo, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Notice(str ...interface{}) { strs := fmt.Sprint(str...) output(LvNotice, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Noticef(format string, str ...interface{}) { strs := fmt.Sprintf(format, str...) output(LvNotice, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Noticeln(str ...interface{}) { strs := fmt.Sprintln(str...) output(LvNotice, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Warning(str ...interface{}) { strs := fmt.Sprint(str...) output(LvWarning, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Warningf(format string, str ...interface{}) { strs := fmt.Sprintf(format, str...) output(LvWarning, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Warningln(str ...interface{}) { strs := fmt.Sprintln(str...) output(LvWarning, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Error(str ...interface{}) { strs := fmt.Sprint(str...) output(LvError, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Errorf(format string, str ...interface{}) { strs := fmt.Sprintf(format, str...) output(LvError, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Errorln(str ...interface{}) { strs := fmt.Sprintln(str...) output(LvError, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Critical(str ...interface{}) { strs := fmt.Sprint(str...) output(LvCritical, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Criticalf(format string, str ...interface{}) { strs := fmt.Sprintf(format, str...) output(LvCritical, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Criticalln(str ...interface{}) { strs := fmt.Sprintln(str...) output(LvCritical, ShowLine, ShowLevel, DoWrite, DoShow, strs) } func Fatal(str ...interface{}) { strs := fmt.Sprint(str...) output(LvFatal, ShowLine, ShowLevel, DoWrite, DoShow, strs) CloseLog() os.Exit(9) } func Fatalf(format string, str ...interface{}) { strs := fmt.Sprintf(format, str...) output(LvFatal, ShowLine, ShowLevel, DoWrite, DoShow, strs) CloseLog() os.Exit(9) } func Fatalln(str ...interface{}) { strs := fmt.Sprintln(str...) output(LvFatal, ShowLine, ShowLevel, DoWrite, DoShow, strs) CloseLog() os.Exit(9) } func Panic(str ...interface{}) { strs := fmt.Sprint(str...) output(LvPanic, ShowLine, ShowLevel, DoWrite, DoShow, strs) panic(str) } func Panicf(format string, str ...interface{}) { strs := fmt.Sprintf(format, str...) output(LvPanic, ShowLine, ShowLevel, DoWrite, DoShow, strs) panic(strs) } func Panicln(str ...interface{}) { strs := fmt.Sprintln(str...) output(LvPanic, ShowLine, ShowLevel, DoWrite, DoShow, strs) panic(str) } func SetLogFile(path string) error { var err error loghandle, err = os.Create(path) switching = false return err } func SwitchFile(path string) error { switching = true if loghandle != nil { loghandle.Close() } return SetLogFile(path) } func CloseLog() { lock.Wait() if loghandle != nil { loghandle.Close() } }