11package logutils
22
33import (
4- "fmt"
4+ "context"
5+ "log/slog"
56 "strings"
67
78 "go.uber.org/zap"
@@ -10,42 +11,78 @@ import (
1011 "github.com/ethereum/go-ethereum/log"
1112)
1213
13- // gethAdapter returns a log.Handler interface that forwards logs to a zap.Logger.
14- // Logs are forwarded raw as if geth were printing them.
15- func gethAdapter (logger * zap.Logger ) log.Handler {
16- return log .FuncHandler (func (r * log.Record ) error {
17- level , err := LvlFromString (r .Lvl .String ())
18- if err != nil {
19- return err
20- }
21- // Skip trace logs to not clutter the output
22- if level == traceLevel {
23- return nil
24- }
25- serializedLog := string (log .TerminalFormat (false ).Format (r ))
26- logger .Check (level , fmt .Sprintf ("'%s'" , strings .TrimSuffix (serializedLog , "\n " ))).Write ()
27- return nil
28- })
14+ type gethAdapter struct {
15+ log.Logger
16+ target * zap.Logger
17+ }
18+
19+ func newGethAdapter (target * zap.Logger ) * gethAdapter {
20+ return & gethAdapter {
21+ Logger : log .NewLogger (log .DiscardHandler ()),
22+ target : target ,
23+ }
24+ }
25+
26+ func (g * gethAdapter ) serializeLog (level slog.Level , msg string , ctx ... interface {}) string {
27+ buf := strings.Builder {}
28+ logger := log .NewLogger (log .LogfmtHandlerWithLevel (& buf , level ))
29+ logger .Log (level , msg , ctx ... )
30+ return buf .String ()
31+ }
32+
33+ func (g * gethAdapter ) Log (level slog.Level , msg string , ctx ... interface {}) {
34+ g .Write (level , msg , ctx ... )
35+ }
36+
37+ func (g * gethAdapter ) Trace (msg string , ctx ... interface {}) {
38+ g .Write (log .LevelTrace , msg , ctx ... )
39+ }
40+
41+ func (g * gethAdapter ) Debug (msg string , ctx ... interface {}) {
42+ g .Write (log .LevelDebug , msg , ctx ... )
43+ }
44+
45+ func (g * gethAdapter ) Info (msg string , ctx ... interface {}) {
46+ g .Write (log .LevelInfo , msg , ctx ... )
47+ }
48+
49+ func (g * gethAdapter ) Warn (msg string , ctx ... interface {}) {
50+ g .Write (log .LevelWarn , msg , ctx ... )
51+ }
52+
53+ func (g * gethAdapter ) Error (msg string , ctx ... interface {}) {
54+ g .Write (log .LevelError , msg , ctx ... )
55+ }
56+
57+ func (g * gethAdapter ) Crit (msg string , ctx ... interface {}) {
58+ g .Write (log .LevelCrit , msg , ctx ... )
59+ }
60+
61+ func (g * gethAdapter ) Write (level slog.Level , msg string , attrs ... any ) {
62+ g .target .Check (zapLevelFromGeth (level ), g .serializeLog (level , msg , attrs ... )).Write ()
63+ }
64+
65+ func (g * gethAdapter ) Enabled (ctx context.Context , level slog.Level ) bool {
66+ return g .target .Core ().Enabled (zapLevelFromGeth (level )) && g .Logger .Enabled (ctx , level )
2967}
3068
3169const traceLevel = zapcore .DebugLevel - 1
3270
33- // LvlFromString returns the appropriate zapcore.Level from a string.
34- func LvlFromString (lvlString string ) (zapcore.Level , error ) {
35- switch strings .ToLower (lvlString ) {
36- case "trace" , "trce" :
37- return traceLevel , nil // zap does not have a trace level, use custom
38- case "debug" , "dbug" :
39- return zapcore .DebugLevel , nil
40- case "info" :
41- return zapcore .InfoLevel , nil
42- case "warn" :
43- return zapcore .WarnLevel , nil
44- case "error" , "eror" :
45- return zapcore .ErrorLevel , nil
46- case "crit" :
47- return zapcore .DPanicLevel , nil // zap does not have a crit level, using DPanicLevel as closest
71+ func zapLevelFromGeth (lvl slog.Level ) zapcore.Level {
72+ switch lvl {
73+ case log .LevelTrace :
74+ return traceLevel // zap does not have a trace level, use custom
75+ case log .LevelDebug :
76+ return zapcore .DebugLevel
77+ case log .LevelInfo :
78+ return zapcore .InfoLevel
79+ case log .LevelWarn :
80+ return zapcore .WarnLevel
81+ case log .LevelError :
82+ return zapcore .ErrorLevel
83+ case log .LevelCrit :
84+ return zapcore .DPanicLevel // zap does not have a crit level, using DPanicLevel as closest
4885 default :
49- return zapcore .InvalidLevel , fmt . Errorf ( "unknown level: %v" , lvlString )
86+ return zapcore .InvalidLevel
5087 }
5188}
0 commit comments