A flexible logging wrapper supporting both slog and logrus with beautiful, consistent formatting
- 🎨 Beautifully coloured output with customizable colours
- 🔄 Support for both slog (Go standard library) and logrus
- 📍 Optional caller information (package, function, line number)
- ⏰ Multiple timestamp formats (RFC3339, Standard, Simple, Time-only)
- 📏 Configurable level padding for perfect alignment
- 🎯 Unified API for both logging backends
- ⚙️ Simple, minimal configuration
go get github.com/zylisp/zylogRun the comprehensive demo:
make demoOr build and run manually:
make build
./bin/zylog-demoAt which point you should see something like the following:
See the demo code in cmd/zylog-demo/main.go for examples of both logging backends.
Use the unified SetupLogging() function to configure either logger:
package main
import (
"github.com/zylisp/zylog"
"github.com/zylisp/zylog/formatter"
"github.com/zylisp/zylog/options"
)
func main() {
// Configure with slog (default)
logger, err := zylog.SetupLogging(&options.ZyLog{
Coloured: true,
Level: "info",
Output: "stdout",
ReportCaller: true,
TimestampFormat: formatter.SimpleTimestamp,
PadLevel: true,
PadAmount: 7,
PadSide: "left",
Logger: options.Slog, // or options.LogRUs
})
if err != nil {
panic(err)
}
// For slog, use the returned logger
if logger != nil {
logger.Info("Application started")
logger.Info("User logged in", "user_id", 12345, "ip", "192.168.1.1")
}
}import (
"log/slog"
"github.com/zylisp/zylog"
"github.com/zylisp/zylog/options"
)
func main() {
// SetupLogging returns the configured slog logger and sets it as default
logger, _ := zylog.SetupLogging(options.Default())
// Use the returned logger directly
logger.Info("Application started")
// Or use the default slog logger
slog.Info("This also works")
// Structured logging
logger.Info("User action",
slog.String("user", "alice"),
slog.Int("request_id", 12345))
}import (
log "github.com/sirupsen/logrus"
"github.com/zylisp/zylog"
"github.com/zylisp/zylog/options"
)
func main() {
// For logrus, SetupLogging returns nil (uses global instance)
opts := options.Default()
opts.Logger = options.LogRUs
_, _ = zylog.SetupLogging(opts)
// Use global logrus instance
log.Info("Application started")
log.WithFields(log.Fields{
"user": "alice",
"request_id": 12345,
}).Info("User action")
}type ZyLog struct {
Coloured bool // Enable coloured output
Level string // Log level: "trace", "debug", "info", "warn", "error"
Output string // Output destination: "stdout", "stderr"
ReportCaller bool // Include caller information
TimestampFormat formatter.TSFormat // Timestamp format
PadLevel bool // Pad level strings for alignment
PadAmount int // Number of characters to pad to
PadSide string // "left" or "right"
MsgSeparator string // Separator between message and attributes
Logger options.Logger // LogRUs or Slog
}// Default configuration (slog with all features enabled)
opts := options.Default()
// Disable caller reporting
opts := options.NoCaller()Zylog allows you to customize the foreground and background colours of every formatted element. By default, zylog uses sensible colour defaults, but you can override any colour you want.
import (
"github.com/fatih/color"
"github.com/zylisp/zylog"
"github.com/zylisp/zylog/colours"
"github.com/zylisp/zylog/options"
)
func main() {
opts := options.Default()
// Customize just the colours you want to change
opts.Colours.LevelError = &colours.Colour{
Fg: color.FgHiRed,
Bg: color.BgYellow, // Add yellow background to errors
}
opts.Colours.Message = &colours.Colour{
Fg: color.FgHiWhite,
Bg: color.Reset, // No background
}
logger, _ := zylog.SetupLogging(opts)
logger.Error("This error has a yellow background!")
}To disable colour for a specific element while keeping others coloured, set both Fg and Bg to color.Reset:
opts := options.Default()
opts.Colours.Timestamp = &colours.Colour{
Fg: color.Reset,
Bg: color.Reset,
}
// Timestamp will now be uncoloured, but everything else remains colouredThe Colours struct provides fine-grained control over every coloured element:
type Colours struct {
// Timestamp colours (default: HiBlack/grey)
Timestamp *Colour
// Log level colours
LevelTrace *Colour // default: HiMagenta
LevelDebug *Colour // default: HiCyan
LevelInfo *Colour // default: HiGreen
LevelWarn *Colour // default: HiYellow
LevelWarning *Colour // default: HiYellow
LevelError *Colour // default: Red
LevelFatal *Colour // default: HiRed
LevelPanic *Colour // default: HiWhite
// Message text colour (default: Green)
Message *Colour
// Arrow separator " ▶ " (default: Cyan)
Arrow *Colour
// Caller information colours
CallerFunction *Colour // default: HiYellow
CallerLine *Colour // default: Yellow
// Structured logging attribute colours
AttrKey *Colour // default: Yellow
AttrValue *Colour // default: HiYellow
}
type Colour struct {
Fg color.Attribute // Foreground colour from github.com/fatih/color
Bg color.Attribute // Background colour from github.com/fatih/color
}Available colour attributes from github.com/fatih/color:
Foreground colours:
color.FgBlack,color.FgRed,color.FgGreen,color.FgYellowcolor.FgBlue,color.FgMagenta,color.FgCyan,color.FgWhitecolor.FgHiBlack,color.FgHiRed,color.FgHiGreen,color.FgHiYellowcolor.FgHiBlue,color.FgHiMagenta,color.FgHiCyan,color.FgHiWhite
Background colours:
color.BgBlack,color.BgRed,color.BgGreen,color.BgYellowcolor.BgBlue,color.BgMagenta,color.BgCyan,color.BgWhitecolor.BgHiBlack,color.BgHiRed,color.BgHiGreen,color.BgHiYellowcolor.BgHiBlue,color.BgHiMagenta,color.BgHiCyan,color.BgHiWhite
Special:
color.Reset- No colour (use for both Fg and Bg to disable colouring for an element)
The existing Coloured: false option continues to work and will disable ALL colours regardless of individual colour settings:
opts := options.Default()
opts.Coloured = false // Disables all colours globallyZylog supports multiple timestamp formats:
formatter.RFC3339- Full RFC3339 format (e.g.,2025-11-07T14:30:45-08:00)formatter.StandardTimestamp- Standard format (e.g.,2006/01/02 15:04:05)formatter.SimpleTimestamp- Compact format: YYYYMMDD.HHmmSS (e.g.,20251107.143045) [Default]formatter.TimeOnly- Time only: HH:mm:SS (e.g.,14:30:45)
opts.TimestampFormat = formatter.RFC3339 // 2024-11-07T14:30:52-05:00
opts.TimestampFormat = formatter.StandardTimestamp // 2006/01/02 15:04:05
opts.TimestampFormat = formatter.SimpleTimestamp // 20241107.143052
opts.TimestampFormat = formatter.TimeOnly // 14:30:5220241107.143052 INFO [main.main:42] ▶ Application started
20241107.143052 WARN [auth.Login:127] ▶ Failed login attempt: user={alice}, ip={192.168.1.1}
- ✅ Standard library (no external dependencies)
- ✅ Better performance
- ✅ Native structured logging
- ✅ Logger instances for better control
- ✅ Modern Go idioms
- ✅ Global singleton pattern
- ✅ Simpler for quick setup
- ✅ Wide ecosystem support
- ✅ Familiar to many Go developers
The formatting style is inspired by the Twig Clojure and Logjam LFE libraries.
© 2019,2025 ZYLISP Project © 2019-2025, geomyidia Project
Apache License, Version 2.0
