splinter

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 25, 2026 License: MIT Imports: 11 Imported by: 0

README

splinter

Simple and minimal logger in Go for my projects.

Fans out structured records to one or more streams. Ships with a console stream (JSON or pretty text) and a file stream with size- and time-based rotation, optional gzip compression, and backup pruning.

Install

go get git.juancwu.dev/juancwu/splinter

Requires Go 1.26 or newer.

Quick start

The package exposes a default logger that writes JSON to stderr at LevelInfo:

package main

import "git.juancwu.dev/juancwu/splinter"

func main() {
    splinter.Info("server started", "port", 8080)
    splinter.Error("request failed", "err", "timeout")
}

Custom logger with file output and rotation

package main

import (
    "time"

    "git.juancwu.dev/juancwu/splinter"
)

func main() {
    logger := splinter.New(
        splinter.WithStream(splinter.NewConsoleStream(
            splinter.ConsolePretty, splinter.LevelDebug,
        )),
        splinter.WithStream(splinter.MustFileStream("logs/app.log", splinter.FileStreamConfig{
            Level:      splinter.LevelInfo,
            Format:     splinter.FileJSON,
            MaxSizeMB:  100,              // rotate at 100 MB
            MaxAge:     24 * time.Hour,   // and at least once per day
            MaxBackups: 7,                // keep the 7 most recent files
            Compress:   true,             // gzip rotated backups
        })),
        splinter.WithAttrs(map[string]any{"service": "api"}),
    )
    defer logger.Close()

    splinter.SetDefault(logger)

    splinter.Info("ready")
}

Child loggers

Logger.With returns a child that inherits streams and merges additional attributes onto every record:

req := logger.With(map[string]any{"request_id": id})
req.Info("handled", "status", 200)

Custom streams

Implement the Stream interface to send logs anywhere — a database, a message queue, an HTTP endpoint, an in-memory buffer for tests:

type Stream interface {
    Name() string
    Write(ctx context.Context, rec splinter.Record) error
    Enabled(level splinter.Level) bool
    Close() error
}

Add it with splinter.WithStream(myStream) at construction time.

Configuration reference

ConsoleStream
Constructor Behaviour
NewConsoleStream(ConsoleJSON, level) One JSON object per line on stderr.
NewConsoleStream(ConsolePretty, level) key=value text on stderr.
ConsoleWriter(w) option Override the destination writer.
FileStream
Field Default Notes
Level LevelInfo Minimum level written to the file.
Format FileJSON FileJSON or FileText.
MaxSizeMB 100 Rotation threshold in MB. 0 disables size-based rotation.
MaxAge 0 Rotation threshold by age. 0 disables time-based rotation.
MaxBackups 5 Number of rotated files to retain (raw + .gz combined).
Compress false gzip rotated files asynchronously after rename.

When both MaxSizeMB and MaxAge are zero, MaxSizeMB defaults to 100 to prevent unbounded growth.

License

MIT — see LICENSE.

Documentation

Overview

Package splinter is a small, opinionated logger that fans out structured records to one or more streams (console, file, custom). The default package-level logger writes JSON to stderr at LevelInfo; replace it with SetDefault to wire in your own configuration.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Debug

func Debug(msg string, args ...any)

Debug logs at LevelDebug on the default Logger.

func Error

func Error(msg string, args ...any)

Error logs at LevelError on the default Logger.

func Info

func Info(msg string, args ...any)

Info logs at LevelInfo on the default Logger.

func Warn

func Warn(msg string, args ...any)

Warn logs at LevelWarn on the default Logger.

Types

type ConsoleFormat

type ConsoleFormat int

ConsoleFormat selects the output style for ConsoleStream.

const (
	// ConsoleJSON writes structured JSON lines.
	ConsoleJSON ConsoleFormat = iota
	// ConsolePretty writes human-readable text (slog.TextHandler).
	ConsolePretty
)

type ConsoleOption

type ConsoleOption func(*consoleConfig)

ConsoleOption configures a ConsoleStream.

func ConsoleWriter

func ConsoleWriter(w io.Writer) ConsoleOption

ConsoleWriter overrides the output destination (default: os.Stderr).

type ConsoleStream

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

ConsoleStream writes log records to an io.Writer (default os.Stderr) using the standard library's slog handlers.

func NewConsoleStream

func NewConsoleStream(format ConsoleFormat, level Level, opts ...ConsoleOption) *ConsoleStream

NewConsoleStream creates a console stream.

func (*ConsoleStream) Close

func (s *ConsoleStream) Close() error

Close implements Stream. No-op for console output.

func (*ConsoleStream) Enabled

func (s *ConsoleStream) Enabled(level Level) bool

Enabled implements Stream.

func (*ConsoleStream) Name

func (s *ConsoleStream) Name() string

Name implements Stream.

func (*ConsoleStream) Write

func (s *ConsoleStream) Write(ctx context.Context, rec Record) error

Write implements Stream.

type FileFormat

type FileFormat int

FileFormat selects the on-disk encoding for FileStream.

