Skip to content

Commit c929290

Browse files
fix: logger initialization before flags parsing (#7372)
Signed-off-by: knqyf263 <[email protected]> Co-authored-by: knqyf263 <[email protected]>
1 parent feaef96 commit c929290

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

pkg/log/deferred.go

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package log
2+
3+
import (
4+
"context"
5+
"log/slog"
6+
"slices"
7+
)
8+
9+
func init() {
10+
// Set the default logger so that logs are buffered until the logger is initialized.
11+
slog.SetDefault(New(&DeferredHandler{records: new([]deferredRecord)}))
12+
}
13+
14+
// DeferredHandler is needed to save logs and print them after calling `PrintLogs()` command.
15+
// For example, this may be necessary when the logger is not yet initialized, but messages need to be transmitted.
16+
// In this case, the messages are saved and printed when the logger is initialized.
17+
type DeferredHandler struct {
18+
attrs []slog.Attr
19+
20+
// Shared with all instances of the handler.
21+
// NOTE: non-thread safe
22+
records *[]deferredRecord
23+
}
24+
25+
type deferredRecord struct {
26+
ctx context.Context
27+
slog.Record
28+
}
29+
30+
func (*DeferredHandler) Enabled(context.Context, slog.Level) bool {
31+
return true
32+
}
33+
34+
func (d *DeferredHandler) Handle(ctx context.Context, record slog.Record) error {
35+
record.AddAttrs(d.attrs...)
36+
*d.records = append(*d.records, deferredRecord{
37+
ctx: ctx,
38+
Record: record,
39+
})
40+
return nil
41+
}
42+
43+
func (d *DeferredHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
44+
h := *d
45+
h.attrs = slices.Clip(d.attrs)
46+
h.attrs = append(h.attrs, attrs...)
47+
return &h
48+
}
49+
50+
func (*DeferredHandler) WithGroup(_ string) slog.Handler {
51+
panic("WithGroup is not implemented")
52+
}
53+
54+
func (d *DeferredHandler) Flush(h slog.Handler) {
55+
for _, record := range *d.records {
56+
if !h.Enabled(record.ctx, record.Level) {
57+
continue
58+
}
59+
_ = h.Handle(record.ctx, record.Record)
60+
}
61+
d.records = nil
62+
}

pkg/log/logger.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,18 @@ func New(h slog.Handler) *Logger {
3333
return slog.New(h)
3434
}
3535

36-
// InitLogger initialize the logger variable
36+
// InitLogger initializes the logger variable and flushes the buffered logs if needed.
3737
func InitLogger(debug, disable bool) {
3838
level := lo.Ternary(debug, slog.LevelDebug, slog.LevelInfo)
3939
out := lo.Ternary(disable, io.Discard, io.Writer(os.Stderr))
40-
slog.SetDefault(New(NewHandler(out, &Options{Level: level})))
40+
h := NewHandler(out, &Options{Level: level})
41+
42+
// Flush the buffered logs if needed.
43+
if d, ok := slog.Default().Handler().(*DeferredHandler); ok {
44+
d.Flush(h)
45+
}
46+
47+
slog.SetDefault(New(h))
4148
}
4249

4350
var (

0 commit comments

Comments
 (0)