tinter

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Feb 26, 2025 License: MIT Imports: 11 Imported by: 1

README

tinter: 🌈 slog.Handler that writes tinted logs

Go Reference Go Report Card

Package tinter implements a zero-dependency slog.Handler that writes tinted (colorized) logs. Its output format is inspired by the zerolog.ConsoleWriter and slog.TextHandler.

The output format can be customized using Options, which is a drop-in replacement for slog.HandlerOptions.

To get started, run:

go get github.com/pwntr/tinter

Output preview:

image

About

tinter is a fork of lmittmann/tint, which introduces the following changes:

  • Uses go-native error values only (anything that implements the error interface), which are passed in as k/v pairs or slog.Attr attributes to colorize any errors that appear in the log, not only errors that had to be previously wrapped explicitly (ref. to the original tint.Err type wrapper).

    The key for the error you pass can be any string you like, as long as the value implements the error interface.

  • Uses faint magenta as the foreground color of the debug level text, to increase readability when glancing over logs, by visually separating it more clearly from the log message itself.

  • Handles all errors in the current code (meaning, doesn't ignore any returned errors), so that the linters (and users) are happy. Also reduced the buffer implementation to methods that are actually used to keep the code lean.

The primary goal of this fork is to have a tinted logger avaiable that doesn't require exposure of the tinter API to deeper levels of your own business logic or logging package API surface - it's a simple drop-in handler that you initialize once with your logger instance and are done. The rest of your app then logs as normal with the default slog API surface.

Note to users migrating from lmittmann/tint

Due to the removal of the tint.Err type wrapper, this fork of tint introduced a breaking change. In case your logging calls actually used that wrapper, please just use the go-native error type for the value (or anything that implements the error interface), in combination with any key you like, or using attributes like slog.Any(...) of type slog.Attr. See Usage for some example logging calls.

The versioning for tinter starts at v1.0.0 with this fork.

Usage

import (
    ...
    "log/slog"
    "github.com/pwntr/tinter"
    ...
)

...

// log target
w := os.Stderr

// logger options
opts := &tinter.Options{
        Level:      slog.LevelDebug,
        TimeFormat: time.Kitchen,
    }

// create a new logger
logger := slog.New(tinter.NewHandler(w, opts))

// set global logger to our new logger (or pass the logger where you need it)
slog.SetDefault(logger)

// example logging calls
slog.Info("Starting server", "addr", ":8080", "env", "production")
slog.Debug("Connected to DB", "db", "myapp", "host", "localhost:5432")
slog.Warn("Slow request", "method", "GET", "path", "/users", "duration", 497*time.Millisecond)
slog.Error("DB connection lost", "err", errors.New("connection reset"), "db", "myapp")
slog.Error("Flux capacitor gone", slog.Any("fail", errors.New("arbitrary error passed")), "engine", 42)

...
Customize Attributes

ReplaceAttr can be used to alter or drop attributes. If set, it is called on each non-group attribute before it is logged. See slog.HandlerOptions for details.

// create a new logger that doesn't write the time
w := os.Stderr
logger := slog.New(
    tinter.NewHandler(w, &tinter.Options{
        ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
            if a.Key == slog.TimeKey && len(groups) == 0 {
                return slog.Attr{}
            }
            return a
        },
    }),
)
Automatically Enable Colors

Colors are enabled by default and can be disabled using the Options.NoColor attribute. To automatically enable colors based on the terminal capabilities, use e.g. the go-isatty package.

w := os.Stderr
logger := slog.New(
    tinter.NewHandler(w, &tinter.Options{
        NoColor: !isatty.IsTerminal(w.Fd()),
    }),
)
Windows Support

Color support on Windows can be added by using e.g. the go-colorable package.

w := os.Stderr
logger := slog.New(
    tinter.NewHandler(colorable.NewColorable(w), nil),
)

Documentation

Overview

Package tinter implements a zero-dependency slog.Handler that writes tinted (colorized) logs. The output format is inspired by the zerolog.ConsoleWriter and slog.TextHandler.

The output format can be customized using Options, which is a drop-in replacement for slog.HandlerOptions.

Customize Attributes

Options.ReplaceAttr can be used to alter or drop attributes. If set, it is called on each non-group attribute before it is logged. See slog.HandlerOptions for details.

w := os.Stderr
logger := slog.New(
	tinter.NewHandler(w, &tinter.Options{
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			if a.Key == slog.TimeKey && len(groups) == 0 {
				return slog.Attr{}
			}
			return a
		},
	}),
)

Automatically Enable Colors

Colors are enabled by default and can be disabled using the Options.NoColor attribute. To automatically enable colors based on the terminal capabilities, use e.g. the go-isatty package.

w := os.Stderr
logger := slog.New(
	tinter.NewHandler(w, &tinter.Options{
		NoColor: !isatty.IsTerminal(w.Fd()),
	}),
)

Windows Support

Color support on Windows can be added by using e.g. the go-colorable package.

w := os.Stderr
logger := slog.New(
	tinter.NewHandler(colorable.NewColorable(w), nil),
)
Example
slog.SetDefault(slog.New(NewHandler(os.Stderr, &Options{
	Level:      slog.LevelDebug - 8,
	TimeFormat: time.Kitchen,
})))

slog.Info("Starting server", "addr", ":8080", "env", "production")
slog.Debug("Connected to DB", "db", "myapp", "host", "localhost:5432")
slog.Log(context.Background(), slog.LevelDebug-2, "lower than debug, but not yet trace level", "weather", "sunny")
slog.Log(context.Background(), slog.LevelDebug-4, "detailed trace message", "fyi", "123")
slog.Log(context.Background(), slog.LevelDebug-8, "super verbose trace message", "atomsCounted", "738795")
slog.Warn("Slow request", "method", "GET", "path", "/users", "duration", 497*time.Millisecond)
slog.Error("DB connection lost", "err", errors.New("connection reset"), "db", "myapp")
slog.Error("Flux capacitor gone", slog.Any("fail", errors.New("arbitrary error passed")), "engine", 42)
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewHandler

func NewHandler(w io.Writer, opts *Options) slog.Handler

NewHandler creates a slog.Handler that writes tinted logs to Writer w, using the default options. If opts is nil, the default options are used.

Types

type Options

type Options struct {
	// Enable source code location (Default: false)
	AddSource bool

	// Minimum level to log (Default: slog.LevelInfo)
	Level slog.Leveler

	// ReplaceAttr is called to rewrite each non-group attribute before it is logged.
	// See https://pkg.go.dev/log/slog#HandlerOptions for details.
	ReplaceAttr func(groups []string, attr slog.Attr) slog.Attr

	// Time format (Default: time.StampMilli)
	TimeFormat string

	// Disable color (Default: false)
	NoColor bool
}

Options for a slog.Handler that writes tinted logs. A zero Options consists entirely of default values.

Options can be used as a drop-in replacement for slog.HandlerOptions.

Jump to

Keyboard shortcuts

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