9 "github.com/go-kit/kit/log"
12 // Color represents an ANSI color. The zero value is Default.
40 // For more on ANSI escape codes see
41 // https://en.wikipedia.org/wiki/ANSI_escape_code. See in particular
42 // https://en.wikipedia.org/wiki/ANSI_escape_code#Colors.
45 resetColorBytes = []byte("\x1b[39;49;22m")
52 fgColorBytes = append(fgColorBytes, []byte("\x1b[39m"))
53 bgColorBytes = append(bgColorBytes, []byte("\x1b[49m"))
56 for color := Black; color < DarkGray; color++ {
57 fgColorBytes = append(fgColorBytes, []byte(fmt.Sprintf("\x1b[%dm", 30+color-Black)))
58 bgColorBytes = append(bgColorBytes, []byte(fmt.Sprintf("\x1b[%dm", 40+color-Black)))
62 for color := DarkGray; color < numColors; color++ {
63 fgColorBytes = append(fgColorBytes, []byte(fmt.Sprintf("\x1b[%d;1m", 30+color-DarkGray)))
64 bgColorBytes = append(bgColorBytes, []byte(fmt.Sprintf("\x1b[%d;1m", 40+color-DarkGray)))
68 // FgBgColor represents a foreground and background color.
69 type FgBgColor struct {
73 func (c FgBgColor) isZero() bool {
74 return c.Fg == Default && c.Bg == Default
77 // NewColorLogger returns a Logger which writes colored logs to w. ANSI color
78 // codes for the colors returned by color are added to the formatted output
79 // from the Logger returned by newLogger and the combined result written to w.
80 func NewColorLogger(w io.Writer, newLogger func(io.Writer) log.Logger, color func(keyvals ...interface{}) FgBgColor) log.Logger {
82 panic("color func nil")
88 bufPool: sync.Pool{New: func() interface{} { return &loggerBuf{} }},
89 noColorLogger: newLogger(w),
93 type colorLogger struct {
95 newLogger func(io.Writer) log.Logger
96 color func(keyvals ...interface{}) FgBgColor
98 noColorLogger log.Logger
101 func (l *colorLogger) Log(keyvals ...interface{}) error {
102 color := l.color(keyvals...)
104 return l.noColorLogger.Log(keyvals...)
107 lb := l.getLoggerBuf()
108 defer l.putLoggerBuf(lb)
109 if color.Fg != Default {
110 lb.buf.Write(fgColorBytes[color.Fg])
112 if color.Bg != Default {
113 lb.buf.Write(bgColorBytes[color.Bg])
115 err := lb.logger.Log(keyvals...)
119 if color.Fg != Default || color.Bg != Default {
120 lb.buf.Write(resetColorBytes)
122 _, err = io.Copy(l.w, lb.buf)
126 type loggerBuf struct {
131 func (l *colorLogger) getLoggerBuf() *loggerBuf {
132 lb := l.bufPool.Get().(*loggerBuf)
134 lb.buf = &bytes.Buffer{}
135 lb.logger = l.newLogger(lb.buf)
142 func (l *colorLogger) putLoggerBuf(cb *loggerBuf) {