@@ -2,18 +2,18 @@ package logflags
2
2
3
3
import (
4
4
"bytes"
5
+ "context"
5
6
"errors"
6
7
"fmt"
7
8
"io"
8
9
"log"
10
+ "log/slog"
9
11
"net"
10
12
"os"
11
13
"sort"
12
14
"strconv"
13
15
"strings"
14
16
"time"
15
-
16
- "github.com/sirupsen/logrus"
17
17
)
18
18
19
19
var any = false
@@ -29,20 +29,25 @@ var stack = false
29
29
30
30
var logOut io.WriteCloser
31
31
32
- func makeLogger (flag bool , fields Fields ) Logger {
32
+ func makeLogger (flag bool , attrs ... interface {} ) Logger {
33
33
if lf := loggerFactory ; lf != nil {
34
+ fields := make (Fields )
35
+ for i := 0 ; i < len (attrs ); i += 2 {
36
+ fields [attrs [i ].(string )] = attrs [i + 1 ]
37
+ }
34
38
return lf (flag , fields , logOut )
35
39
}
36
- logger := logrus . New (). WithFields ( logrus . Fields ( fields ))
37
- logger . Logger . Formatter = DefaultFormatter ()
40
+
41
+ var out io. WriteCloser = os . Stderr
38
42
if logOut != nil {
39
- logger . Logger . Out = logOut
43
+ out = logOut
40
44
}
41
- logger . Logger . Level = logrus . ErrorLevel
45
+ level := slog . LevelError
42
46
if flag {
43
- logger . Logger . Level = logrus . DebugLevel
47
+ level = slog . LevelDebug
44
48
}
45
- return & logrusLogger {logger }
49
+ logger := slog .New (newTextHandler (out , & slog.HandlerOptions {Level : level })).With (attrs ... )
50
+ return slogLogger {logger }
46
51
}
47
52
48
53
// Any returns true if any logging is enabled.
@@ -58,7 +63,7 @@ func GdbWire() bool {
58
63
59
64
// GdbWireLogger returns a configured logger for the gdbserial wire protocol.
60
65
func GdbWireLogger () Logger {
61
- return makeLogger (gdbWire , Fields { "layer" : "gdbconn" } )
66
+ return makeLogger (gdbWire , "layer" , "gdbconn" )
62
67
}
63
68
64
69
// Debugger returns true if the debugger package should log.
@@ -68,7 +73,7 @@ func Debugger() bool {
68
73
69
74
// DebuggerLogger returns a logger for the debugger package.
70
75
func DebuggerLogger () Logger {
71
- return makeLogger (debugger , Fields { "layer" : "debugger" } )
76
+ return makeLogger (debugger , "layer" , "debugger" )
72
77
}
73
78
74
79
// LLDBServerOutput returns true if the output of the LLDB server should be
@@ -85,7 +90,7 @@ func DebugLineErrors() bool {
85
90
86
91
// DebugLineLogger returns a logger for the dwarf/line package.
87
92
func DebugLineLogger () Logger {
88
- return makeLogger (debugLineErrors , Fields { "layer" : "dwarf-line" } )
93
+ return makeLogger (debugLineErrors , "layer" , "dwarf-line" )
89
94
}
90
95
91
96
// RPC returns true if RPC messages should be logged.
@@ -100,7 +105,7 @@ func RPCLogger() Logger {
100
105
101
106
// rpcLogger returns a logger for RPC messages set to a specific minimal log level.
102
107
func rpcLogger (flag bool ) Logger {
103
- return makeLogger (flag , Fields { "layer" : "rpc" } )
108
+ return makeLogger (flag , "layer" , "rpc" )
104
109
}
105
110
106
111
// DAP returns true if dap package should log.
@@ -110,7 +115,7 @@ func DAP() bool {
110
115
111
116
// DAPLogger returns a logger for dap package.
112
117
func DAPLogger () Logger {
113
- return makeLogger (dap , Fields { "layer" : "dap" } )
118
+ return makeLogger (dap , "layer" , "dap" )
114
119
}
115
120
116
121
// FnCall returns true if the function call protocol should be logged.
@@ -119,7 +124,7 @@ func FnCall() bool {
119
124
}
120
125
121
126
func FnCallLogger () Logger {
122
- return makeLogger (fnCall , Fields { "layer" : "proc" , "kind" : "fncall" } )
127
+ return makeLogger (fnCall , "layer" , "proc" , "kind" , "fncall" )
123
128
}
124
129
125
130
// Minidump returns true if the minidump loader should be logged.
@@ -128,7 +133,7 @@ func Minidump() bool {
128
133
}
129
134
130
135
func MinidumpLogger () Logger {
131
- return makeLogger (minidump , Fields { "layer" : "core" , "kind" : "minidump" } )
136
+ return makeLogger (minidump , "layer" , "core" , "kind" , "minidump" )
132
137
}
133
138
134
139
// Stack returns true if the stacktracer should be logged.
@@ -137,7 +142,7 @@ func Stack() bool {
137
142
}
138
143
139
144
func StackLogger () Logger {
140
- return makeLogger (stack , Fields { "layer" : "core" , "kind" : "stack" } )
145
+ return makeLogger (stack , "layer" , "core" , "kind" , "stack" )
141
146
}
142
147
143
148
// WriteDAPListeningMessage writes the "DAP server listening" message in dap mode.
@@ -162,7 +167,7 @@ func writeListeningMessage(server string, addr net.Addr) {
162
167
return
163
168
}
164
169
logger := rpcLogger (true )
165
- logger .Warn ("Listening for remote connections (connections are not authenticated nor encrypted)" )
170
+ logger .Warnf ("Listening for remote connections (connections are not authenticated nor encrypted)" )
166
171
}
167
172
168
173
func WriteError (msg string ) {
@@ -173,6 +178,10 @@ func WriteError(msg string) {
173
178
}
174
179
}
175
180
181
+ func WriteCgoFlagsWarning () {
182
+ makeLogger (true , "layer" , "dlv" ).Warn ("CGO_CFLAGS already set, Cgo code could be optimized." )
183
+ }
184
+
176
185
var errLogstrWithoutLog = errors .New ("--log-output specified without --log" )
177
186
178
187
// Setup sets debugger flags based on the contents of logstr.
@@ -240,59 +249,91 @@ func Close() {
240
249
}
241
250
}
242
251
243
- // DefaultFormatter provides a simplified version of logrus.TextFormatter that
244
- // doesn't make logs unreadable when they are output to a text file or to a
245
- // terminal that doesn't support colors.
246
- func DefaultFormatter () logrus. Formatter {
247
- return textFormatterInstance
252
+ type textHandler struct {
253
+ out io. WriteCloser
254
+ opts slog. HandlerOptions
255
+ attrs []slog. Attr
256
+ preformattedAttrs string // preformatted version of attrs for optimization purposes
248
257
}
249
258
250
- type textFormatter struct {}
259
+ func newTextHandler (out io.WriteCloser , opts * slog.HandlerOptions ) * textHandler {
260
+ return & textHandler {
261
+ out : out ,
262
+ opts : * opts ,
263
+ }
264
+ }
251
265
252
- var textFormatterInstance = & textFormatter {}
266
+ func (h * textHandler ) Enabled (_ context.Context , l slog.Level ) bool {
267
+ return l >= h .opts .Level .Level ()
268
+ }
253
269
254
- func (f * textFormatter ) Format (entry * logrus.Entry ) ([]byte , error ) {
255
- var b * bytes.Buffer
256
- if entry .Buffer != nil {
257
- b = entry .Buffer
258
- } else {
259
- b = & bytes.Buffer {}
270
+ func (h * textHandler ) WithAttrs (attrs []slog.Attr ) slog.Handler {
271
+ h2 := * h
272
+ h2 .attrs = append (h2 .attrs , attrs ... )
273
+ m := map [string ]slog.Value {}
274
+ keys := []string {}
275
+ for i := range attrs {
276
+ m [attrs [i ].Key ] = attrs [i ].Value
277
+ keys = append (keys , attrs [i ].Key )
278
+ }
279
+ sort .Strings (keys )
280
+ b := new (bytes.Buffer )
281
+ for _ , key := range keys {
282
+ appendAttr (b , key , m [key ])
260
283
}
284
+ b .Truncate (b .Len () - 1 )
285
+ h2 .preformattedAttrs = b .String ()
286
+ return & h2
287
+ }
261
288
262
- keys := make ([]string , 0 , len (entry .Data ))
263
- for k := range entry .Data {
264
- keys = append (keys , k )
289
+ func appendAttr (b * bytes.Buffer , key string , val slog.Value ) {
290
+ b .WriteString (key )
291
+ b .WriteByte ('=' )
292
+ stringVal := val .String ()
293
+ if needsQuoting (stringVal ) {
294
+ fmt .Fprintf (b , "%q" , stringVal )
295
+ } else {
296
+ b .WriteString (stringVal )
265
297
}
266
- sort .Strings (keys )
298
+ b .WriteByte (',' )
299
+ }
300
+
301
+ func (h * textHandler ) WithGroup (group string ) slog.Handler {
302
+ // group not handled
303
+ return h
304
+ }
305
+
306
+ func (h * textHandler ) Handle (_ context.Context , entry slog.Record ) error {
307
+ b := & bytes.Buffer {}
267
308
268
309
b .WriteString (entry .Time .Format (time .RFC3339 ))
269
310
b .WriteByte (' ' )
270
- b .WriteString (entry .Level .String ())
311
+ b .WriteString (strings . ToLower ( entry .Level .String () ))
271
312
b .WriteByte (' ' )
272
- for i , key := range keys {
273
- b .WriteString (key )
274
- b .WriteByte ('=' )
275
- stringVal , ok := entry .Data [key ].(string )
276
- if ! ok {
277
- stringVal = fmt .Sprint (entry .Data [key ])
278
- }
279
- if f .needsQuoting (stringVal ) {
280
- fmt .Fprintf (b , "%q" , stringVal )
281
- } else {
282
- b .WriteString (stringVal )
283
- }
284
- if i != len (keys )- 1 {
285
- b .WriteByte (',' )
286
- } else {
313
+ b .WriteString (h .preformattedAttrs )
314
+
315
+ if entry .NumAttrs () > 0 {
316
+ if len (h .preformattedAttrs ) > 0 {
287
317
b .WriteByte (' ' )
288
318
}
319
+ entry .Attrs (func (attr slog.Attr ) bool {
320
+ appendAttr (b , attr .Key , attr .Value )
321
+ return true
322
+ })
323
+ b .Truncate (b .Len () - 1 )
289
324
}
325
+
326
+ if len (h .preformattedAttrs ) > 0 || entry .NumAttrs () > 0 {
327
+ b .WriteByte (' ' )
328
+ }
329
+
290
330
b .WriteString (entry .Message )
291
331
b .WriteByte ('\n' )
292
- return b .Bytes (), nil
332
+ _ , err := h .out .Write (b .Bytes ())
333
+ return err
293
334
}
294
335
295
- func ( f * textFormatter ) needsQuoting (text string ) bool {
336
+ func needsQuoting (text string ) bool {
296
337
for _ , ch := range text {
297
338
if ! ((ch >= 'a' && ch <= 'z' ) ||
298
339
(ch >= 'A' && ch <= 'Z' ) ||
0 commit comments