Skip to content

Commit fcf6d6a

Browse files
authored
log: provide registration for custom format encoder (#146)
Fixes #145
1 parent edc1105 commit fcf6d6a

File tree

2 files changed

+68
-7
lines changed

2 files changed

+68
-7
lines changed

log/zaplogger.go

+19-7
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,26 @@ func newEncoder(c *OutputConfig) zapcore.Encoder {
119119
if c.EnableColor {
120120
encoderCfg.EncodeLevel = zapcore.CapitalColorLevelEncoder
121121
}
122-
switch c.Formatter {
123-
case "console":
124-
return zapcore.NewConsoleEncoder(encoderCfg)
125-
case "json":
126-
return zapcore.NewJSONEncoder(encoderCfg)
127-
default:
128-
return zapcore.NewConsoleEncoder(encoderCfg)
122+
if newFormatEncoder, ok := formatEncoders[c.Formatter]; ok {
123+
return newFormatEncoder(encoderCfg)
129124
}
125+
// Defaults to console encoder.
126+
return zapcore.NewConsoleEncoder(encoderCfg)
127+
}
128+
129+
var formatEncoders = map[string]NewFormatEncoder{
130+
"console": zapcore.NewConsoleEncoder,
131+
"json": zapcore.NewJSONEncoder,
132+
}
133+
134+
// NewFormatEncoder is the function type for creating a format encoder out of an encoder config.
135+
type NewFormatEncoder func(zapcore.EncoderConfig) zapcore.Encoder
136+
137+
// RegisterFormatEncoder registers a NewFormatEncoder with the specified formatName key.
138+
// The existing formats include "console" and "json", but you can override these format encoders
139+
// or provide a new custom one.
140+
func RegisterFormatEncoder(formatName string, newFormatEncoder NewFormatEncoder) {
141+
formatEncoders[formatName] = newFormatEncoder
130142
}
131143

132144
// GetLogEncoderKey gets user defined log output name, uses defKey if empty.

log/zaplogger_test.go

+49
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ import (
1717
"errors"
1818
"fmt"
1919
"runtime"
20+
"strings"
2021
"testing"
2122
"time"
2223

2324
"github.com/stretchr/testify/assert"
2425
"github.com/stretchr/testify/require"
2526
"go.uber.org/zap"
27+
"go.uber.org/zap/buffer"
2628
"go.uber.org/zap/zapcore"
2729
"go.uber.org/zap/zaptest/observer"
2830

@@ -334,3 +336,50 @@ func TestLogEnableColor(t *testing.T) {
334336
l.Warn("hello")
335337
l.Error("hello")
336338
}
339+
340+
func TestLogNewFormatEncoder(t *testing.T) {
341+
const myFormatter = "myformatter"
342+
log.RegisterFormatEncoder(myFormatter, func(ec zapcore.EncoderConfig) zapcore.Encoder {
343+
return &consoleEncoder{
344+
Encoder: zapcore.NewJSONEncoder(zapcore.EncoderConfig{}),
345+
pool: buffer.NewPool(),
346+
cfg: ec,
347+
}
348+
})
349+
cfg := []log.OutputConfig{{Writer: "console", Level: "trace", Formatter: myFormatter}}
350+
l := log.NewZapLog(cfg).With(log.Field{Key: "trace-id", Value: "xx"})
351+
l.Trace("hello")
352+
l.Debug("hello")
353+
l.Info("hello")
354+
l.Warn("hello")
355+
l.Error("hello")
356+
// 2023/12/14 10:54:55 {"trace-id":"xx"} DEBUG hello
357+
// 2023/12/14 10:54:55 {"trace-id":"xx"} DEBUG hello
358+
// 2023/12/14 10:54:55 {"trace-id":"xx"} INFO hello
359+
// 2023/12/14 10:54:55 {"trace-id":"xx"} WARN hello
360+
// 2023/12/14 10:54:55 {"trace-id":"xx"} ERROR hello
361+
}
362+
363+
type consoleEncoder struct {
364+
zapcore.Encoder
365+
pool buffer.Pool
366+
cfg zapcore.EncoderConfig
367+
}
368+
369+
func (c consoleEncoder) Clone() zapcore.Encoder {
370+
return consoleEncoder{Encoder: c.Encoder.Clone(), pool: buffer.NewPool(), cfg: c.cfg}
371+
}
372+
373+
func (c consoleEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
374+
buf, err := c.Encoder.EncodeEntry(zapcore.Entry{}, nil)
375+
if err != nil {
376+
return nil, err
377+
}
378+
buffer := c.pool.Get()
379+
buffer.AppendString(entry.Time.Format("2006/01/02 15:04:05"))
380+
field := buf.String()
381+
buffer.AppendString(" " + field[:len(field)-1] + " ")
382+
buffer.AppendString(strings.ToUpper(entry.Level.String()) + " ")
383+
buffer.AppendString(entry.Message + "\n")
384+
return buffer, nil
385+
}

0 commit comments

Comments
 (0)