xlog

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 8, 2026 License: MIT Imports: 10 Imported by: 0

README

xlog

Test, Lint Go Reference

xlog is a thin wrapper around the standard library's log/slog package. It trades a little of slog's flexibility for a small, opinionated API that is quick to wire up in applications and easy to stub out in tests.

It was originally developed as part of digineo/texd and extracted into its own module for reuse.

Features

  • A minimal Logger interface with Debug/Info/Warn/Error/Fatal and With methods.
  • Functional options for configuration (New(...Option)).
  • Text or JSON output using the standard library's handlers — the core module has no third-party dependencies.
  • A pluggable handler backend (UseHandler): opt into a richer handler without the core module depending on it. A colorized text backend is shipped as the optional xlog/slogor sub-module.
  • Convenience attribute constructors (String, Int, Error, …) so you don't need to import log/slog alongside xlog.
  • Test helpers: a no-op Discard logger and a MockClock option for deterministic timestamps.

Installation

go get github.com/digineo/xlog

Requires Go 1.26 or later.

Usage

package main

import (
	"log/slog"

	"github.com/digineo/xlog"
)

func main() {
	log, err := xlog.New(
		xlog.AsText(),
		xlog.Leveled(slog.LevelDebug),
	)
	if err != nil {
		panic(err)
	}

	log.Info("service started", xlog.String("addr", ":8080"))

	if err := run(); err != nil {
		log.Error("service failed", xlog.Error(err))
	}
}
Options
Option Effect
WriteTo(w) Write log output to w (default: os.Stdout).
Leveled(l) Set the minimum log level from a slog.Level.
LeveledString(s) Set the level from a string ("debug", "info", …).
AsText() Emit human-readable key=value lines (stdlib text handler).
AsJSON() Emit one JSON object per log record.
WithSource() Include source file and line in each record.
Discard() Mute the logger entirely.
MockClock(t) Use a fixed timestamp — handy in tests.
UseHandler(kind, f) Install a custom slog.Handler backend (see below).

Exactly one handler option (AsText(), AsJSON(), Discard(), or a custom UseHandler) selects the output format; New returns an error if none is given, or if two options request different kinds — e.g. passing both AsText() and AsJSON() is a conflict.

Colorized output (xlog/slogor)

The core module intentionally ships without a colorized handler so it stays dependency-free. Colorized, human-friendly text output lives in the optional xlog/slogor sub-module, backed by slogor:

import (
	"log/slog"

	"github.com/digineo/xlog"
	"github.com/digineo/xlog/slogor"
)

log, err := xlog.New(
	slogor.Colorized(),
	xlog.Leveled(slog.LevelInfo),
)

slogor.Colorized() produces text output, so it implies xlog.AsText() and conflicts with xlog.AsJSON(). Install it with:

go get github.com/digineo/xlog/slogor

Because it is a separate module, projects that don't use it never pull in the slogor or go-isatty dependencies. The same UseHandler extension point lets you wire up any other slog.Handler backend.

Testing

Use NewDiscard() to obtain a logger that swallows everything, or combine MockClock with WriteTo to assert on deterministic output:

var buf bytes.Buffer
log, _ := xlog.New(
	xlog.AsText(),
	xlog.WriteTo(&buf),
	xlog.MockClock(time.Unix(1650000000, 0).UTC()),
)
log.Info("hello", xlog.String("who", "world"))
// buf now holds a line with a fixed timestamp

License

MIT — see LICENSE.

Documentation

Overview

Package xlog provides a thin wrapper around log/slog.

Index

Constants

View Source
const ErrorKey = "error"

Key used to denote error values.

Variables

View Source
var (
	String   = slog.String
	Int64    = slog.Int64
	Int      = slog.Int
	Uint64   = slog.Uint64
	Float64  = slog.Float64
	Bool     = slog.Bool
	Time     = slog.Time
	Group    = slog.Group
	Duration = slog.Duration
	Any      = slog.Any
)

Convenience slog.Attr generators. Allows cluttering imports (no need to import both log/slog and xlog).

View Source
var ErrNilWriter = errors.New("invalid writer: nil")

Functions

func Error

func Error(err error) slog.Attr

Error constructs a first-class error log attribute.

Not to be confused with (xlog.Logger).Error() or (log/slog).Error(), which produce an error-level log message.

func ParseLevel

func ParseLevel(s string) (l slog.Level, err error)

ParseLevel tries to convert a (case-insensitive) string into a slog.Level. Accepted values are "debug", "info", "warn", "warning", "error" and "fatal". Other input will result in err not being nil.

Types

type ErrorValue

type ErrorValue struct {
	// contains filtered or unexported fields
}

ErrorValue holds an error value.

func (ErrorValue) LogValue

func (err ErrorValue) LogValue() slog.Value

LogValue implements slog.LogValuer.

func (ErrorValue) Value

func (err ErrorValue) Value() slog.Value

Value extracts the error message.

type HandlerConfig

type HandlerConfig struct {
	// Output is the writer log records should be written to.
	Output io.Writer
	// Level is the minimum level to log. It is never nil.
	Level slog.Leveler
	// Source reports whether source positions should be included.
	Source bool
}

HandlerConfig carries the resolved base configuration to a HandlerFactory. It gives handler provider packages (such as xlog/slogor) access to the settings shared by all handlers, without exposing xlog's internal option state.

type HandlerFactory

type HandlerFactory func(*HandlerConfig) slog.Handler

A HandlerFactory constructs a slog.Handler from the resolved configuration.

type HandlerKind

type HandlerKind uint8

HandlerKind classifies the output format a handler produces. It is used to detect conflicting handler options: requesting two different kinds (e.g. both text and JSON output) makes New return an error, while options of the same kind override each other (last one wins).

const (
	// HandlerText denotes a human-readable text handler.
	HandlerText HandlerKind = iota + 1
	// HandlerJSON denotes a machine-readable JSON handler.
	HandlerJSON
	// HandlerDiscard denotes a handler that mutes all output.
	HandlerDiscard
)

func (HandlerKind) String

func (k HandlerKind) String() string

String implements fmt.Stringer.

type Logger

type Logger interface {
	// Debug writes log messages with DEBUG severity.
	Debug(msg string, a ...slog.Attr)
	// Info writes log messages with INFO severity.
	Info(msg string, a ...slog.Attr)
	// Warn writes log messages with WARN severity.
	Warn(msg string, a ...slog.Attr)
	// Error writes log messages with ERROR severity.
	Error(msg string, a ...slog.Attr)
	// Fatal writes log messages with ERROR severity, and then
	// exits the whole program.
	Fatal(msg string, a ...slog.Attr)
	// With returns a Logger that includes the given attributes
	// in each output operation.
	With(a ...slog.Attr) Logger
}

A Logger allows writing messages with various severities.

func New

func New(opt ...Option) (Logger, error)

New creates a new logger instance. By default, log messages are written to stdout, and the log level is INFO.

func NewDiscard

func NewDiscard() Logger

NewDiscard produces basically the same logger as

xlog.New(xlog.Discard(), otheroptions...)

but without the option application overhead.

type Option

type Option func(*options) error

An Option represents a functional configuration option. These are used to configure new logger instances.

func AsJSON

func AsJSON() Option

AsJSON configures a JSONHandler, i.e. log messages will be printed as JSON string.

func AsText

func AsText() Option

AsText configures a TextHandler, i.e. the message output is a simple list of key=value pairs with minimal quoting. It uses the handler from the standard library and therefore has no external dependencies.

For colorized, human-friendly text output, use the xlog/slogor sub-module, whose Colorized option is a drop-in replacement.

func Discard

func Discard() Option

Discard mutes the logger. See also NewDiscard() for a simpler constructor.

func Leveled

func Leveled(l slog.Level) Option

Leveled sets the log level.

func LeveledString

func LeveledString(s string) Option

LeveledString interprets s (see ParseLevel) and sets the log level. If s is unknown, the error will be revealed with New().

func MockClock

func MockClock(t time.Time) Option

MockClock sets up a canned timestamp.

func UseHandler

func UseHandler(kind HandlerKind, factory HandlerFactory) Option

UseHandler installs a handler produced by factory. The kind classifies the handler for conflict detection (see HandlerKind).

It is the extension point used by handler provider packages such as xlog/slogor, so that alternative backends can be plugged in without the core module depending on them.

func WithSource

func WithSource() Option

WithSource enables source code positions in log messages.

func WriteTo

func WriteTo(w io.Writer) Option

WriteTo sets the output.

Directories

Path Synopsis
slogor module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL