Documentation
¶
Overview ¶
Package slogs provides a lightweight, zero-external-dependency unified logging solution built on Go's standard log/slog package (Go 1.21+).
Features ¶
- Dual-target output: console (stderr) and file (JSON), dispatched via a built-in fan-out multiHandler.
- File rotation: built-in Rotator (adapted from lumberjack, MIT License) supports size-based rolling, backup retention, age-based cleanup, and gzip compression.
- Structured attributes: Logger.With attaches key-value context that propagates to all output targets.
- Named loggers: package-level CreateLogger/GetLogger manage multiple isolated logger instances via a singleton Manager.
- Global default: lazy-initialized default logger with package-level convenience functions (Info, Debug, Error, etc.).
Quick Start ¶
Zero-configuration usage with the global default logger:
slogs.Info("server started", "port", 8080)
slogs.Errorf("connection failed: %v", err)
Explicit initialization with file output:
cfg := slogs.NewConfig("debug", "logs/app.log", "json")
if err := slogs.Init(cfg); err != nil {
log.Fatal(err)
}
Standalone logger instance:
logger, err := slogs.NewLogger(slogs.Config{
Level: "info",
FilePath: "logs/audit.log",
MaxSize: 50,
})
if err != nil {
log.Fatal(err)
}
defer logger.Close()
logger.Info("audit event", "user", "admin")
Named loggers for multi-module isolation:
scanLog, _ := slogs.CreateLogger("scan", slogs.NewConfig("info", "logs/scan.log", "json"))
auditLog, _ := slogs.CreateLogger("audit", slogs.NewConfig("debug", "logs/audit.log", "json"))
defer slogs.CloseAll()
Configuration ¶
The Config struct controls logging behavior:
- Level: minimum log level ("debug", "info", "warn", "error").
- Format: console format ("text" or "json").
- FilePath: log file path; empty disables file output.
- MaxSize: max megabytes per file before rotation (default 100).
- MaxBackups: max old files to retain (default 3).
- MaxAge: max days to retain old files (default 30).
- Compress: gzip-compress rotated files (default true).
Thread Safety ¶
All exported types and functions are safe for concurrent use. The Manager uses a read-write mutex; Logger and Rotator use internal synchronization.
Index ¶
- func CloseAll() error
- func Debug(msg string, args ...any)
- func Debugf(template string, args ...any)
- func Error(msg string, args ...any)
- func Errorf(template string, args ...any)
- func Info(msg string, args ...any)
- func Infof(template string, args ...any)
- func Init(config Config) error
- func RemoveLogger(name string) error
- func SetDefault(logger *Logger)
- func Warn(msg string, args ...any)
- func Warnf(template string, args ...any)
- type Config
- type Logger
- func (l *Logger) Close() error
- func (l *Logger) Debug(msg string, args ...any)
- func (l *Logger) Debugf(template string, args ...any)
- func (l *Logger) Error(msg string, args ...any)
- func (l *Logger) Errorf(template string, args ...any)
- func (l *Logger) Info(msg string, args ...any)
- func (l *Logger) Infof(template string, args ...any)
- func (l *Logger) Slog() *slog.Logger
- func (l *Logger) Warn(msg string, args ...any)
- func (l *Logger) Warnf(template string, args ...any)
- func (l *Logger) With(args ...any) *Logger
- type Manager
- type Rotator
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CloseAll ¶
func CloseAll() error
CloseAll closes all managed loggers, closes the default logger, and resets the registry.
func Init ¶
Init initializes the global default logger with the given configuration. Once the default logger has been initialized (either via Init or lazy init), subsequent calls are no-ops and return nil.
Example ¶
ExampleInit demonstrates initializing the global default logger with file output.
package main
import (
"fmt"
"os"
"path/filepath"
"github.com/winezer0/slogs"
)
func main() {
dir, _ := os.MkdirTemp("", "slogs-example")
defer os.RemoveAll(dir)
cfg := slogs.NewConfig("debug", filepath.Join(dir, "app.log"), "json")
if err := slogs.Init(cfg); err != nil {
fmt.Println("init error:", err)
return
}
slogs.Debug("initialized with file output")
// Output is written to stderr and the log file.
}
Output:
func RemoveLogger ¶ added in v0.0.3
RemoveLogger removes and closes a named logger from the registry.
func SetDefault ¶
func SetDefault(logger *Logger)
SetDefault replaces the global default logger (useful for testing or late configuration). The previous default logger is closed to prevent resource leaks.
Example ¶
ExampleSetDefault demonstrates replacing the global default logger.
package main
import (
"fmt"
"os"
"path/filepath"
"github.com/winezer0/slogs"
)
func main() {
dir, _ := os.MkdirTemp("", "slogs-example")
defer os.RemoveAll(dir)
cfg := slogs.NewConfig("warn", filepath.Join(dir, "warn.log"), "json")
logger, err := slogs.NewLogger(cfg)
if err != nil {
fmt.Println("error:", err)
return
}
defer logger.Close()
slogs.SetDefault(logger)
// Now package-level functions use the new logger.
slogs.Warn("disk usage high", "percent", 92)
}
Output:
Types ¶
type Config ¶
type Config struct {
// Level is the minimum log level: debug, info, warn, error.
Level string `yaml:"level"`
// Format is the console output format: "text" (human-readable) or "json" (structured).
Format string `yaml:"format"`
// FilePath is the log file path; empty means no file output.
FilePath string `yaml:"file_path"`
// MaxSize is the maximum size in megabytes of a single log file before rotation.
MaxSize int `yaml:"max_size"`
// MaxBackups is the maximum number of old log files to retain.
MaxBackups int `yaml:"max_backups"`
// MaxAge is the maximum number of days to retain old log files.
MaxAge int `yaml:"max_age"`
// Compress determines whether rotated files are compressed.
Compress bool `yaml:"compress"`
}
Config holds logging configuration.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns a sensible default configuration (info level, text console, no file).
Example ¶
ExampleDefaultConfig demonstrates obtaining the default configuration.
package main
import (
"fmt"
"github.com/winezer0/slogs"
)
func main() {
cfg := slogs.DefaultConfig()
fmt.Println(cfg.Level)
fmt.Println(cfg.Format)
fmt.Println(cfg.MaxSize)
}
Output: info text 100
func NewConfig ¶
NewConfig creates a Config with the given level, file path, and format, applying defaults for rotation parameters.
Example ¶
ExampleNewConfig demonstrates creating a configuration with custom parameters.
package main
import (
"fmt"
"github.com/winezer0/slogs"
)
func main() {
cfg := slogs.NewConfig("error", "/var/log/myapp.log", "json")
fmt.Println(cfg.Level)
fmt.Println(cfg.FilePath)
fmt.Println(cfg.Compress)
}
Output: error /var/log/myapp.log true
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger wraps slog.Logger with configuration and lifecycle management.
func CreateLogger ¶
CreateLogger creates and registers a named logger.
Example ¶
ExampleCreateLogger demonstrates creating and retrieving named loggers.
package main
import (
"fmt"
"os"
"path/filepath"
"github.com/winezer0/slogs"
)
func main() {
dir, _ := os.MkdirTemp("", "slogs-example")
defer os.RemoveAll(dir)
defer slogs.CloseAll()
_, err := slogs.CreateLogger("scan", slogs.NewConfig("info", filepath.Join(dir, "scan.log"), "json"))
if err != nil {
fmt.Println("error:", err)
return
}
logger, ok := slogs.GetLogger("scan")
fmt.Println("retrieved:", ok)
logger.Info("scan completed", "targets", 42)
}
Output: retrieved: true
func Default ¶
func Default() *Logger
Default returns the global default logger, initializing it if necessary.
Example ¶
ExampleDefault demonstrates using the global default logger with zero configuration.
package main
import (
"github.com/winezer0/slogs"
)
func main() {
logger := slogs.Default()
logger.Info("using default logger", "version", "1.0.0")
}
Output:
func NewLogger ¶
NewLogger creates a Logger from the given configuration. Console output goes to stderr; file output (if configured) uses JSON with rotation.
Example ¶
ExampleNewLogger demonstrates creating a standalone logger instance.
package main
import (
"fmt"
"os"
"path/filepath"
"github.com/winezer0/slogs"
)
func main() {
dir, _ := os.MkdirTemp("", "slogs-example")
defer os.RemoveAll(dir)
cfg := slogs.Config{
Level: "info",
Format: "text",
FilePath: filepath.Join(dir, "audit.log"),
MaxSize: 50,
MaxBackups: 5,
MaxAge: 14,
Compress: true,
}
logger, err := slogs.NewLogger(cfg)
if err != nil {
fmt.Println("error:", err)
return
}
defer logger.Close()
logger.Info("audit event", "user", "admin", "action", "login")
}
Output:
func (*Logger) With ¶
With returns a Logger with the given attributes attached.
Example ¶
ExampleLogger_With demonstrates attaching structured attributes to a logger.
package main
import (
"github.com/winezer0/slogs"
)
func main() {
logger := slogs.Default()
reqLogger := logger.With("request_id", "abc-123", "service", "gateway")
reqLogger.Info("processing request", "method", "GET", "path", "/api/users")
}
Output:
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager manages named logger instances.
func (*Manager) CloseAll ¶
CloseAll closes all managed loggers, closes the default logger, and clears the registry.
type Rotator ¶
type Rotator struct {
// Filename is the file to write logs to. Backup log files will be retained
// in the same directory.
Filename string
// MaxSize is the maximum size in megabytes of the log file before rotation.
// Defaults to 100 megabytes.
MaxSize int
// MaxAge is the maximum number of days to retain old log files.
MaxAge int
// MaxBackups is the maximum number of old log files to retain.
MaxBackups int
// LocalTime determines if the time used for formatting the timestamps in
// backup files is the computer's local time. Default is UTC.
LocalTime bool
// Compress determines if rotated log files should be compressed using gzip.
Compress bool
// contains filtered or unexported fields
}
Rotator is an io.WriteCloser that writes to a rotating log file.
Rotator opens or creates the logfile on first Write. If the file exists and is less than MaxSize megabytes, it will open and append to that file. If the file exists and its size is >= MaxSize megabytes, the file is renamed by putting the current time in a timestamp in the name immediately before the file's extension. A new log file is then created using original filename.
Backups use the form `name-timestamp.ext` where timestamp is formatted with `2006-01-02T15-04-05.000`.