powerline

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2023 License: EUPL-1.2 Imports: 9 Imported by: 1

README

powerline: a slog.Handler that writes powerline output

Package powerline implements a zero-dependency slog.Handler that writes logs with powerline symbols. The output format is inspired by slog.TextHandler and the magnificent tint.

The icons and colors used can be customized by setting custom mappings using HandlerOptions, which is an extension of the slog.HandlerOptions.

Usage

Basic usage:

package main

import (
	"errors"
	"log/slog"
	"os"
	"time"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	slog.SetDefault(slog.New(powerline.NewHandler(os.Stderr, &powerline.HandlerOptions{
		Level: slog.LevelDebug,
	})))

	slog.Debug("Starting to log things", "var", 1234)
	slog.Info("Logging a thing", "start", time.Now())
	slog.Warn("Something might break", "thing", "bork")
	slog.Error("Something broke", "err", errors.New("an error"))
}

example output

And it can all be customized:

package main

import (
	"errors"
	"log/slog"
	"os"
	"time"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	slog.SetDefault(slog.New(powerline.NewHandler(os.Stderr, &powerline.HandlerOptions{
		Level:      slog.LevelDebug,
		TimeFormat: time.DateTime,
		Icons:      powerline.VerboseIcons,
		Colors:     powerline.NoColors,
	})))

	slog.Debug("Starting to log things", "var", 1234)
	slog.Info("Logging a thing", "start", time.Now())
	slog.Warn("Something might break", "thing", "bork")
	slog.Error("Something broke", "err", errors.New("an error"))
}

example output

Documentation

Overview

Package powerline implements a zero-dependency slog.Handler that writes logs with powerline symbols.

Index

Examples

Constants

View Source
const (
	ColorDefault      = -1
	ColorBlack        = 0
	ColorRed          = 1
	ColorGreen        = 2
	ColorYellow       = 3
	ColorBlue         = 4
	ColorMagenta      = 5
	ColorCyan         = 6
	ColorLightGray    = 7
	ColorDarkGray     = 8
	ColorLightRed     = 9
	ColorLightGreen   = 10
	ColorLightYellow  = 11
	ColorLightBlue    = 12
	ColorLightMagenta = 13
	ColorLightCyan    = 14
	ColorWhite        = 15
)

Basic ANSI color definitions for 256-color terminals.

View Source
const (

	// DefaultAttrColor contains the default attribute foreground color (medium gray).
	DefaultAttrColor = 244
)

Variables

DefaultColors contains the default ANSI colors used for formatting messages.

View Source
var DefaultIcons = map[slog.Level]string{
	slog.LevelDebug: "✚",
	slog.LevelInfo:  "✓",
	slog.LevelWarn:  "🗲",
	slog.LevelError: "✗",
}

DefaultIcons contains the default prefix mapping.

NoColors is a colors scheme with colors disabled.

View Source
var VerboseIcons = map[slog.Level]string{
	slog.LevelDebug: slog.LevelDebug.String(),
	slog.LevelInfo:  slog.LevelInfo.String(),
	slog.LevelWarn:  slog.LevelWarn.String(),
	slog.LevelError: slog.LevelError.String(),
}

VerboseIcons contains an alternative set of levels with the default log level strings instead of icons.

Functions

This section is empty.

Types

type Color

type Color [2]int

Color contains an 8-bit ANSI color code pair (foreground and background). See https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit

func NewColor

func NewColor(fg, bg int) Color

NewColor initializes a new terminal color.

func (Color) String

func (c Color) String() string

type ColorScheme

type ColorScheme struct {
	Time    Color
	Level   Color
	Message Color
	Attrs   Color
}

ColorScheme contains a color scheme for a log message. All colors are optional: the zero value will show all values in the default foreground/background color.

type Handler

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

Handler implements a slog.Handler with bright colors.

func NewHandler

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

NewHandler returns an initialized Handler.

