github.com/anycable/anycable-go@v1.5.1/logger/logger.go (about) 1 package logger 2 3 import ( 4 "fmt" 5 "log/slog" 6 "os" 7 8 "github.com/anycable/anycable-go/utils" 9 "github.com/lmittmann/tint" 10 ) 11 12 func InitLogger(format string, level string) (slog.Handler, error) { 13 logLevel, err := parseLevel(level) 14 15 if err != nil { 16 return nil, err 17 } 18 19 var handler slog.Handler 20 21 switch format { 22 case "text": 23 { 24 opts := &tint.Options{ 25 Level: logLevel, 26 NoColor: !utils.IsTTY(), 27 TimeFormat: "2006-01-02 15:04:05.000", 28 ReplaceAttr: transformAttr, 29 } 30 handler = tint.NewHandler(os.Stdout, opts) 31 } 32 case "json": 33 { 34 handler = slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: logLevel}) 35 } 36 default: 37 { 38 return nil, fmt.Errorf("unknown log format: %s.\nAvaialable formats are: text, json", format) 39 } 40 } 41 42 logger := slog.New(handler) 43 slog.SetDefault(logger) 44 45 return handler, nil 46 } 47 48 var LevelNames = map[string]slog.Level{ 49 "debug": slog.LevelDebug, 50 "info": slog.LevelInfo, 51 "warn": slog.LevelWarn, 52 "error": slog.LevelError, 53 } 54 55 func parseLevel(level string) (slog.Level, error) { 56 lvl, ok := LevelNames[level] 57 if !ok { 58 return slog.LevelInfo, fmt.Errorf("unknown log level: %s.\nAvailable levels are: debug, info, warn, error", level) 59 } 60 61 return lvl, nil 62 } 63 64 // Perform some transformations before sending the log record to the handler: 65 // - Transform errors into messages to avoid showing stack traces 66 func transformAttr(groups []string, attr slog.Attr) slog.Attr { 67 if attr.Key == "err" || attr.Key == "error" { 68 if err, ok := attr.Value.Any().(error); ok { 69 return slog.Attr{Key: attr.Key, Value: slog.StringValue(err.Error())} 70 } 71 } 72 73 return attr 74 }