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  }