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
- func ReplaceLevelName(_ []string, a slog.Attr) slog.Attr
- func SetDefaultLevel(level Level)
- type Config
- type ConsoleHandler
- type ConsoleHandlerOptions
- type Field
- func Bool(key string, val bool) Field
- func Duration(key string, val time.Duration) Field
- func Err(err error) Field
- func Float32(key string, val float32) Field
- func Float64(key string, val float64) Field
- func Hex(key string, val any) Field
- func Int(key string, val int) Field
- func Int16(key string, val int16) Field
- func Int32(key string, val int32) Field
- func Int64(key string, val int64) Field
- func Int8(key string, val int8) Field
- func IntFunc(key string, f func() int) Field
- func Object(key string, val any) Field
- func String(key, val string) Field
- func StringFunc(key string, f func() string) Field
- func Stringer(key string, val fmt.Stringer) Field
- func Strings(key string, val []string) Field
- func Time(key string, val time.Time) Field
- func Uint(key string, val uint) Field
- func Uint16(key string, val uint16) Field
- func Uint32(key string, val uint32) Field
- func Uint64(key string, val uint64) Field
- func Uint8(key string, val uint8) Field
- type Level
- type Logger
- func (l *Logger) Closer(closer io.Closer, msg string)
- func (l *Logger) CloserCtx(ctx context.Context, closer closerCtx, msg string)
- func (l *Logger) Debug(msg string, args ...Field)
- func (l *Logger) DebugContext(ctx context.Context, msg string, args ...Field)
- func (l *Logger) Enabled(ctx context.Context, level Level) bool
- func (l *Logger) Error(msg string, args ...Field)
- func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...Field)
- func (l *Logger) Fatal(msg string, args ...Field)
- func (l *Logger) FatalContext(ctx context.Context, msg string, args ...Field)
- func (l *Logger) Info(msg string, args ...Field)
- func (l *Logger) InfoContext(ctx context.Context, msg string, args ...Field)
- func (l *Logger) Level() Level
- func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...Field)
- func (l *Logger) MultiCloser(msg string, closers ...io.Closer)
- func (l *Logger) MultiCloserCtx(ctx context.Context, msg string, closers ...closerCtx)
- func (l *Logger) Named(name string) *Logger
- func (l *Logger) SetLevel(level Level)
- func (l *Logger) Trace(msg string, args ...Field)
- func (l *Logger) TraceContext(ctx context.Context, msg string, args ...Field)
- func (l *Logger) Warn(msg string, args ...Field)
- func (l *Logger) WarnContext(ctx context.Context, msg string, args ...Field)
- func (l *Logger) With(fields ...any) *Logger
- type TestingT
Constants ¶
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.
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 ¶
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 ¶
Enabled reports whether the handler handles records at the given level. The handler ignores records whose level is lower.
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 ¶
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 Hex ¶
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 IntFunc ¶
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 ¶
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 StringFunc ¶
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.
type 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 NewNop ¶
func NewNop() *Logger
NewNop creates a no-op logger which never writes logs to the output. Useful for tests.
func NewTestLogger ¶
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 ¶
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 ¶
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 ¶
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) DebugContext ¶
DebugContext logs at LevelDebug with the given context.
func (*Logger) Enabled ¶
Enabled reports whether l emits log records at the given context and level. nolint: contextcheck
func (*Logger) ErrorContext ¶
ErrorContext logs at LevelError with the given context.
func (*Logger) FatalContext ¶
FatalContext logs at FatalLevel with the given context.
func (*Logger) InfoContext ¶
InfoContext logs at LevelInfo with the given context.
func (*Logger) Log ¶
Log emits a log record with the current time and the given level and message. nolint: contextcheck
func (*Logger) MultiCloser ¶
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 ¶
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 ¶
Named adds a new path segment to the logger's name. Segments are joined by periods. By default, Loggers are unnamed.
func (*Logger) TraceContext ¶
TraceContext logs at TraceLevel with the given context.
func (*Logger) WarnContext ¶
WarnContext logs at LevelWarn with the given context.
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.