package log import ( "fmt" "golang.org/x/term" "io" "os" "strings" ) // ColorMode indicates if colorized output should be used type ColorMode int const ( // ColorAuto means to automatically detect if a writer is an interactive terminal and // if so use colorized output. ColorAuto ColorMode = 0 // ColorNever avoids colorized output at all. ColorNever ColorMode = -1 // ColorAlways enforces colorized output even if it is routed into some file. ColorAlways ColorMode = 1 // ColorOn means to enable colorized output. ColorOn ColorMode = 1 // ColorOff means not to use colorized output. ColorOff ColorMode = -1 ) // Colorize indicates if colorized output should be used. func (c ColorMode) Colorize() bool { return c > 0 } type PlainFormatter struct { UseColor ColorMode /* avoid checking the output fd on each log message. Only do so if fd changed */ lastFd int fdColor ColorMode } func (f *PlainFormatter) resolveColorMode(target io.Writer) ColorMode { if f.UseColor == ColorAuto { fd := -1 if file, ok := target.(*os.File); ok { fd = int(file.Fd()) } if f.fdColor == ColorAuto || fd != f.lastFd { // update cache f.lastFd = fd if fd > -1 && term.IsTerminal(fd) { f.fdColor = ColorOn } else { f.fdColor = ColorOff } } return f.fdColor } return f.UseColor } type levelColorData struct { Dark string Light string } /* fg bg Black 30/90 40/100 Red 31 41 Green 32 42 Yellow 33 43 Blue 34 44 Magenta 35 45 Cyan 36 46 White 37 47 */ var levelColorDatas = []levelColorData{ /* SILENT */ {Dark: "\033[30;107m", Light: ""}, // never ever log it? /* PANIC */ {Dark: "\033[93;101m", Light: ""}, /* FATAL */ {Dark: "\033[30;101m", Light: ""}, /* ERROR */ {Dark: "\033[91m", Light: ""}, /* WARN */ {Dark: "\033[33m", Light: ""}, /* NOTICE */ {Dark: "\033[95m", Light: ""}, /* INFO */ {Dark: "\033[97m", Light: ""}, /* DEBUG */ {Dark: "\033[37m", Light: ""}, /* TRACE */ {Dark: "\033[90m", Light: ""}, } func (f *PlainFormatter) String() string { return "PlainFormatter" } func (f *PlainFormatter) Output(message string, envelope Envelope) { o := envelope.Logger().Target() cm := f.resolveColorMode(o) msg := "" if cm.Colorize() { msg += levelColorDatas[envelope.Level()].Dark } msg += envelope.Time().Format("20060102-150405.000000") + " " if envelope.Logger() != 0 { msg += "[" + envelope.Logger().String() + "] " } msg += envelope.Level().String() + ": " msg += strings.TrimSpace(message) if envelope.Error() != nil { msg += fmt.Sprintf(" [err=%v]", envelope.Error()) } for _, v := range envelope.Arguments() { msg += " " + v.String() } if cm.Colorize() { msg += "\033[0m" } msg += "\n" // "time (logger) level message args" fmt.Fprint(o, msg) }