slog

package module
v0.5.7 Latest Latest
Warning

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

Go to latest
Published: Jan 16, 2024 License: MIT Imports: 3 Imported by: 39

README

slog, a back-end agnostic interface for structured logs

Go Reference Codebeat Badge

slog.Logger provides a simple standardised interface for structured logs for libraries. It supports six log levels and fields with unique string labels (keys).

Interface

Every method of this interface, with the exception of Print(), returns a slog.Logger so it can be daisy chained when composing a log entry. A log entry begins with setting the level followed by optional addition of fields and a call stack and ends with a message calling a Print method. Based on the specified level an entry can be enabled or disabled. Calls to methods on disabled entries will cause no action unless it's used to create a new entry with a level that is enabled.

Log Levels

An slog.Logger entry can have of one of six levels, of which Fatal is expected to end the execution just like the standard log.Fatal()right after adding the log entry, and Panic to raise a recoverable panic like log.Panic().

  1. Debug
  2. Info
  3. Warn
  4. Error
  5. Fatal
  6. Panic

New log entries can be created by calling the named shortcut methods (Debug(), Info(), Warn(), Error(), Fatal(), and Panic()) or via WithLevel(level).

Enabled

A log entry is considered Enabled if the handler would actually log entries of the specified level. It is always safe to operate on disabled loggers and the cost of should be negletable as when a logger is not Enabled() string formatting operations or fields and stack commands are not performed.

Sometimes it is useful to know if a certain level is Enabled so you can decide between two levels with different degree of detail. For this purpose one can use WithEnabled() like this:

if log, ok := logger.Debug().WithEnabled(); ok {
	log.WithField("request", req).Print("Let's write detailed debug stuff")
} else if log, ok := logger.Info().WithEnabled(); ok {
	log.Print("Let's write info stuff instead")
}

Logs of Fatal and Panic level are expected to exit/panic regardless of the Enabled state.

Fields

In slog fields are unique key/value pairs where the key is a non-empty string and the value could be any type.

Call Stack

A Call stack is attached to a log entry considering the given distance to a caller/initiator function.

Print

slog.Logger support three Print methods mimicking their equivalent in the fmt package from the standard library. Print(), Println(), and Printf() that finally attempt to emit the log entry with the given message and any previously attached Field.

Standard *log.Logger

In order to be compatible with the standard library's provided log.Logger, slog provides an io.Writer interface connected to a handler function that is expected to parse the entry and call a provided slog.Logger as appropriate. This writer is created by calling NewLogWriter and passing the logger and the handler function, which is then passed to log.New() to create the *log.Logger.

Alternatively a generic handler is provided when using NewStdLogger().

Handlers

A handler is an object that implements the slog.Logger interface. We provide handlers to use popular loggers as backend.

We also offer backend independent handlers

  • cblog, a implementation that allows you to receive log entries through a channel.
  • filter, that can filter by level and also alter log entries before passing them to another slog.Logger.
  • discard, a placeholder that won't log anything but saves the user from checking if a logger was provided or not every time.

Documentation

Overview

Package slog provides a backend agnostic interface for structured logs

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewStdLogger

func NewStdLogger(l Logger, prefix string, flags int) *log.Logger

NewStdLogger creates a standard *log.Logger using a slog.Logger behind the scenes

Types

type Fields

type Fields map[string]any

Fields is sugar syntax for WithFields() for those who believe log.WithFields(slog.Fields{foo: bar}) is nicer than log.WithFields(map[string]any{foo: var})

type LogLevel

type LogLevel int8

LogLevel represents the level of criticality of a log entry

const (
	// UndefinedLevel is a placeholder for the zero-value when no level has been set
	UndefinedLevel LogLevel = iota

	// Panic represents a log entry for a fatal problem that could be stoped by defer/recover
	Panic
	// Fatal represents a log entry for a problem we can't recover
	Fatal
	// Error represents a log entry for a problem we can recover
	Error
	// Warn represents a log entry for something that might not a problem but it's worth mentioning
	Warn
	// Info represents a log entry just to tell what we are doing
	Info
	// Debug represents a log entry that contains information important mostly only to developers
	Debug

	// ErrorFieldName is the preferred field label for errors
	ErrorFieldName = "error"
)

type LogWriter

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

LogWriter is a io.Writer that calls a given function to log each Write() call

func NewLogWriter

func NewLogWriter(l Logger, fn LogWriterFunc) *LogWriter

NewLogWriter creates a new LogWriter with the given slog.Logger and handler function

func (*LogWriter) Write

func (w *LogWriter) Write(p []byte) (n int, err error)

type LogWriterFunc

type LogWriterFunc func(Logger, string) error

LogWriterFunc is the prototype of the functions used to process and log Write() calls

type Logger

type Logger interface {
	Debug() Logger // Debug is an alias of WithLevel(Debug)
	Info() Logger  // Info is an alias of WithLevel(Info)
	Warn() Logger  // Warn is an alias of WithLevel(Warn)
	Error() Logger // Error is an alias of WithLevel(Error)
	Fatal() Logger // Fatal is an alias of WithLevel(Fatal)
	Panic() Logger // Panic is an alias of WithLevel(Panic)

	// Print adds a log entry handled in the manner of fmt.Print
	Print(...any)
	// Println adds a log entry handled in the manner of fmt.Println
	Println(...any)
	// Printf adds a log entry handled in the manner of fmt.Printf
	Printf(string, ...any)

	// WithLevel returns a new log context set to add entries to the specified level
	WithLevel(LogLevel) Logger

	// WithStack attaches a call stack a log context
	WithStack(int) Logger
	// WithField attaches a field to a log context
	WithField(string, any) Logger
	// WithFields attaches a set of fields to a log context
	WithFields(map[string]any) Logger

	// Enabled tells if the Logger would actually log
	Enabled() bool

	// WithEnabled tells if Enabled but also passes a reference to
	// the logger for convenience when choosing what to log
	//
	// e.g.
	// if log, ok := logger.Debug().WithEnabled(); ok {
	//    log.Print("Let's write detailed debug stuff")
	// } elseif log, ok := logger.Info().WithEnabled(); ok {
	//    log.Print("Let's write info stuff instead")
	// }
	WithEnabled() (Logger, bool)
}

Logger is a backend agnostic interface for structured logs

Directories

Path Synopsis
handlers
cblog Module
discard Module
filter Module
logrus Module
zap Module
zerolog Module
Package internal provides helpers for concrete slog implementations
Package internal provides helpers for concrete slog implementations

Jump to

Keyboard shortcuts

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