ceph-csi/vendor/github.com/gemalto/flume/console_encoder.go

226 lines
5.6 KiB
Go
Raw Permalink Normal View History

package flume
import (
"encoding/hex"
"github.com/mgutz/ansi"
"go.uber.org/zap"
"go.uber.org/zap/buffer"
"go.uber.org/zap/zapcore"
)
//nolint:gochecknoinits
func init() {
_ = zap.RegisterEncoder("term", func(cfg zapcore.EncoderConfig) (zapcore.Encoder, error) {
return NewConsoleEncoder((*EncoderConfig)(&cfg)), nil
})
_ = zap.RegisterEncoder("term-color", func(cfg zapcore.EncoderConfig) (zapcore.Encoder, error) {
return NewColorizedConsoleEncoder((*EncoderConfig)(&cfg), nil), nil
})
}
// Colorizer returns ansi escape sequences for the colors for each log level.
// See Colors for a default implementation.
type Colorizer interface {
Level(l Level) string
}
// Colors is an implementation of the Colorizer interface, which assigns colors
// to the default log levels.
type Colors struct {
Debug, Info, Warn, Error string
}
// Level implements Colorizer
func (c *Colors) Level(l Level) string {
if l < DebugLevel {
return Dim
}
switch l {
case DebugLevel:
return c.Debug
case InfoLevel:
return c.Info
case Level(zapcore.WarnLevel):
return c.Warn
default:
return c.Error
}
}
// DefaultColors is the default instance of Colors, used as the default colors if
// a nil Colorizer is passed to NewColorizedConsoleEncoder.
var DefaultColors = Colors{
Debug: ansi.ColorCode("cyan"),
Info: ansi.ColorCode("green+h"),
Warn: ansi.ColorCode("yellow+bh"),
Error: ansi.ColorCode("red+bh"),
}
type consoleEncoder struct {
*ltsvEncoder
colorizer Colorizer
}
// NewConsoleEncoder creates an encoder whose output is designed for human -
// rather than machine - consumption. It serializes the core log entry data
// (message, level, timestamp, etc.) in a plain-text format. The context is
// encoded in LTSV.
//
// Note that although the console encoder doesn't use the keys specified in the
// encoder configuration, it will omit any element whose key is set to the empty
// string.
func NewConsoleEncoder(cfg *EncoderConfig) Encoder {
ltsvEncoder := NewLTSVEncoder(cfg).(*ltsvEncoder)
ltsvEncoder.allowNewLines = true
ltsvEncoder.allowTabs = true
ltsvEncoder.blankKey = "value"
ltsvEncoder.binaryEncoder = hex.Dump
return &consoleEncoder{ltsvEncoder: ltsvEncoder}
}
// NewColorizedConsoleEncoder creates a console encoder, like NewConsoleEncoder, but
// colors the text with ansi escape codes. `colorize` configures which colors to
// use for each level.
//
// If `colorizer` is nil, it will default to DefaultColors.
//
// `github.com/mgutz/ansi` is a convenient package for getting color codes, e.g.:
//
// ansi.ColorCode("red")
//
func NewColorizedConsoleEncoder(cfg *EncoderConfig, colorizer Colorizer) Encoder {
e := NewConsoleEncoder(cfg).(*consoleEncoder)
e.colorizer = colorizer
if e.colorizer == nil {
e.colorizer = &DefaultColors
}
return e
}
// Clone implements the Encoder interface
func (c *consoleEncoder) Clone() zapcore.Encoder {
return &consoleEncoder{
ltsvEncoder: c.ltsvEncoder.Clone().(*ltsvEncoder),
colorizer: c.colorizer,
}
}
// Dim is the color used for context keys, time, and caller information
var Dim = ansi.ColorCode("240")
// Bright is the color used for the message
var Bright = ansi.ColorCode("default+b")
// EncodeEntry implements the Encoder interface
func (c *consoleEncoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
final := *c.ltsvEncoder
context := final.buf
final.buf = bufPool.Get()
origLen := final.buf.Len()
if c.TimeKey != "" {
c.colorDim(final.buf)
final.skipNextElementSeparator = true
c.EncodeTime(ent.Time, &final)
}
if c.LevelKey != "" {
c.colorLevel(final.buf, ent.Level)
if final.buf.Len() > origLen {
final.buf.AppendByte(' ')
}
final.skipNextElementSeparator = true
c.EncodeLevel(ent.Level, &final)
}
if final.buf.Len() > origLen {
c.colorDim(final.buf)
final.buf.AppendString(" | ")
} else {
final.buf.Reset()
}
// Add the message itself.
if c.MessageKey != "" {
c.colorReset(final.buf)
// c.colorBright(&final)
final.safeAddString(ent.Message, false)
// ensure a minimum of 2 spaces between the message and the fields,
// to improve readability
final.buf.AppendString(" ")
}
c.colorDim(final.buf)
// Add fields.
for _, f := range fields {
f.AddTo(&final)
}
// Add context
if context.Len() > 0 {
final.addFieldSeparator()
_, _ = final.buf.Write(context.Bytes())
}
// Add callsite
c.writeCallSite(&final, ent.LoggerName, ent.Caller)
// If there's no stacktrace key, honor that; this allows users to force
// single-line output.
if ent.Stack != "" && c.StacktraceKey != "" {
final.buf.AppendByte('\n')
final.buf.AppendString(ent.Stack)
}
c.colorReset(final.buf)
final.buf.AppendByte('\n')
return final.buf, nil
}
func (c *consoleEncoder) writeCallSite(final *ltsvEncoder, name string, caller zapcore.EntryCaller) {
shouldWriteName := name != "" && c.NameKey != ""
shouldWriteCaller := caller.Defined && c.CallerKey != ""
if !shouldWriteName && !shouldWriteCaller {
return
}
final.addKey("@")
if shouldWriteName {
final.buf.AppendString(name)
if shouldWriteCaller {
final.buf.AppendByte('@')
}
}
if shouldWriteCaller {
final.skipNextElementSeparator = true
final.EncodeCaller(caller, final)
}
}
func (c *consoleEncoder) colorDim(buf *buffer.Buffer) {
c.applyColor(buf, Dim)
}
func (c *consoleEncoder) colorLevel(buf *buffer.Buffer, level zapcore.Level) {
if c.colorizer != nil {
c.applyColor(buf, c.colorizer.Level(Level(level)))
}
}
func (c *consoleEncoder) applyColor(buf *buffer.Buffer, s string) {
if c.colorizer != nil {
buf.AppendString(ansi.Reset)
if s != "" {
buf.AppendString(s)
}
}
}
func (c *consoleEncoder) colorReset(buf *buffer.Buffer) {
c.applyColor(buf, "")
}