123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- // Package zapx 提供了 zap 日志的对接
- package zapx
- import (
- "encoding/base64"
- "encoding/json"
- "fmt"
- "strconv"
- "time"
- "go.uber.org/zap/buffer"
- "go.uber.org/zap/zapcore"
- )
- var pool = buffer.NewPool()
- // 创建新的 encoder 对象
- func NewEncoder(category string, formatter CallerFormatFunc) zapcore.Encoder {
- return &encoder{
- key: "",
- category: category,
- formatCallerPath: formatter,
- entries: &recordEntries{
- stringEntries: []StringEntry{},
- floatEntries: []FloatEntry{},
- intEntries: []IntEntry{},
- boolEntries: []BoolEntry{},
- },
- }
- }
- // 调用方路径格式化函数类型
- type CallerFormatFunc = func(zapcore.EntryCaller) string
- // 格式化为全路径
- func CallerFullPath(c zapcore.EntryCaller) string { return c.FullPath() }
- // 格式化为相对路径
- func CallerTrimmedPath(c zapcore.EntryCaller) string { return c.TrimmedPath() }
- // 日志记录的参数
- type recordEntries struct {
- stringEntries []StringEntry
- floatEntries []FloatEntry
- intEntries []IntEntry
- boolEntries []BoolEntry
- }
- // 因为 json number 都是 double 型数字,最高有效位只有 53 位。所以为了避免精度丢失,需要对 int64 类型数据做以下处理:
- // - 能被 int32 表示的数据当作 int 数字处理。
- // - 在 double 类型安全范围内的数字当作 float64 数字处理。
- // - 无法用 double 表示的数字当作 string 处理。
- func addInt64(r *recordEntries, key string, value int64) {
- switch {
- case int64(int32(value)) == value:
- r.intEntries = append(r.intEntries, IntEntry{Key: key, Value: int32(value)})
- case int64(float64(value)) == value:
- r.floatEntries = append(r.floatEntries, FloatEntry{Key: key, Value: float64(value)})
- default:
- r.stringEntries = append(r.stringEntries, StringEntry{Key: key, Value: strconv.FormatInt(value, 10)})
- }
- }
- // uint 情况同上,转换规则为:
- // - 能被 int32 表示的数据当作 int 数字处理。
- // - 在 double 类型安全范围内的数字当作 float64 数字处理。
- // - 无法用 double 表示的数字当作 string 处理。
- func addUint64(r *recordEntries, key string, value uint64) {
- switch {
- case uint64(int32(value)) == value:
- r.intEntries = append(r.intEntries, IntEntry{Key: key, Value: int32(value)})
- case uint64(float64(value)) == value:
- r.floatEntries = append(r.floatEntries, FloatEntry{Key: key, Value: float64(value)})
- default:
- r.stringEntries = append(r.stringEntries, StringEntry{Key: key, Value: strconv.FormatUint(value, 10)})
- }
- }
- type encoder struct {
- key string
- category string
- formatCallerPath func(zapcore.EntryCaller) string
- entries *recordEntries
- }
- func (e *encoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
- var caller string
- if entry.Caller != (zapcore.EntryCaller{}) {
- caller = e.formatCallerPath(entry.Caller)
- }
- r := LogRecord{
- EventTime: entry.Time,
- Category: e.category,
- Level: entry.Level.String(),
- Caller: caller,
- Message: entry.Message,
- StringEntries: e.entries.stringEntries,
- FloatEntries: e.entries.floatEntries,
- IntEntries: e.entries.intEntries,
- BoolEntries: e.entries.boolEntries,
- }
- enc := &objectEncoder{
- key: e.key,
- entries: &recordEntries{
- stringEntries: []StringEntry{},
- floatEntries: []FloatEntry{},
- intEntries: []IntEntry{},
- boolEntries: []BoolEntry{},
- },
- }
- if entry.LoggerName != "" {
- enc.AddString("loggerName", entry.LoggerName)
- }
- for _, field := range fields {
- field.AddTo(enc)
- }
- if entry.Stack != "" {
- enc.AddString("stack", entry.Stack)
- }
- r.StringEntries = append(r.StringEntries, enc.entries.stringEntries...)
- r.FloatEntries = append(r.FloatEntries, enc.entries.floatEntries...)
- r.IntEntries = append(r.IntEntries, enc.entries.intEntries...)
- r.BoolEntries = append(r.BoolEntries, enc.entries.boolEntries...)
- bs, err := json.Marshal(r)
- if err != nil {
- return nil, err
- }
- buf := pool.Get()
- _, err = buf.Write(bs)
- if err != nil {
- return nil, err
- }
- return buf, nil
- }
- func (e *encoder) AddArray(key string, marshaler zapcore.ArrayMarshaler) error {
- return marshaler.MarshalLogArray(&sliceEncoder{key: addKey(e.key, key)})
- }
- func (e *encoder) AddObject(key string, marshaler zapcore.ObjectMarshaler) error {
- return marshaler.MarshalLogObject(&objectEncoder{key: addKey(e.key, key)})
- }
- // 不支持纯二进制类型,用 Base64 编码一下。
- func (e *encoder) AddBinary(key string, value []byte) {
- v := base64.StdEncoding.EncodeToString(value)
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: v})
- }
- func (e *encoder) AddByteString(key string, value []byte) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: string(value)})
- }
- func (e *encoder) AddBool(key string, value bool) {
- e.entries.boolEntries = append(e.entries.boolEntries, BoolEntry{Key: addKey(e.key, key), Value: value})
- }
- func (e *encoder) AddComplex128(key string, value complex128) {
- v := strconv.FormatComplex(value, 'f', -1, 128)
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: v})
- }
- func (e *encoder) AddComplex64(key string, value complex64) {
- v := strconv.FormatComplex(complex128(value), 'f', -1, 64)
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: v})
- }
- func (e *encoder) AddDuration(key string, value time.Duration) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: value.String()})
- }
- func (e *encoder) AddFloat64(key string, value float64) {
- e.entries.floatEntries = append(e.entries.floatEntries, FloatEntry{Key: addKey(e.key, key), Value: value})
- }
- func (e *encoder) AddFloat32(key string, value float32) {
- e.entries.floatEntries = append(e.entries.floatEntries, FloatEntry{Key: addKey(e.key, key), Value: float64(value)})
- }
- func (e *encoder) AddInt(key string, value int) {
- addInt64(e.entries, addKey(e.key, key), int64(value))
- }
- func (e *encoder) AddInt64(key string, value int64) {
- addInt64(e.entries, addKey(e.key, key), value)
- }
- func (e *encoder) AddInt32(key string, value int32) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addKey(e.key, key), Value: value})
- }
- func (e *encoder) AddInt16(key string, value int16) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addKey(e.key, key), Value: int32(value)})
- }
- func (e *encoder) AddInt8(key string, value int8) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addKey(e.key, key), Value: int32(value)})
- }
- func (e *encoder) AddString(key string, value string) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: value})
- }
- func (e *encoder) AddTime(key string, value time.Time) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: value.Format(time.RFC3339Nano)})
- }
- func (e *encoder) AddUint(key string, value uint) {
- addUint64(e.entries, addKey(e.key, key), uint64(value))
- }
- func (e *encoder) AddUint64(key string, value uint64) {
- addUint64(e.entries, addKey(e.key, key), value)
- }
- func (e *encoder) AddUint32(key string, value uint32) {
- addUint64(e.entries, addKey(e.key, key), uint64(value))
- }
- func (e *encoder) AddUint16(key string, value uint16) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addKey(e.key, key), Value: int32(value)})
- }
- func (e *encoder) AddUint8(key string, value uint8) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addKey(e.key, key), Value: int32(value)})
- }
- func (e *encoder) AddUintptr(key string, value uintptr) {
- addUint64(e.entries, addKey(e.key, key), uint64(value))
- }
- func (e *encoder) AddReflected(key string, value any) error {
- v := fmt.Sprint(value)
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: v})
- return nil
- }
- func (e *encoder) OpenNamespace(key string) {
- e.key = addKey(e.key, key)
- }
- func (e *encoder) Clone() zapcore.Encoder {
- return &encoder{
- key: e.key,
- category: e.category,
- formatCallerPath: e.formatCallerPath,
- entries: &recordEntries{
- stringEntries: e.entries.stringEntries,
- floatEntries: e.entries.floatEntries,
- intEntries: e.entries.intEntries,
- boolEntries: e.entries.boolEntries,
- },
- }
- }
- func addKey(parent, child string) string {
- if parent == "" {
- return child
- }
- return parent + "." + child
- }
- func addIndex(parent string, index int) string {
- return fmt.Sprintf("%s[%d]", parent, index)
- }
- type objectEncoder struct {
- key string
- entries *recordEntries
- }
- func (e *objectEncoder) AddArray(key string, marshaler zapcore.ArrayMarshaler) error {
- return marshaler.MarshalLogArray(&sliceEncoder{key: addKey(e.key, key), entries: e.entries})
- }
- func (e *objectEncoder) AddObject(key string, marshaler zapcore.ObjectMarshaler) error {
- return marshaler.MarshalLogObject(&objectEncoder{key: addKey(e.key, key), entries: e.entries})
- }
- // 不支持纯二进制类型,用 Base64 编码一下。
- func (e *objectEncoder) AddBinary(key string, value []byte) {
- v := base64.StdEncoding.EncodeToString(value)
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: v})
- }
- func (e *objectEncoder) AddByteString(key string, value []byte) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: string(value)})
- }
- func (e *objectEncoder) AddBool(key string, value bool) {
- e.entries.boolEntries = append(e.entries.boolEntries, BoolEntry{Key: addKey(e.key, key), Value: value})
- }
- func (e *objectEncoder) AddComplex128(key string, value complex128) {
- v := strconv.FormatComplex(value, 'f', -1, 128)
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: v})
- }
- func (e *objectEncoder) AddComplex64(key string, value complex64) {
- v := strconv.FormatComplex(complex128(value), 'f', -1, 64)
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: v})
- }
- func (e *objectEncoder) AddDuration(key string, value time.Duration) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: value.String()})
- }
- func (e *objectEncoder) AddFloat64(key string, value float64) {
- e.entries.floatEntries = append(e.entries.floatEntries, FloatEntry{Key: addKey(e.key, key), Value: value})
- }
- func (e *objectEncoder) AddFloat32(key string, value float32) {
- e.entries.floatEntries = append(e.entries.floatEntries, FloatEntry{Key: addKey(e.key, key), Value: float64(value)})
- }
- func (e *objectEncoder) AddInt(key string, value int) {
- addInt64(e.entries, addKey(e.key, key), int64(value))
- }
- func (e *objectEncoder) AddInt64(key string, value int64) {
- addInt64(e.entries, addKey(e.key, key), value)
- }
- func (e *objectEncoder) AddInt32(key string, value int32) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addKey(e.key, key), Value: value})
- }
- func (e *objectEncoder) AddInt16(key string, value int16) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addKey(e.key, key), Value: int32(value)})
- }
- func (e *objectEncoder) AddInt8(key string, value int8) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addKey(e.key, key), Value: int32(value)})
- }
- func (e *objectEncoder) AddString(key string, value string) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: value})
- }
- func (e *objectEncoder) AddTime(key string, value time.Time) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: value.Format(time.RFC3339Nano)})
- }
- func (e *objectEncoder) AddUint(key string, value uint) {
- addUint64(e.entries, addKey(e.key, key), uint64(value))
- }
- func (e *objectEncoder) AddUint64(key string, value uint64) {
- addUint64(e.entries, addKey(e.key, key), value)
- }
- func (e *objectEncoder) AddUint32(key string, value uint32) {
- addUint64(e.entries, addKey(e.key, key), uint64(value))
- }
- func (e *objectEncoder) AddUint16(key string, value uint16) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addKey(e.key, key), Value: int32(value)})
- }
- func (e *objectEncoder) AddUint8(key string, value uint8) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addKey(e.key, key), Value: int32(value)})
- }
- func (e *objectEncoder) AddUintptr(key string, value uintptr) {
- addUint64(e.entries, addKey(e.key, key), uint64(value))
- }
- func (e *objectEncoder) AddReflected(key string, value any) error {
- v := fmt.Sprint(value)
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addKey(e.key, key), Value: v})
- return nil
- }
- func (e *objectEncoder) OpenNamespace(key string) {
- e.key = addKey(e.key, key)
- }
- type sliceEncoder struct {
- key string
- index int
- entries *recordEntries
- }
- func (e *sliceEncoder) AppendBool(value bool) {
- e.entries.boolEntries = append(e.entries.boolEntries, BoolEntry{Key: addIndex(e.key, e.index), Value: value})
- e.index++
- }
- func (e *sliceEncoder) AppendByteString(value []byte) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addIndex(e.key, e.index), Value: string(value)})
- e.index++
- }
- func (e *sliceEncoder) AppendComplex128(value complex128) {
- v := strconv.FormatComplex(value, 'f', -1, 128)
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addIndex(e.key, e.index), Value: v})
- e.index++
- }
- func (e *sliceEncoder) AppendComplex64(value complex64) {
- v := strconv.FormatComplex(complex128(value), 'f', -1, 64)
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addIndex(e.key, e.index), Value: v})
- e.index++
- }
- func (e *sliceEncoder) AppendFloat64(value float64) {
- e.entries.floatEntries = append(e.entries.floatEntries, FloatEntry{Key: addIndex(e.key, e.index), Value: value})
- e.index++
- }
- func (e *sliceEncoder) AppendFloat32(value float32) {
- e.entries.floatEntries = append(e.entries.floatEntries, FloatEntry{Key: addIndex(e.key, e.index), Value: float64(value)})
- e.index++
- }
- func (e *sliceEncoder) AppendInt(value int) {
- addInt64(e.entries, addIndex(e.key, e.index), int64(value))
- e.index++
- }
- func (e *sliceEncoder) AppendInt64(value int64) {
- addInt64(e.entries, addIndex(e.key, e.index), value)
- e.index++
- }
- func (e *sliceEncoder) AppendInt32(value int32) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addIndex(e.key, e.index), Value: value})
- e.index++
- }
- func (e *sliceEncoder) AppendInt16(value int16) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addIndex(e.key, e.index), Value: int32(value)})
- e.index++
- }
- func (e *sliceEncoder) AppendInt8(value int8) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addIndex(e.key, e.index), Value: int32(value)})
- e.index++
- }
- func (e *sliceEncoder) AppendString(value string) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addIndex(e.key, e.index), Value: value})
- e.index++
- }
- func (e *sliceEncoder) AppendUint(value uint) {
- addUint64(e.entries, addIndex(e.key, e.index), uint64(value))
- e.index++
- }
- func (e *sliceEncoder) AppendUint64(value uint64) {
- addUint64(e.entries, addIndex(e.key, e.index), value)
- e.index++
- }
- func (e *sliceEncoder) AppendUint32(value uint32) {
- addUint64(e.entries, addIndex(e.key, e.index), uint64(value))
- e.index++
- }
- func (e *sliceEncoder) AppendUint16(value uint16) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addIndex(e.key, e.index), Value: int32(value)})
- e.index++
- }
- func (e *sliceEncoder) AppendUint8(value uint8) {
- e.entries.intEntries = append(e.entries.intEntries, IntEntry{Key: addIndex(e.key, e.index), Value: int32(value)})
- e.index++
- }
- func (e *sliceEncoder) AppendUintptr(value uintptr) {
- addUint64(e.entries, addIndex(e.key, e.index), uint64(value))
- e.index++
- }
- func (e *sliceEncoder) AppendDuration(value time.Duration) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addIndex(e.key, e.index), Value: value.String()})
- e.index++
- }
- func (e *sliceEncoder) AppendTime(value time.Time) {
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addIndex(e.key, e.index), Value: value.Format(time.RFC3339Nano)})
- e.index++
- }
- func (e *sliceEncoder) AppendArray(value zapcore.ArrayMarshaler) error {
- err := value.MarshalLogArray(&sliceEncoder{key: addIndex(e.key, e.index), entries: e.entries})
- e.index++
- return err
- }
- func (e *sliceEncoder) AppendObject(value zapcore.ObjectMarshaler) error {
- err := value.MarshalLogObject(&objectEncoder{key: addIndex(e.key, e.index), entries: e.entries})
- e.index++
- return err
- }
- func (e *sliceEncoder) AppendReflected(value any) error {
- v := fmt.Sprint(value)
- e.entries.stringEntries = append(e.entries.stringEntries, StringEntry{Key: addIndex(e.key, e.index), Value: v})
- e.index++
- return nil
- }
|