package starlog import ( "fmt" "os" "path/filepath" "runtime" "strconv" "sync" "time" "github.com/fatih/color" "github.com/mattn/go-colorable" ) // Base attributes 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.FgHiRed BOLD = color.Bold ) // Log Level const ( LvDebug = iota LvInfo LvNotice LvWarning LvError LvCritical LvPanic LvFatal ) // Log Init Data 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 waiting = make(chan int, 1) ) // Output 使用此进行windows支持 var Output = colorable.NewColorableStdout() func write(logs string) { var i int lock.Add(1) 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 waiting <- 1 defer func() { <-waiting }() 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 { logcolor := color.New(Colors[level]...) logstr := logcolor.Sprint(logs) fmt.Fprint(Output, logstr) } if HandleFunc != nil { go HandleFunc(Colors[level], logs) } if dowrite { write(logs) } } // StdPrint 进行stdout标准输出 func StdPrint(c1, c2 color.Attribute, str ...interface{}) { waiting <- 1 defer func() { <-waiting }() colorstr := color.New(c1, c2) colorstr.Fprint(Output, str...) } func StdPrintf(c1, c2 color.Attribute, format string, str ...interface{}) { waiting <- 1 defer func() { <-waiting }() colorstr := color.New(c1, c2) colorstr.Fprintf(Output, format, str...) } func StdPrintln(c1, c2 color.Attribute, str ...interface{}) { waiting <- 1 defer func() { <-waiting }() colorstr := color.New(c1, c2) colorstr.Fprintln(Output, str...) } func Print(c1, c2 color.Attribute, str ...interface{}) { StdPrint(c1, c2, str...) write(fmt.Sprint(str...)) } func Printf(c1, c2 color.Attribute, format string, str ...interface{}) { StdPrintf(c1, c2, format, str...) write(fmt.Sprintf(format, str...)) } func Println(c1, c2 color.Attribute, str ...interface{}) { StdPrintln(c1, c2, str...) write(fmt.Sprintln(str...)) } 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() } }