Skip to content

Commit e0314ba

Browse files
author
mirkobrombin
committed
feat: add colored logging support and byte slice pooling for improved performance
1 parent 893069e commit e0314ba

File tree

3 files changed

+62
-16
lines changed

3 files changed

+62
-16
lines changed

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@ go 1.22
44

55
require (
66
github.com/armon/go-radix v1.0.0
7+
github.com/muesli/termenv v0.15.2
78
github.com/quic-go/quic-go v0.48.2
89
github.com/rivo/tview v0.0.0-20241103174730-c76f7879f592
910
github.com/rs/zerolog v1.33.0
10-
github.com/sirupsen/logrus v1.9.3
1111
github.com/spf13/cobra v1.8.1
1212
github.com/valyala/fasthttp v1.58.0
1313
github.com/yookoala/gofast v0.8.0
1414
)
1515

1616
require (
1717
github.com/andybalholm/brotli v1.1.1 // indirect
18+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
1819
github.com/gdamore/encoding v1.0.0 // indirect
1920
github.com/gdamore/tcell/v2 v2.7.1 // indirect
2021
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7X
22
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
33
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
44
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
5+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
6+
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
57
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
68
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
79
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -43,6 +45,8 @@ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APP
4345
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
4446
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
4547
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
48+
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
49+
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
4650
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
4751
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
4852
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
@@ -64,8 +68,6 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
6468
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
6569
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
6670
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
67-
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
68-
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
6971
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
7072
github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
7173
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
@@ -75,7 +77,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
7577
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
7678
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
7779
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
78-
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
7980
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
8081
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
8182
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
@@ -125,7 +126,6 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
125126
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
126127
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
127128
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
128-
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
129129
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
130130
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
131131
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

internal/logger/logger.go

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,34 @@ import (
55
"io"
66
"os"
77
"path/filepath"
8+
"sync"
89
"time"
910

1011
"github.com/mirkobrombin/goup/internal/config"
12+
"github.com/muesli/termenv"
1113
"github.com/rs/zerolog"
1214
)
1315

16+
var loggerBytePool = &byteSlicePool{
17+
pool: sync.Pool{
18+
New: func() interface{} {
19+
return make([]byte, 8*1024)
20+
},
21+
},
22+
}
23+
24+
type byteSlicePool struct {
25+
pool sync.Pool
26+
}
27+
28+
func (b *byteSlicePool) Get() []byte {
29+
return b.pool.Get().([]byte)
30+
}
31+
32+
func (b *byteSlicePool) Put(buf []byte) {
33+
b.pool.Put(buf)
34+
}
35+
1436
// Fields is a map of string keys to arbitrary values, emulating logrus.Fields
1537
// for compatibility with existing code.
1638
type Fields map[string]interface{}
@@ -36,6 +58,29 @@ func (l *Logger) WithFields(fields Fields) *Logger {
3658
}
3759
}
3860

61+
// ColoredConsoleWriter wraps an io.Writer to print colored logs.
62+
func ColoredConsoleWriter(out io.Writer) zerolog.ConsoleWriter {
63+
return zerolog.ConsoleWriter{
64+
Out: out,
65+
TimeFormat: "15:04:05",
66+
FormatLevel: func(i interface{}) string {
67+
level := i.(string)
68+
switch level {
69+
case "info":
70+
return termenv.String("INFO").Foreground(termenv.ANSICyan).String()
71+
case "warn":
72+
return termenv.String("WARN").Foreground(termenv.ANSIYellow).String()
73+
case "error":
74+
return termenv.String("ERROR").Foreground(termenv.ANSIRed).String()
75+
case "debug":
76+
return termenv.String("DEBUG").Foreground(termenv.ANSIWhite).String()
77+
default:
78+
return level
79+
}
80+
},
81+
}
82+
}
83+
3984
// Info logs a message at Info level.
4085
func (l *Logger) Info(msg string) {
4186
l.base.Info().Msg(msg)
@@ -56,7 +101,7 @@ func (l *Logger) Errorf(format string, args ...interface{}) {
56101
l.base.Error().Msgf(format, args...)
57102
}
58103

59-
// Debug logs a message at Debug level (not heavily used by default).
104+
// Debug logs a message at Debug level.
60105
func (l *Logger) Debug(msg string) {
61106
l.base.Debug().Msg(msg)
62107
}
@@ -76,7 +121,8 @@ func (l *Logger) Warnf(format string, args ...interface{}) {
76121
l.base.Warn().Msgf(format, args...)
77122
}
78123

79-
// NewLogger creates a new Logger that writes both to stdout and a site-specific file.
124+
// NewLogger creates a new Logger that writes JSON to files and colored
125+
// logs to stdout.
80126
func NewLogger(identifier string, fields Fields) (*Logger, error) {
81127
logDir := filepath.Join(
82128
config.GetLogDir(),
@@ -95,14 +141,13 @@ func NewLogger(identifier string, fields Fields) (*Logger, error) {
95141
return nil, err
96142
}
97143

98-
mw := io.MultiWriter(os.Stdout, file)
144+
multiWriter := io.MultiWriter(file, ColoredConsoleWriter(os.Stdout))
99145

100-
// Zerolog logger with time + multiwriter
101-
base := zerolog.New(mw).With().Timestamp().Logger()
146+
base := zerolog.New(multiWriter).With().Timestamp().Logger()
102147

103148
l := &Logger{
104149
base: base,
105-
out: mw,
150+
out: multiWriter,
106151
}
107152

108153
if fields != nil {
@@ -112,7 +157,7 @@ func NewLogger(identifier string, fields Fields) (*Logger, error) {
112157
return l, nil
113158
}
114159

115-
// NewPluginLogger creates a plugin-specific log file (no stdout).
160+
// NewPluginLogger creates a plugin-specific log file (JSON format, no stdout).
116161
func NewPluginLogger(siteDomain, pluginName string) (*Logger, error) {
117162
logDir := filepath.Join(
118163
config.GetLogDir(),
@@ -147,7 +192,9 @@ func (l *Logger) Writer() io.WriteCloser {
147192

148193
go func() {
149194
defer pr.Close()
150-
buf := make([]byte, 1024)
195+
buf := loggerBytePool.Get()
196+
defer loggerBytePool.Put(buf)
197+
151198
var tmp []byte
152199

153200
for {
@@ -176,9 +223,7 @@ func (l *Logger) Writer() io.WriteCloser {
176223
}
177224
}()
178225

179-
return &pipeWriteCloser{
180-
pipeWriter: pw,
181-
}
226+
return &pipeWriteCloser{pipeWriter: pw}
182227
}
183228

184229
// pipeWriteCloser implements Write and Close delegating to a PipeWriter.

0 commit comments

Comments
 (0)