@@ -5,12 +5,34 @@ import (
5
5
"io"
6
6
"os"
7
7
"path/filepath"
8
+ "sync"
8
9
"time"
9
10
10
11
"github.com/mirkobrombin/goup/internal/config"
12
+ "github.com/muesli/termenv"
11
13
"github.com/rs/zerolog"
12
14
)
13
15
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
+
14
36
// Fields is a map of string keys to arbitrary values, emulating logrus.Fields
15
37
// for compatibility with existing code.
16
38
type Fields map [string ]interface {}
@@ -36,6 +58,29 @@ func (l *Logger) WithFields(fields Fields) *Logger {
36
58
}
37
59
}
38
60
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
+
39
84
// Info logs a message at Info level.
40
85
func (l * Logger ) Info (msg string ) {
41
86
l .base .Info ().Msg (msg )
@@ -56,7 +101,7 @@ func (l *Logger) Errorf(format string, args ...interface{}) {
56
101
l .base .Error ().Msgf (format , args ... )
57
102
}
58
103
59
- // Debug logs a message at Debug level (not heavily used by default) .
104
+ // Debug logs a message at Debug level.
60
105
func (l * Logger ) Debug (msg string ) {
61
106
l .base .Debug ().Msg (msg )
62
107
}
@@ -76,7 +121,8 @@ func (l *Logger) Warnf(format string, args ...interface{}) {
76
121
l .base .Warn ().Msgf (format , args ... )
77
122
}
78
123
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.
80
126
func NewLogger (identifier string , fields Fields ) (* Logger , error ) {
81
127
logDir := filepath .Join (
82
128
config .GetLogDir (),
@@ -95,14 +141,13 @@ func NewLogger(identifier string, fields Fields) (*Logger, error) {
95
141
return nil , err
96
142
}
97
143
98
- mw := io .MultiWriter (os .Stdout , file )
144
+ multiWriter := io .MultiWriter (file , ColoredConsoleWriter ( os .Stdout ) )
99
145
100
- // Zerolog logger with time + multiwriter
101
- base := zerolog .New (mw ).With ().Timestamp ().Logger ()
146
+ base := zerolog .New (multiWriter ).With ().Timestamp ().Logger ()
102
147
103
148
l := & Logger {
104
149
base : base ,
105
- out : mw ,
150
+ out : multiWriter ,
106
151
}
107
152
108
153
if fields != nil {
@@ -112,7 +157,7 @@ func NewLogger(identifier string, fields Fields) (*Logger, error) {
112
157
return l , nil
113
158
}
114
159
115
- // NewPluginLogger creates a plugin-specific log file (no stdout).
160
+ // NewPluginLogger creates a plugin-specific log file (JSON format, no stdout).
116
161
func NewPluginLogger (siteDomain , pluginName string ) (* Logger , error ) {
117
162
logDir := filepath .Join (
118
163
config .GetLogDir (),
@@ -147,7 +192,9 @@ func (l *Logger) Writer() io.WriteCloser {
147
192
148
193
go func () {
149
194
defer pr .Close ()
150
- buf := make ([]byte , 1024 )
195
+ buf := loggerBytePool .Get ()
196
+ defer loggerBytePool .Put (buf )
197
+
151
198
var tmp []byte
152
199
153
200
for {
@@ -176,9 +223,7 @@ func (l *Logger) Writer() io.WriteCloser {
176
223
}
177
224
}()
178
225
179
- return & pipeWriteCloser {
180
- pipeWriter : pw ,
181
- }
226
+ return & pipeWriteCloser {pipeWriter : pw }
182
227
}
183
228
184
229
// pipeWriteCloser implements Write and Close delegating to a PipeWriter.
0 commit comments