Example

Basic usage of powerline is simple. This looks better in a terminal than in the Go Playground.

package main

import (
	"log/slog"
	"os"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	slog.SetDefault(slog.New(powerline.NewHandler(os.Stdout, nil)))

	slog.Info("Hello world", "extra", 1234)

}
Output:

�[0m�[38;5;0;48;5;10m ✓ �[38;5;10;49m �[38;5;10;49mHello world�[38;5;244;49m extra=1234
�[0m
Example (CustomIcons)

It is possible to override the icons. Only the error level and higher are overridden, other (lower) levels default to the string value of the slog.Level.

package main

import (
	"log/slog"
	"os"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	log := slog.New(powerline.NewHandler(os.Stdout, &powerline.HandlerOptions{
		Level:  slog.LevelInfo,
		Colors: powerline.NoColors,
		Icons: map[slog.Level]string{
			slog.LevelWarn: "a warning",
		},
	}))

	log.Error("Hello world")

}
Output:

a warning  Hello world
Example (CustomLevel1)

It is also possible to set the log level to a custom value by replacing it.

package main

import (
	"log/slog"
	"os"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	log := slog.New(powerline.NewHandler(os.Stdout, &powerline.HandlerOptions{
		Level:  slog.LevelInfo,
		Colors: powerline.NoColors,
		Icons:  powerline.VerboseIcons,
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			if a.Key == slog.LevelKey {
				return slog.String(slog.LevelKey, "CUSTOM")
			}

			return a
		},
	}))

	log.Info("Hello world")

}
Output:

CUSTOM  Hello world
Example (CustomLevel2)

This also works for a log level, which is then interpreted with the default icons.

package main

import (
	"log/slog"
	"os"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	log := slog.New(powerline.NewHandler(os.Stdout, &powerline.HandlerOptions{
		Level:  slog.LevelInfo,
		Colors: powerline.NoColors,
		Icons:  powerline.DefaultIcons,
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			// Replace the log level with the warning level.
			if a.Key == slog.LevelKey {
				return slog.Int(slog.LevelKey, int(slog.LevelWarn))
			}

			return a
		},
	}))

	log.Error("This was error")

}
Output:

🗲  This was error
Example (CustomTime)

It is possible to show the time by setting a time format. Additionally, replacing the time attribute will show any time of your choice.

package main

import (
	"log/slog"
	"os"
	"time"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	log := slog.New(powerline.NewHandler(os.Stdout, &powerline.HandlerOptions{
		Level:      slog.LevelInfo,
		Colors:     powerline.NoColors,
		Icons:      powerline.VerboseIcons,
		TimeFormat: time.DateTime,
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			if a.Key == slog.TimeKey {
				return slog.Time(slog.TimeKey, time.Date(1970, 1, 1, 0, 0, 0, 0, time.Local))
			}

			return a
		},
	}))

	log.Info("Hello world", "extra", 1234)

}
Output:

1970-01-01 00:00:00  INFO  Hello world extra=1234
Example (CustomTimeString)

It is possible to override the time as any other value, which will always be shown.

package main

import (
	"log/slog"
	"os"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	log := slog.New(powerline.NewHandler(os.Stdout, &powerline.HandlerOptions{
		Level:  slog.LevelInfo,
		Colors: powerline.NoColors,
		Icons:  powerline.VerboseIcons,
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			if a.Key == slog.TimeKey {
				return slog.String(slog.TimeKey, "now")
			}

			return a
		},
	}))

	log.Info("Hello world", "extra", 1234)

}
Output:

now  INFO  Hello world extra=1234
Example (UndefinedLevel1)

Custom levels are logged as the closest (lower) level.

package main

import (
	"context"
	"log/slog"
	"os"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	log := slog.New(powerline.NewHandler(os.Stdout, &powerline.HandlerOptions{
		Level:  slog.LevelInfo,
		Colors: powerline.NoColors,
	}))

	log.Log(context.Background(), slog.LevelWarn+1, "This is a custom level")

}
Output:

🗲  This is a custom level
Example (UndefinedLevel2)

If a level is completely undefined, the result of slog.Level.String is shown.

package main

import (
	"context"
	"log/slog"
	"os"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	log := slog.New(powerline.NewHandler(os.Stdout, &powerline.HandlerOptions{
		Level:  slog.LevelInfo,
		Colors: powerline.NoColors,
		Icons:  map[slog.Level]string{},
	}))

	// Custom levels are logged as the closest (lower) level,
	// simple string conversion is used when no icon is defined.
	log.Log(context.Background(), slog.LevelError+1, "This is a custom level")

}
Output:

ERROR+1  This is a custom level

func (*Handler) Enabled

func (h *Handler) Enabled(_ context.Context, level slog.Level) bool

Enabled returns true if records of the given log level are handled.

func (*Handler) Handle

func (h *Handler) Handle(ctx context.Context, record slog.Record) (err error)

Handle handles the given slog.Record.

func (*Handler) WithAttrs

func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs returns a new Handler whose attributes are extended with the given attributes.

Example
package main

import (
	"log/slog"
	"os"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	log := slog.New(powerline.NewHandler(os.Stdout, &powerline.HandlerOptions{
		Level:  slog.LevelInfo,
		Colors: powerline.NoColors,
	}))

	// Trust me, the powerline. look better in a terminal.
	log.With("extra", 12345).Info("Hello world")

}
Output:

✓  Hello world extra=12345

func (*Handler) WithGroup

func (h *Handler) WithGroup(name string) slog.Handler

WithGroup returns a new Handler whose groups are extended with the given group name.

Example
package main

import (
	"log/slog"
	"os"

	"gitlab.com/slxh/go/powerline"
)

func main() {
	log := slog.New(powerline.NewHandler(os.Stdout, &powerline.HandlerOptions{
		Level:  slog.LevelInfo,
		Colors: powerline.NoColors,
	}))

	// Trust me, the powerline. look better in a terminal.
	log.WithGroup("group").Info("Hello world", "extra", 123)

}
Output:

✓  Hello world group.extra=123

type HandlerOptions

type HandlerOptions struct {
	// AddSource enables or disables source code location.
	AddSource bool

	// Level configures the minimum log level.
	Level slog.Leveler

	// ReplaceAttr is called to rewrite attributes before being logged.
	// See https://pkg.go.dev/log/slog#HandlerOptions for details.
	ReplaceAttr func(groups []string, a slog.Attr) slog.Attr

	// TimeFormat contains the time format used for formatting time.
	// No time is logged when left empty (the default).
	TimeFormat string

	// Colors contains a mapping log levels to ANSI color codes.
	// It defaults to [DefaultColors].
	Colors map[slog.Level]ColorScheme

	// Icons contains a mapping of colors to log levels.
	// It defaults to [DefaultIcons].
	Icons map[slog.Level]string
}

HandlerOptions is an extended version of slog.HandlerOptions.

The options can be modified to use different icons and colors. For example:

 &powerline.HandlerOptions{
		Level:      slog.LevelDebug,
		TimeFormat: time.DateTime,
		Icons:      powerline.VerboseIcons,
		Colors:     powerline.NoColors,
	}

Will result in output like:

2023-09-01 18:37:56  DEBUG  Starting to log things var=1234
2023-09-01 18:37:56  INFO  Logging a thing start=2023-09-01T18:37:56.908+02:00
2023-09-01 18:37:56  WARN  Something might break thing=bork
2023-09-01 18:37:56  ERROR  Something broke err="an error"

Directories

Path Synopsis
internal
buffer
Package buffer provides a pool-allocated byte buffer.
Package buffer provides a pool-allocated byte buffer.

Jump to

Keyboard shortcuts

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