Core

/app/lib/log/encoder.go (2.4 KB)

  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package log

import (
"fmt"
"strings"

"github.com/pkg/errors"
"github.com/samber/lo"
"go.uber.org/zap/buffer"
"go.uber.org/zap/zapcore"

"{{{ .Package }}}/app/util"
)

const timeFormat = "15:04:05.000000"

type customEncoder struct {
zapcore.Encoder
colored bool
pool buffer.Pool
}

func newEncoder(cfg zapcore.EncoderConfig, colored bool) *customEncoder {
return &customEncoder{Encoder: zapcore.NewJSONEncoder(cfg), colored: colored, pool: buffer.NewPool()}
}

func (e *customEncoder) Clone() zapcore.Encoder {
return &customEncoder{Encoder: e.Encoder.Clone(), colored: e.colored, pool: e.pool}
}

func (e *customEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
go func() {
recentMU.Lock()
defer recentMU.Unlock()
RecentLogs = append(RecentLogs, &entry)
if len(RecentLogs) > 50 {
RecentLogs = RecentLogs[1:]
}
}()
b, err := e.Encoder.EncodeEntry(entry, fields)
if err != nil {
return nil, errors.Wrap(err, "logging error")
}
out := b.Bytes()
b.Free()

data, err := util.FromJSONMap(out)
if err != nil {
return nil, errors.Wrap(err, "can't parse logging JSON")
}

ret := e.pool.Get()
ret.AppendByte('\n')
addLine := func(l string) {
ret.AppendString(l)
ret.AppendByte('\n')
}

lvl := fmt.Sprintf("%-5v", entry.Level.CapitalString())
if e.colored {
lvl = levelToColor[entry.Level.String()].Add(lvl)
}
tm := entry.Time.Format(timeFormat)

msg := entry.Message
var msgLines []string
if strings.Contains(msg, "\n") {
msgLines = util.StringSplitLines(msg)
msg = msgLines[0]
msgLines = msgLines[1:]
}

if e.colored {
addLine(fmt.Sprintf("[%s] %s %s", lvl, tm, Cyan.Add(msg)))
} else {
addLine(fmt.Sprintf("[%s] %s %s", lvl, tm, msg))
}

lo.ForEach(msgLines, func(ml string, _ int) {
if e.colored {
if strings.Contains(ml, util.AppKey) {
ml = Green.Add(ml)
}
addLine(" " + Cyan.Add(ml))
} else {
addLine(" " + ml)
}
})
if len(data) > 0 {
addLine(" " + util.ToJSONCompact(data))
}
caller := entry.Caller.String()
if entry.Caller.Function != "" {
caller += " (" + entry.Caller.Function + ")"
}
addLine(" " + caller)

if entry.Stack != "" {
st := util.StringSplitLines(entry.Stack)
lo.ForEach(st, func(stl string, _ int) {
if strings.Contains(stl, util.AppKey) {
stl = Green.Add(stl)
}
addLine(" " + stl)
})
}
return ret, nil
}