Skip to content

Arhius/slogx

Repository files navigation

slogx

A thin, opinionated wrapper around Go's log/slog that builds a fully configured *slog.Logger from a small set of functional options and, optionally, LOG_* environment variables.

Features

  • JSON or text encoding — toggle with one option or one env var.
  • Stdout or stderr destination — typed enum, not raw strings at the call-site.
  • Runtime-mutable level — either supply your own *slog.LevelVar or let NewWithLevelVar hand one back to you.
  • Pluggable handlers — drop in a caller-supplied slog.Handler (Loki, Datadog, OpenTelemetry, …) and the option pipeline short-circuits out of your way.
  • Env-driven configuration — standard 12-factor pattern, prefix is configurable.
  • Sentinel errors designed for errors.Is matching.
  • Never fails — invalid env values are silently ignored; the configured default is kept.

Install

go get github.com/Arhius/slogx

Quickstart

package main

import "github.com/Arhius/slogx"

func main() {
    lg := slogx.New() // JSON, info level, stdout, installed as slog.Default
    lg.Info("hello", "k", "v")
}

Configuration

Resolution order: defaults → options → environment. Later inputs overwrite earlier ones.

Options

Option Default Description
WithWriter(io.Writer) os.Stdout Destination for log output.
WithFormat(Format) JSONFormat JSONFormat or TextFormat.
WithLevel(Level) InfoLevel DebugLevel, InfoLevel, WarnLevel, or ErrorLevel.
WithAddSource(bool) false Adds source file:line on every record.
WithSetDefault(bool) true Installs the logger via slog.SetDefault.
WithLoadFromEnv(bool) true Toggles LOG_* env overrides.
WithEnvPrefix(string) "LOG" Prefix used for env lookups.
WithHandler(slog.Handler) Installs a custom handler. Short-circuits format/writer/level/add-source and their env overrides.
WithLevelVar(*slog.LevelVar) Installs a caller-owned *slog.LevelVar. Wins over WithLevel regardless of option order.

Environment variables

All names are built as <PREFIX>_<SUFFIX>. Prefix defaults to LOG.

Variable Accepted values Maps to
LOG_FORMAT json, text WithFormat
LOG_LEVEL debug, info, warn, error WithLevel
LOG_ADD_SOURCE anything strconv.ParseBool accepts WithAddSource
LOG_OUTPUT stdout, stderr underlying writer

Any variable whose value fails to parse is silently ignored; other variables still apply.

Runtime level changes

Two equivalent recipes — pick whichever fits your call-site better.

// (1) You already have a *slog.LevelVar (for instance because an admin endpoint needs to flip it):
lv := &slog.LevelVar{}
lv.Set(slog.LevelInfo)
lg := slogx.New(slogx.WithLevelVar(lv))

lv.Set(slog.LevelDebug) // takes effect on the next record
// (2) You don't want to pre-allocate:
lg, lv := slogx.NewWithLevelVar(slogx.WithLevel(slogx.InfoLevel))

lv.Set(slog.LevelDebug)

NewWithLevelVar always returns a non-nil *slog.LevelVar; if you also passed WithLevelVar(yours), that same pointer is returned unmodified.

Custom handlers

h := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})
lg := slogx.New(slogx.WithHandler(h))

When WithHandler is set, the custom handler owns its own configuration. LOG_FORMAT, LOG_LEVEL, LOG_ADD_SOURCE, and LOG_OUTPUT are all no-ops. WithSetDefault and WithLoadFromEnv still apply.

Errors

Sentinel errors, matched with errors.Is:

  • ErrNilLogger — for downstream code reporting an unexpectedly nil *slog.Logger.
  • ErrInvalidFormat, ErrInvalidLevel, ErrInvalidOutput — returned by ParseFormat / ParseLevel / ParseOutput.
if _, err := slogx.ParseLevel(input); errors.Is(err, slogx.ErrInvalidLevel) {
    // ...
}

Development

go test -race -cover ./...          # tests + coverage (target: 100.0%)
go test -run=NONE -bench=. ./...    # benchmarks
go vet ./...
gofmt -l .

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages