log

package
v0.0.0-...-fa54556 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2025 License: Apache-2.0 Imports: 14 Imported by: 4

Documentation

Overview

Package log provides fast, structured logging based on Go's slog package.

This package wraps Go's standard slog library with additional convenience functions and configuration options specifically designed for retro console emulation and tooling development.

Features

  • Structured logging with key-value pairs
  • Multiple output formats (text, JSON)
  • Configurable log levels
  • High performance with minimal allocations
  • Console-friendly formatting
  • Testing utilities for log verification

Basic Usage

import "github.com/retroenv/retrogolib/log"

func main() {
	logger := log.New(log.Config{
		Level:  log.LevelInfo,
		Format: log.FormatText,
	})

	logger.Info("Starting emulation",
		log.String("system", "NES"),
		log.Int("rom_size", 32768),
	)

	logger.Error("Failed to load ROM",
		log.String("filename", "game.nes"),
		log.String("error", err.Error()),
	)
}

Log Levels

  • Debug: Detailed diagnostic information
  • Info: General operational messages
  • Warn: Warning conditions that don't halt operation
  • Error: Error conditions that may affect functionality

Output Formats

  • Text: Human-readable console output
  • JSON: Structured JSON for log aggregation systems

Performance

The logging system is designed for high performance:

  • Zero allocation for disabled log levels
  • Efficient field handling
  • Minimal overhead in hot paths like CPU emulation loops

Testing Support

The package includes utilities for testing log output:

  • Capture log messages in tests
  • Verify specific log entries were written
  • Mock logging for isolated unit tests

Thread Safety

All logging operations are thread-safe and can be used concurrently from multiple goroutines without external synchronization.

Package log provides logging functionality.

Index

Constants

View Source
const (
	// TraceLevel logs are typically voluminous, and are usually disabled in
	// production.
	TraceLevel = slog.LevelDebug << 1

	// DebugLevel logs are typically voluminous, and are usually disabled in
	// production.
	DebugLevel = slog.LevelDebug

	// InfoLevel is the default logging priority.
	InfoLevel = slog.LevelInfo

	// WarnLevel logs are more important than Info, but don't need individual
	// human review.
	WarnLevel = slog.LevelWarn

	// ErrorLevel logs are high-priority. If an application is running smoothly,
	// it shouldn't generate any error-level logs.
	ErrorLevel = slog.LevelError

	// FatalLevel logs a message, then calls os.Exit(1).
	FatalLevel = slog.LevelError << 1
)

Log levels.

View Source
const DefaultTimeFormat = "2006-01-02 15:04:05"

DefaultTimeFormat is a slimmer default time format used if no other time format is specified.

Variables

This section is empty.

Functions

func ReplaceLevelName

func ReplaceLevelName(_ []string, a slog.Attr) slog.Attr

ReplaceLevelName sets custom defined level names for outputting.

func SetDefaultLevel

func SetDefaultLevel(level Level)

SetDefaultLevel sets the default level for all newly created loggers.

Types

type Config

type Config struct {
	// CallerInfo adds a ("source", "file:line") attribute to the output
	// indicating the source code position of the log statement.
	CallerInfo bool

	Level Level

	Output io.Writer

	// Handler handles log records produced by a Logger..
	Handler slog.Handler

	// TimeFormat defines the time format to use, defaults to "2006-01-02 15:04:05"
	// Outputting of time can be disabled with - for the console handler.
	TimeFormat string
}

Config represents configuration for a logger.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the default config. The returned config can be adjusted and used to create a logger with custom config using the NewWithConfig() function.

type ConsoleHandler

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

ConsoleHandler formats the logger output in a better human-readable way.

func NewConsoleHandler

func NewConsoleHandler(w io.Writer, opts *ConsoleHandlerOptions) *ConsoleHandler

NewConsoleHandler returns a new console handler.

func (*ConsoleHandler) Enabled

func (h *ConsoleHandler) Enabled(ctx context.Context, level slog.Level) bool

Enabled reports whether the handler handles records at the given level. The handler ignores records whose level is lower.

func (*ConsoleHandler) Handle

func (h *ConsoleHandler) Handle(ctx context.Context, r slog.Record) error

Handle handles the Record.

func (*ConsoleHandler) WithAttrs

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

WithAttrs returns a new Handler whose attributes consist of both the receiver's attributes and the arguments. nolint: ireturn

func (*ConsoleHandler) WithGroup

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

WithGroup returns a new Handler with the given group appended to the receiver's existing groups. nolint: ireturn

type ConsoleHandlerOptions

type ConsoleHandlerOptions struct {
	SlogOptions *slog.HandlerOptions

	TimeFormat string
}

ConsoleHandlerOptions are options for a ConsoleHandler. A zero HandlerOptions consists entirely of default values.

type Field

type Field = slog.Attr

A Field is a marshaling operation used to add a key-value pair to a logger's context. Most fields are lazily marshaled, so it's inexpensive to add fields to disabled debug-level log statements.

func Bool

func Bool(key string, val bool) Field

Bool constructs a Field with the given key and value.

func Duration

func Duration(key string, val time.Duration) Field

Duration constructs a Field with the given key and value.

func Err

func Err(err error) Field

Err constructs a Field with the given key and value.

func Float32

func Float32(key string, val float32) Field

Float32 constructs a Field with the given key and value.

func Float64

func Float64(key string, val float64) Field

Float64 constructs a Field with the given key and value.

func Hex

func Hex(key string, val any) Field

Hex constructs a Field with the given key and formats integer values in hex format. The hex formatting is evaluated lazily - only when the log level is enabled and the handler processes the record. This provides significant performance benefits for expensive hex formatting when logging is disabled.

Supports signed and unsigned integers of various bit widths with appropriate zero-padding.

Examples:

log.Hex("addr", uint16(0x1234))  // "addr": "0x1234"
log.Hex("byte", uint8(0xFF))     // "byte": "0xFF"
log.Hex("opcode", 0x4C)          // "opcode": "0x4C"

func Int

func Int(key string, val int) Field

Int constructs a Field with the given key and value.

func Int16

func Int16(key string, val int16) Field

Int16 constructs a Field with the given key and value.

func Int32

func Int32(key string, val int32) Field

Int32 constructs a Field with the given key and value.

func Int64

func Int64(key string, val int64) Field

Int64 constructs a Field with the given key and value.

func Int8

func Int8(key string, val int8) Field

Int8 constructs a Field with the given key and value.

func IntFunc

func IntFunc(key string, f func() int) Field

IntFunc constructs a Field with the given key and a function that returns an int. The function is evaluated lazily - only when the log level is enabled and the handler processes the record. This provides significant performance benefits for expensive int computations when logging is disabled.

func Object

func Object(key string, val any) Field

Object constructs a Field with the given key and value. It should be used for types that are not represented by a specialized Field function. If the passed value type does not implement a custom array or object marshaller, reflection will be used for the fields of the type. Using reflection for performance critical code paths should be avoided.

func String

func String(key, val string) Field

String constructs a Field with the given key and value.

func StringFunc

func StringFunc(key string, f func() string) Field

StringFunc constructs a Field with the given key and a function that returns a string. The function is evaluated lazily - only when the log level is enabled and the handler processes the record. This provides significant performance benefits for expensive string operations when logging is disabled.

func Stringer

func Stringer(key string, val fmt.Stringer) Field

Stringer constructs a Field with the given key and value.

func Strings

func Strings(key string, val []string) Field

Strings constructs a Field with the given key and value.

func Time

func Time(key string, val time.Time) Field

Time constructs a Field with the given key and value.

func Uint

func Uint(key string, val uint) Field

Uint constructs a Field with the given key and value.

func Uint16

func Uint16(key string, val uint16) Field

Uint16 constructs a Field with the given key and value.

func Uint32

func Uint32(key string, val uint32) Field

Uint32 constructs a Field with the given key and value.

func Uint64

func Uint64(key string, val uint64) Field

Uint64 constructs a Field with the given key and value.

func Uint8

func Uint8(key string, val uint8) Field

Uint8 constructs a Field with the given key and value.

type Level

type Level = slog.Level

Level is a logging priority. Higher levels are more important.

func DefaultLevel

func DefaultLevel() Level

DefaultLevel returns the current default level for all loggers newly created with New().

type Logger

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

Logger provides fast, leveled, structured logging. All methods are safe for concurrent use.

func New

func New() *Logger

New returns a new Logger instance.

func NewNop

func NewNop() *Logger

NewNop creates a no-op logger which never writes logs to the output. Useful for tests.

func NewTestLogger

func NewTestLogger(t TestingT) *Logger

NewTestLogger builds a new Logger that logs all messages to the given testing.TB. The logs get only printed if a test fails or if the test is run with -v verbose flag.

func NewWithConfig

func NewWithConfig(cfg Config) *Logger

NewWithConfig creates a new logger for the given config. If no level is set in the config, it will use the default level of this package.

func (*Logger) Closer

func (l *Logger) Closer(closer io.Closer, msg string)

Closer calls the closer function and if an error gets returned it logs an error. This function is useful when using patterns like defer resp.Body.Close() which now become: defer logger.Closer(resp.Body, "closing body"). It filters out common expected errors like os.ErrClosed and network connection errors.

func (*Logger) CloserCtx

func (l *Logger) CloserCtx(ctx context.Context, closer closerCtx, msg string)

CloserCtx calls the closer function and if an error gets returned it logs an error. It respects context deadlines and cancellation, logging timeout errors appropriately.

func (*Logger) Debug

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

Debug logs at LevelDebug.

func (*Logger) DebugContext

func (l *Logger) DebugContext(ctx context.Context, msg string, args ...Field)

DebugContext logs at LevelDebug with the given context.

func (*Logger) Enabled

func (l *Logger) Enabled(ctx context.Context, level Level) bool

Enabled reports whether l emits log records at the given context and level. nolint: contextcheck

func (*Logger) Error

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

Error logs at LevelError.

func (*Logger) ErrorContext

func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...Field)

ErrorContext logs at LevelError with the given context.

func (*Logger) Fatal

func (l *Logger) Fatal(msg string, args ...Field)

Fatal logs at FatalLevel.

func (*Logger) FatalContext

func (l *Logger) FatalContext(ctx context.Context, msg string, args ...Field)

FatalContext logs at FatalLevel with the given context.

func (*Logger) Info

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

Info logs at LevelInfo.

func (*Logger) InfoContext

func (l *Logger) InfoContext(ctx context.Context, msg string, args ...Field)

InfoContext logs at LevelInfo with the given context.

func (*Logger) Level

func (l *Logger) Level() Level

Level returns the minimum enabled log level.

func (*Logger) Log

func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...Field)

Log emits a log record with the current time and the given level and message. nolint: contextcheck

func (*Logger) MultiCloser

func (l *Logger) MultiCloser(msg string, closers ...io.Closer)

MultiCloser calls multiple closer functions and logs any errors. It continues closing all resources even if some fail, logging each error separately.

func (*Logger) MultiCloserCtx

func (l *Logger) MultiCloserCtx(ctx context.Context, msg string, closers ...closerCtx)

MultiCloserCtx calls multiple context-aware closer functions and logs any errors. It continues closing all resources even if some fail, logging each error separately.

func (*Logger) Named

func (l *Logger) Named(name string) *Logger

Named adds a new path segment to the logger's name. Segments are joined by periods. By default, Loggers are unnamed.

func (*Logger) SetLevel

func (l *Logger) SetLevel(level Level)

SetLevel alters the logging level.

func (*Logger) Trace

func (l *Logger) Trace(msg string, args ...Field)

Trace logs at TraceLevel.

func (*Logger) TraceContext

func (l *Logger) TraceContext(ctx context.Context, msg string, args ...Field)

TraceContext logs at TraceLevel with the given context.

func (*Logger) Warn

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

Warn logs at LevelWarn.

func (*Logger) WarnContext

func (l *Logger) WarnContext(ctx context.Context, msg string, args ...Field)

WarnContext logs at LevelWarn with the given context.

func (*Logger) With

func (l *Logger) With(fields ...any) *Logger

With creates a child logger and adds structured context to it. Fields added to the child don't affect the parent, and vice versa.

type TestingT

type TestingT interface {
	// Logf logs the given message without failing the test.
	Logf(string, ...any)

	// Errorf logs the given message and marks the test as failed.
	Errorf(string, ...any)

	// FailNow marks the test as failed and stops execution of that test.
	FailNow()

	// Helper marks the calling function as a test helper function.
	Helper()
}

TestingT is a subset of the API provided by all *testing.T and *testing.B objects.

Jump to

Keyboard shortcuts

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