github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/conf/logger/slog_handler.go (about)

     1  package logger
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log/slog"
     7  	"os"
     8  	"path/filepath"
     9  	"runtime"
    10  )
    11  
    12  func NewJsonHandler(skip int) *customJsonHandler {
    13  	return &customJsonHandler{
    14  		skip: skip,
    15  		JSONHandler: slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
    16  			AddSource:   skip > 0,
    17  			Level:       gLevel,
    18  			ReplaceAttr: CustomReplacer,
    19  		}),
    20  	}
    21  }
    22  
    23  type customJsonHandler struct {
    24  	skip int
    25  	*slog.JSONHandler
    26  }
    27  
    28  func (h *customJsonHandler) Handle(ctx context.Context, r slog.Record) error {
    29  	var pcs [1]uintptr
    30  	runtime.Callers(h.skip, pcs[:])
    31  	r.PC = pcs[0]
    32  	return h.JSONHandler.Handle(ctx, r)
    33  }
    34  
    35  func (h *customJsonHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
    36  	return &customJsonHandler{
    37  		skip:        h.skip,
    38  		JSONHandler: h.JSONHandler.WithAttrs(attrs).(*slog.JSONHandler),
    39  	}
    40  }
    41  
    42  func (h *customJsonHandler) WithGroup(group string) slog.Handler {
    43  	return &customJsonHandler{
    44  		skip:        h.skip,
    45  		JSONHandler: h.JSONHandler.WithGroup(group).(*slog.JSONHandler),
    46  	}
    47  }
    48  
    49  func (h *customJsonHandler) Enabled(_ context.Context, lv slog.Level) bool {
    50  	return lv >= gLevel
    51  }
    52  
    53  func NewTextHandler(skip int) *customTextHandler {
    54  	return &customTextHandler{
    55  		skip: skip,
    56  		TextHandler: slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
    57  			AddSource:   skip > 0,
    58  			Level:       gLevel,
    59  			ReplaceAttr: CustomReplacer,
    60  		}),
    61  	}
    62  }
    63  
    64  type customTextHandler struct {
    65  	skip int
    66  	*slog.TextHandler
    67  }
    68  
    69  func (h *customTextHandler) Handle(ctx context.Context, r slog.Record) error {
    70  	var pcs [1]uintptr
    71  	runtime.Callers(h.skip, pcs[:])
    72  	r.PC = pcs[0]
    73  	return h.TextHandler.Handle(ctx, r)
    74  }
    75  
    76  func (h *customTextHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
    77  	return &customTextHandler{
    78  		skip:        h.skip,
    79  		TextHandler: h.TextHandler.WithAttrs(attrs).(*slog.TextHandler),
    80  	}
    81  }
    82  
    83  func (h *customTextHandler) WithGroup(group string) slog.Handler {
    84  	return &customTextHandler{
    85  		skip:        h.skip,
    86  		TextHandler: h.TextHandler.WithGroup(group).(*slog.TextHandler),
    87  	}
    88  }
    89  
    90  func (h *customTextHandler) Enabled(_ context.Context, lv slog.Level) bool {
    91  	return lv >= gLevel
    92  }
    93  
    94  func CustomReplacer(groups []string, a slog.Attr) slog.Attr {
    95  	// time format
    96  	v := a.Value
    97  	if a.Value.Kind() == slog.KindTime {
    98  		a.Value = slog.StringValue(v.Time().Format("20060102-150405.000Z0700"))
    99  	}
   100  
   101  	// replace time key format
   102  	if a.Key == slog.TimeKey {
   103  		a.Key = "@ts"
   104  		return a
   105  	}
   106  
   107  	// replace level key
   108  	if a.Key == slog.LevelKey {
   109  		val := ""
   110  		switch v := a.Value.Any().(slog.Level); v {
   111  		case slog.LevelDebug:
   112  			val = "deb"
   113  		case slog.LevelInfo:
   114  			val = "inf"
   115  		case slog.LevelWarn:
   116  			val = "wrn"
   117  		default:
   118  			val = "err"
   119  		}
   120  		return slog.String("@lv", val)
   121  	}
   122  
   123  	// replace stack info
   124  	if a.Key == slog.SourceKey {
   125  		s := a.Value.Any().(*slog.Source)
   126  		s.File = filepath.Base(s.File)
   127  		return slog.String("@src", fmt.Sprintf("%s:%d", s.File, s.Line))
   128  	}
   129  
   130  	return a
   131  }