const (
	// FileJSON writes one JSON object per line (slog.JSONHandler).
	FileJSON FileFormat = iota
	// FileText writes a human-readable text line (slog.TextHandler).
	FileText
)

type FileStream

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

FileStream writes log records to a file with size and/or time-based rotation. Safe for concurrent use.

func MustFileStream

func MustFileStream(path string, cfg FileStreamConfig) *FileStream

MustFileStream is like NewFileStream but panics on error. Convenient for application startup where a missing log file is fatal.

func NewFileStream

func NewFileStream(path string, cfg FileStreamConfig) (*FileStream, error)

NewFileStream opens (or creates) the log file and returns a ready stream.

func (*FileStream) Close

func (s *FileStream) Close() error

Close implements Stream. Flushes and closes the underlying file.

func (*FileStream) Enabled

func (s *FileStream) Enabled(level Level) bool

Enabled implements Stream.

func (*FileStream) Name

func (s *FileStream) Name() string

Name implements Stream.

func (*FileStream) Write

func (s *FileStream) Write(ctx context.Context, rec Record) error

Write implements Stream.

type FileStreamConfig

type FileStreamConfig struct {
	// Level is the minimum level to write. Default: LevelInfo.
	Level Level

	// Format is the on-disk encoding. Default: FileJSON.
	Format FileFormat

	// MaxSizeMB is the file-size rotation threshold in megabytes.
	// Zero disables size-based rotation. When both MaxSizeMB and MaxAge are
	// zero, MaxSizeMB defaults to 100 so logs cannot grow unbounded.
	MaxSizeMB int

	// MaxAge is the age-based rotation threshold. Zero disables it.
	// Rotation fires lazily on the first Write after the boundary elapses.
	MaxAge time.Duration

	// MaxBackups is the number of rotated files to retain. Default: 5.
	MaxBackups int

	// Compress gzips rotated files asynchronously after rotation.
	Compress bool
}

FileStreamConfig controls FileStream behaviour.

type Level

type Level = slog.Level

Level mirrors slog.Level so callers don't need to import slog directly.

const (
	LevelDebug Level = slog.LevelDebug
	LevelInfo  Level = slog.LevelInfo
	LevelWarn  Level = slog.LevelWarn
	LevelError Level = slog.LevelError
)

func LevelFromString

func LevelFromString(s string) Level

LevelFromString parses a level name (case-insensitive). Accepted: "debug", "info", "warn"/"warning", "error". Unknown input returns LevelInfo.

type Logger

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

Logger fans out log records to one or more Streams. Streams are fixed at construction time; child loggers from With share the same streams.

func Default

func Default() *Logger

Default returns the package-level Logger.

func New

func New(opts ...Option) *Logger

New creates a Logger. With no streams supplied, a JSON ConsoleStream at LevelInfo writing to stderr is used.

func SetDefault

func SetDefault(l *Logger) *Logger

SetDefault replaces the package-level Logger. The previous Logger is returned so the caller can Close it if they own its streams.

func (*Logger) Close

func (l *Logger) Close() error

Close shuts down all streams. Returns the first error encountered, but always attempts to close every stream.

func (*Logger) Debug

func (l *Logger) Debug(msg string, args ...any)

Debug logs at LevelDebug.

func (*Logger) Error

func (l *Logger) Error(msg string, args ...any)

Error logs at LevelError.

func (*Logger) Info

func (l *Logger) Info(msg string, args ...any)

Info logs at LevelInfo.

func (*Logger) Warn

func (l *Logger) Warn(msg string, args ...any)

Warn logs at LevelWarn.

func (*Logger) With

func (l *Logger) With(attrs map[string]any) *Logger

With returns a child Logger with additional attributes merged onto the base. The child shares streams and the error handler with the parent.

type Option

type Option func(*Logger)

Option configures a Logger.

func WithAttrs

func WithAttrs(attrs map[string]any) Option

WithAttrs pre-populates attributes on every record produced by this logger.

func WithErrorHandler

func WithErrorHandler(fn func(stream string, rec Record, err error)) Option

WithErrorHandler sets a callback invoked when a stream's Write fails. The default handler prints to stderr.

func WithStream

func WithStream(s Stream) Option

WithStream adds a Stream to the logger.

type Record

type Record struct {
	Time    time.Time
	Level   Level
	Message string
	Attrs   map[string]any
}

Record is a self-contained log entry passed to every Stream.

func (Record) LevelLabel

func (r Record) LevelLabel() string

LevelLabel returns a human-friendly label for the record's level.

type Stream

type Stream interface {
	// Name returns a short identifier used in error reporting (e.g. "console").
	Name() string

	// Write handles a single record. Implementations must be safe for
	// concurrent use.
	Write(ctx context.Context, rec Record) error

	// Enabled reports whether the stream cares about the given level.
	Enabled(level Level) bool

	// Close flushes and releases any resources. Called once by Logger.Close.
	Close() error
}

Stream is the abstraction for a log output destination.

Jump to

Keyboard shortcuts

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