Skip to content

ewrap/slog — slog adapter subpackage

A 30-line subpackage that lets a stdlib *log/slog.Logger satisfy ewrap.Logger. Stdlib-only — no extra deps.

Install

go get github.com/hyp3rd/ewrap/slog

Usage

import (
    stdslog "log/slog"
    "os"

    "github.com/hyp3rd/ewrap"
    ewrapslog "github.com/hyp3rd/ewrap/slog"
)

handler := stdslog.NewJSONHandler(os.Stdout, &stdslog.HandlerOptions{
    Level: stdslog.LevelDebug,
})
logger := ewrapslog.New(stdslog.New(handler))

err := ewrap.New("boom", ewrap.WithLogger(logger))
err.Log()

API

type Adapter struct{ /* unexported */ }

func New(logger *slog.Logger) *Adapter

func (a *Adapter) Error(msg string, keysAndValues ...any)
func (a *Adapter) Debug(msg string, keysAndValues ...any)
func (a *Adapter) Info(msg string, keysAndValues ...any)

Adapter is a thin shim — each method forwards to the wrapped logger with the same arguments. keysAndValues is the standard alternating key/value convention; *slog.Logger accepts it natively.

When you need this vs when you don't

You need the adapter when you're calling (*Error).Log (or anything else that takes an ewrap.Logger):

err := ewrap.New("boom", ewrap.WithLogger(ewrapslog.New(slogger)))
err.Log() // adapter forwards to slogger.Error(...)

You don't need the adapter when you're logging via slog directly. *Error implements slog.LogValuer, so this works without any adapter:

slogger.Error("payment failed", "err", err)
// emits message, type, severity, request_id, cause, metadata as
// structured fields — see fmt.Formatter & slog

See fmt.Formatter & slog for the LogValuer details.

Why a subpackage?

*log/slog.Logger is in the stdlib, so the adapter has no third-party dependencies. It's still a separate subpackage so importing only ewrap doesn't pull in log/slog for projects that don't use it (rare but possible — embedded targets, for example).