Skip to content

Commit

Permalink
log: provide registration for custom format encoder (#146)
Browse files Browse the repository at this point in the history
Fixes #145
  • Loading branch information
WineChord authored Dec 14, 2023
1 parent edc1105 commit fcf6d6a
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 7 deletions.
26 changes: 19 additions & 7 deletions log/zaplogger.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,26 @@ func newEncoder(c *OutputConfig) zapcore.Encoder {
if c.EnableColor {
encoderCfg.EncodeLevel = zapcore.CapitalColorLevelEncoder
}
switch c.Formatter {
case "console":
return zapcore.NewConsoleEncoder(encoderCfg)
case "json":
return zapcore.NewJSONEncoder(encoderCfg)
default:
return zapcore.NewConsoleEncoder(encoderCfg)
if newFormatEncoder, ok := formatEncoders[c.Formatter]; ok {
return newFormatEncoder(encoderCfg)
}
// Defaults to console encoder.
return zapcore.NewConsoleEncoder(encoderCfg)
}

var formatEncoders = map[string]NewFormatEncoder{
"console": zapcore.NewConsoleEncoder,
"json": zapcore.NewJSONEncoder,
}

// NewFormatEncoder is the function type for creating a format encoder out of an encoder config.
type NewFormatEncoder func(zapcore.EncoderConfig) zapcore.Encoder

// RegisterFormatEncoder registers a NewFormatEncoder with the specified formatName key.
// The existing formats include "console" and "json", but you can override these format encoders
// or provide a new custom one.
func RegisterFormatEncoder(formatName string, newFormatEncoder NewFormatEncoder) {
formatEncoders[formatName] = newFormatEncoder
}

// GetLogEncoderKey gets user defined log output name, uses defKey if empty.
Expand Down
49 changes: 49 additions & 0 deletions log/zaplogger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ import (
"errors"
"fmt"
"runtime"
"strings"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/buffer"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"

Expand Down Expand Up @@ -334,3 +336,50 @@ func TestLogEnableColor(t *testing.T) {
l.Warn("hello")
l.Error("hello")
}

func TestLogNewFormatEncoder(t *testing.T) {
const myFormatter = "myformatter"
log.RegisterFormatEncoder(myFormatter, func(ec zapcore.EncoderConfig) zapcore.Encoder {
return &consoleEncoder{
Encoder: zapcore.NewJSONEncoder(zapcore.EncoderConfig{}),
pool: buffer.NewPool(),
cfg: ec,
}
})
cfg := []log.OutputConfig{{Writer: "console", Level: "trace", Formatter: myFormatter}}
l := log.NewZapLog(cfg).With(log.Field{Key: "trace-id", Value: "xx"})
l.Trace("hello")
l.Debug("hello")
l.Info("hello")
l.Warn("hello")
l.Error("hello")
// 2023/12/14 10:54:55 {"trace-id":"xx"} DEBUG hello
// 2023/12/14 10:54:55 {"trace-id":"xx"} DEBUG hello
// 2023/12/14 10:54:55 {"trace-id":"xx"} INFO hello
// 2023/12/14 10:54:55 {"trace-id":"xx"} WARN hello
// 2023/12/14 10:54:55 {"trace-id":"xx"} ERROR hello
}

type consoleEncoder struct {
zapcore.Encoder
pool buffer.Pool
cfg zapcore.EncoderConfig
}

func (c consoleEncoder) Clone() zapcore.Encoder {
return consoleEncoder{Encoder: c.Encoder.Clone(), pool: buffer.NewPool(), cfg: c.cfg}
}

func (c consoleEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
buf, err := c.Encoder.EncodeEntry(zapcore.Entry{}, nil)
if err != nil {
return nil, err
}
buffer := c.pool.Get()
buffer.AppendString(entry.Time.Format("2006/01/02 15:04:05"))
field := buf.String()
buffer.AppendString(" " + field[:len(field)-1] + " ")
buffer.AppendString(strings.ToUpper(entry.Level.String()) + " ")
buffer.AppendString(entry.Message + "\n")
return buffer, nil
}

0 comments on commit fcf6d6a

Please sign in to comment.