package logging import ( "context" "io" "log/slog" "os" "runtime" ) type Config struct { Level slog.Level `toml:"level"` File string `toml:"file"` } func SetupLogger(cfg Config) *slog.Logger { opts := &slog.HandlerOptions{Level: cfg.Level} var handler slog.Handler var writter io.Writer writter = os.Stdout if cfg.File != "" { f, _ := os.OpenFile(cfg.File, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) writter = f } handler = slog.NewJSONHandler(writter, opts) logger := slog.New(handler) slog.SetDefault(logger) return logger } type contextKeyType struct{} var contextKey contextKeyType func WithLogger(ctx context.Context, logger *slog.Logger) context.Context { return context.WithValue(ctx, contextKey, logger) } func FromContext(ctx context.Context) *slog.Logger { if logger, ok := ctx.Value(contextKey).(*slog.Logger); ok { return logger } return slog.Default() } func RecoverLog(ctx context.Context, err any) { logger := FromContext(ctx) const size = 64 << 10 buf := make([]byte, size) buf = buf[:runtime.Stack(buf, false)] logger.Log(ctx, slog.LevelError, "Program Paniced", "error", err, "stack", string(buf)) }