multilog

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2025 License: MIT Imports: 17 Imported by: 1

README

multilog

Go CI Workflow Go Report Card codecov GoDoc Go Version

A simple Go logging library to aggregate and manage multiple loggers with different formats and levels.

multilog provides a flexible way to send log messages to multiple destinations (e.g. stdout, files, custom writers) simultaneously, with configurable formats and per-logger log levels.

Features

  • Multiple handler types:
    • Console handlers for terminal output
    • File handlers with log rotation
    • JSON handlers for structured logging
  • Custom log levels including standard levels and performance logging
  • Configurable log patterns with placeholders
  • Support for structured logging via slog
  • Log rotation via lumberjack
  • Context-aware logging methods
  • Performance metrics collection
  • Custom attribute manipulation

Installation

go get github.com/phani-kb/multilog

Basic Usage

package main

import (
	"log/slog"
	
	"github.com/phani-kb/multilog"
)

func main() {
	// Create a console handler
	consoleHandler := multilog.NewConsoleHandler(multilog.CustomHandlerOptions{
		Level:   "perf",
		Enabled: true,
		Pattern: "[time] [level] [msg]",
	})

	// Create a file handler with rotation
	fileHandler, _ := multilog.NewFileHandler(multilog.CustomHandlerOptions{
		Level:      "debug",
		Enabled:    true,
		Pattern:    "[datetime] [level] [source] [msg]",
		File:       "logs/app.log",
		MaxSize:    5,
		MaxBackups: 3,
		MaxAge:     7,
	})

	// Create a JSON handler
	jsonHandler, _ := multilog.NewJSONHandler(multilog.CustomHandlerOptions{
		Level:   "perf",
		Enabled: true,
		Pattern: "[date] [level] [source] [msg]",
		File:    "logs/app.json",
	}, nil)

	// Create a logger with multiple handlers
	logger := multilog.NewLogger(consoleHandler, fileHandler, jsonHandler)

	// Set as default slog logger
	slog.SetDefault(logger.Logger)

	// Basic logging
	slog.Debug("Debug message")
	slog.Info("Info message", "user", "john", "action", "login")
	slog.Warn("Warning message", "temperature", 80)
	slog.Error("Error occurred", "err", "file not found")

	// Format-style logging
	logger.Debugf("Debug message with %s formatting", "string")
	logger.Infof("User %s logged in from %s", "john", "192.168.1.1")
	logger.Warnf("Temperature is %d degrees", 80)
	logger.Errorf("Failed to open file: %v", "permission denied")

	// Performance logging
	logger.Perf("Database operation", "operation", "query", "table", "users")
}
Example Output

Console output (with default pattern):

10:10:09 INFO Info message [user=john action=login]
10:10:09 WARN Warning message [temperature=80]
10:10:09 ERROR Error occurred [err="file not found"]
10:10:09 INFO User john logged in from 192.168.1.1
10:10:09 WARN Temperature is 80 degrees
10:10:09 ERROR Failed to open file: permission denied
10:10:09 PERF Database operation [goroutines:3,alloc:0.419044 MB,sys:6.334976 MB,heap_alloc:0.419044 MB,heap_sys:3.687500 MB,heap_idle:2.625000 MB,heap_inuse:1.062500 MB,stack_sys:0.312500 MB] [operation=query table=users]

File output (with source information):

2025-05-29 10:10:09 DEBUG unknown Debug message
2025-05-29 10:10:09 INFO unknown Info message [user=john action=login]
2025-05-29 10:10:09 WARN unknown Warning message [temperature=80]
2025-05-29 10:10:09 ERROR unknown Error occurred [err="file not found"]
2025-05-29 10:10:09 DEBUG basic_usage.go:50:main.main Debug message with string formatting
2025-05-29 10:10:09 INFO basic_usage.go:51:main.main User john logged in from 192.168.1.1
2025-05-29 10:10:09 WARN basic_usage.go:52:main.main Temperature is 80 degrees
2025-05-29 10:10:09 ERROR basic_usage.go:53:main.main Failed to open file: permission denied
2025-05-29 10:10:09 PERF basic_usage.go:56:main.main Database operation [goroutines:3,alloc:0.429909 MB,sys:6.334976 MB,heap_alloc:0.429909 MB,heap_sys:3.687500 MB,heap_idle:2.593750 MB,heap_inuse:1.093750 MB,stack_sys:0.312500 MB] [operation=query table=users]

JSON output:

{"action":"login","datetime":"2025-05-29 10:10:09","level":"INFO","msg":"Info message","source":"unknown","user":"john"}
{"datetime":"2025-05-29 10:10:09","level":"WARN","msg":"Warning message","source":"unknown","temperature":80}
{"datetime":"2025-05-29 10:10:09","err":"file not found","level":"ERROR","msg":"Error occurred","source":"unknown"}
{"datetime":"2025-05-29 10:10:09","level":"INFO","msg":"User john logged in from 192.168.1.1","source":"basic_usage.go:51:main.main"}
{"datetime":"2025-05-29 10:10:09","level":"WARN","msg":"Temperature is 80 degrees","source":"basic_usage.go:52:main.main"}
{"datetime":"2025-05-29 10:10:09","level":"ERROR","msg":"Failed to open file: permission denied","source":"basic_usage.go:53:main.main"}
{"datetime":"2025-05-29 10:10:09","level":"PERF","msg":"Database operation","operation":"query","perf":"goroutines:3,alloc:0.438530 MB,sys:6.334976 MB,heap_alloc:0.438530 MB,heap_sys:3.687500 MB,heap_idle:2.578125 MB,heap_inuse:1.109375 MB,stack_sys:0.312500 MB","source":"basic_usage.go:56:main.main","table":"users"}

Configuration

Multilog can be configured via code or YAML configuration:

multilog:
  handlers:
    - type: console
      level: debug
      enabled: true
      use_single_letter_level: true
      pattern: "[datetime] [[level]] [msg]"
    - type: file
      subtype: text
      level: debug
      enabled: true
      pattern: "[date] - [[time]] [[level]] [[source]] [msg]"
      file: logs/output.log
      max_size: 5 # MB
      max_backups: 7
      max_age: 1 # days
    - type: file
      subtype: json
      level: debug
      enabled: true
      pattern_placeholders: "[datetime], [level], [source], [msg], [perf]"
      file: logs/output.json
      max_size: 5 # MB
      max_backups: 7
      max_age: 1 # days

Load configuration file:

cfg, err := multilog.NewConfig("config.yml")
if err != nil {
    panic(err)
}

handlers, err := multilog.CreateHandlers(cfg)
if err != nil {
    panic(err)
}

logger := multilog.NewLogger(handlers...)

Pattern Placeholders

Customize your log format with these placeholders:

  • [date] - Date in YYYY-MM-DD format
  • [time] - Time in HH:MM:SS format
  • [datetime] - Combined date and time
  • [level] - Log level (DEBUG, INFO, WARN, ERROR, PERF)
  • [msg] - Log message
  • [source] - Source file, line number, and function
  • [perf] - Performance metrics (goroutines, heap, etc.)

Log Levels

  • debug - Detailed debugging information
  • info - General operational information
  • warn - Warning events that don't affect operation
  • error - Error events that might still allow continued operation
  • perf - Performance metrics (extends slog levels)

Handler Types

Console Handler

Outputs logs to stdout with customizable format:

handler := multilog.NewConsoleHandler(multilog.CustomHandlerOptions{
    Level:                "debug",
    Enabled:              true,
    Pattern:              "[time] [level] [msg]",
    UseSingleLetterLevel: true,
})
File Handler

Writes logs to a file with rotation support:

handler, err := multilog.NewFileHandler(multilog.CustomHandlerOptions{
    Level:     "info",
    Enabled:   true,
    Pattern:   "[datetime] [level] [source] [msg]",
    File:      "logs/app.log",
    MaxSize:   5,    // megabytes
    MaxBackups: 3,   // number of backups
    MaxAge:    7,    // days
})
JSON Handler

Structured logging in JSON format:

handler, err := multilog.NewJsonHandler(multilog.CustomHandlerOptions{
    Level:   "debug",
    Enabled: true,
    PatternPlaceholders: []string{
        "[datetime]", "[level]", "[msg]", "[source]",
    },
    File:    "logs/app.json",
})

Custom Handler Options

The CustomHandlerOptions struct provides extensive customization for all handlers:

Option Type Description Default
Level string Minimum log level to output "info"
SubType string Handler subtype (e.g., "text", "json") "text"
Enabled bool Whether the handler is active true
Pattern string Log message format pattern "[time] [level] [msg]"
PatternPlaceholders []string Placeholders for JSON handler []string{"[datetime]", "[level]", "[msg]", "[source]"}
AddSource bool Include source file/line information false
UseSingleLetterLevel bool Use single letter for level (D,I,W,E,P) false
ValuePrefixChar string Character before values ""
ValueSuffixChar string Character after values ""
File string Log file path ""
MaxSize int Max size in MB before rotation 5
MaxBackups int Max number of old log files 1
MaxAge int Max days to retain old logs 1
Single Letter Level Example

When UseSingleLetterLevel is enabled:

handler := multilog.NewConsoleHandler(multilog.CustomHandlerOptions{
    Level:                "info",
    Enabled:              true,
    Pattern:              "[time] [level] [msg]",
    UseSingleLetterLevel: true,
})

Output:

10:13:53 I Info message [user=john action=login]
10:13:53 W Warning message [temperature=80]
10:13:53 E Error occurred [err="file not found"]
10:13:53 I User john logged in from 192.168.1.1
10:13:53 W Temperature is 80 degrees
10:13:53 E Failed to open file: permission denied

Performance Metrics

Multilog can automatically collect and log performance metrics:

logger.Perf("API request completed", 
    "endpoint", "/users", 
    "method", "GET", 
    "duration_ms", 42)

This will include metrics such as:

  • Goroutine count
  • Heap allocations
  • System memory usage

Example performance log output:

10:04:05 PERF API request completed [goroutines:1,alloc:0.250191 MB,sys:6.334976 MB,heap_alloc:0.250191 MB,heap_sys:3.718750 MB,heap_idle:2.906250 MB,heap_inuse:0.812500 MB,stack_sys:0.281250 MB] [endpoint=/users method=GET duration_ms=42]

Advanced Usage

Context-Aware Logging
ctx := context.Background()

// Add request ID to context
ctx = context.WithValue(ctx, "request_id", "abc-123")

logger.InfoContext(ctx, "Processing request for user %s", "john")
Custom Attribute Replacement
replaceAttr := func(groups []string, a slog.Attr) slog.Attr {
    if a.Key == "password" {
        return slog.String("password", "****")
    }
    return a
}

opts := multilog.CustomHandlerOptions{
    Level:   "info",
    Enabled: true,
}

handler := multilog.NewCustomHandler(&opts, writer, replaceAttr)
Customizing Value Formatting

You can customize how values appear in logs:

handler := multilog.NewConsoleHandler(multilog.CustomHandlerOptions{
    Level:           "debug",
    Enabled:         true,
    Pattern:         "[time] [level] [msg]",
    ValuePrefixChar: "<",
    ValueSuffixChar: ">",
})

Output:

<10:51:36> <INFO> <Info message>
<10:51:36> <DEBUG> <Debugging information> [user=john action=login]

Implementation Details

Caller Information Tracking

Multilog captures source location (file, line, function) even through wrapper functions by using debug.Stack() to parse the call stack and identify the actual logging call.

⚠️ Performance Note: debug.Stack() has overhead. For high-volume production logging, disable source tracking with AddSource: false.

Standard Go logging approaches using runtime.Caller() with a fixed skip count would only report locations within the logging library itself, not the actual application code that initiated the log call.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements

  • slog - The Go standard library structured logging package
  • lumberjack - For log rotation

Documentation

Overview

Package multilog provides a multi-logger that can log to multiple destinations.

Index

Constants

View Source
const (
	DefaultTimeFormat     = "15:04:05"
	DefaultDateTimeFormat = "2006-01-02 15:04:05"
	DefaultDateFormat     = "2006-01-02"
)

Default time and date formats

View Source
const (
	DefaultLogFileSize    = 5 // in megabytes
	DefaultLogFileBackups = 1
	DefaultLogFileAge     = 1 // in days
)

Default log file settings

View Source
const (
	DebugLevel = "debug"
	InfoLevel  = "info"
	WarnLevel  = "warn"
	ErrorLevel = "error"
	PerfLevel  = "perf"
)

Log levels

View Source
const (
	FileHandlerType    = "file"
	ConsoleHandlerType = "console"
)

Handler types

View Source
const (
	TextHandlerSubType = "text"
	JSONHandlerSubType = "json"
)

Subtypes for file handlers

View Source
const (
	DefaultValuePrefixChar = ""
	DefaultValueSuffixChar = ""
)

Default value prefix and suffix characters

View Source
const (
	DefaultSuffixStartChar = "["
	DefaultSuffixEndChar   = "]"
)

Default suffix characters

View Source
const (
	DefaultPerfStartChar = "["
	DefaultPerfEndChar   = "]"
)

Default performance metrics characters

View Source
const (
	DefaultPlaceholderPrefixChar = "["
	DefaultPlaceholderSuffixChar = "]"
)

Default placeholder prefix and suffix characters

View Source
const (
	DatePlaceholder     = "[date]"
	TimePlaceholder     = "[time]"
	DateTimePlaceholder = "[datetime]"
	LevelPlaceholder    = "[level]"
	MsgPlaceholder      = "[msg]"
	PerfPlaceholder     = "[perf]"
	SourcePlaceholder   = "[source]"
)

Pattern placeholders

View Source
const (
	FileSource = "[file]"
	LineSource = "[line]"
	FuncSource = "[func]"
)

Source placeholders

View Source
const (
	DefaultFormat           = "[time] [level] [msg]"
	DefaultPerfFormat       = "[time] [level] [perf] [msg]"
	DefaultDebugFormat      = "[time] [level] [perf] [msg] [source]"
	DefaultErrorFormat      = "[time] [level] [msg] [source]"
	DefaultSourceFormat     = "[file]:[line]:[func]"
	DefaultPerfSourceFormat = DefaultSourceFormat
)

Default log formats

View Source
const (
	UnknownLevel     = "unknown"
	UnknownSource    = "unknown"
	DefaultSLogLevel = slog.LevelInfo
	DefaultLogLevel  = "info"
	LevelPerf        = slog.Level(-1)
)

Log level constants

View Source
const GenericLogFuncName = "multilog.(*Logger).log"

GenericLogFuncName is the function name used for generic logging.

View Source
const PackagePrefix = "multilog.(*Logger)."

PackagePrefix is the prefix used for package-level logging.

Variables

View Source
var (
	RemoveTimeKey    = RemoveKey(slog.TimeKey)
	RemoveLevelKey   = RemoveKey(slog.LevelKey)
	RemoveSourceKey  = RemoveKey(slog.SourceKey)
	RemoveMessageKey = RemoveKey(slog.MessageKey)
)

RemoveTimeKey, RemoveLevelKey, RemoveSourceKey, and RemoveMessageKey are functions

View Source
var CallIdentifiers = []string{
	"Perf(",
	"Perff(",
	"Infof(",
	"Warnf(",
	"Debugf(",
	"Errorf(",
}

CallIdentifiers contains the identifiers for various logging functions.

DefaultPatternPlaceholders represents the default pattern placeholders.

View Source
var LevelMap = map[string]slog.Level{
	"debug": slog.LevelDebug,
	"info":  slog.LevelInfo,
	"warn":  slog.LevelWarn,
	"error": slog.LevelError,
	"perf":  LevelPerf,
}

LevelMap maps string to slog.Level.

View Source
var LevelNamesMap = map[slog.Leveler]string{
	slog.LevelDebug: "debug",
	slog.LevelInfo:  "info",
	slog.LevelWarn:  "warn",
	slog.LevelError: "error",
	LevelPerf:       "perf",
}

LevelNamesMap maps slog.Level to string.

LogLevels contains all supported log levels.

Functions

func AddPrefixSuffix

func AddPrefixSuffix(value string, opts *CustomHandlerOptions) string

AddPrefixSuffix adds the prefix and suffix to the value.

func BaseName

func BaseName(file string) string

BaseName returns the base name of a file.

func Contains

func Contains(slice []string, item string) bool

Contains checks if a string slice contains a specific item.

func ContainsKey

func ContainsKey(keys []string, key string) bool

ContainsKey checks if the given key is present in the keys.

func CreateHandlers

func CreateHandlers(config *Config) ([]slog.Handler, error)

CreateHandlers creates the handlers based on the configuration.

func CreateRotationWriter

func CreateRotationWriter(opts CustomHandlerOptions) *bufio.Writer

CreateRotationWriter creates a rotation writer for the given options.

func GetCallerInfo

func GetCallerInfo(identifiers ...string) (fn, file string, line int, found bool)

GetCallerInfo retrieves the caller information from the stack trace.

func GetLevelName

func GetLevelName(level slog.Level) string

GetLevelName returns the string representation of the slog.Level.

func GetOtherCallerInfo

func GetOtherCallerInfo() (fn, file string, line int, found bool)

GetOtherCallerInfo returns the caller information for other logs.

func GetOtherSourceValue

func GetOtherSourceValue(fn, file string, line int) string

GetOtherSourceValue returns the source value for other logs.

func GetPerfCallerInfo

func GetPerfCallerInfo() (fn, file string, line int, found bool)

GetPerfCallerInfo returns the caller information for performance logs.

func GetPerformanceMetrics

func GetPerformanceMetrics() string

GetPerformanceMetrics gathers memory and goroutine metrics.

func GetPerformanceMetricsUsingRuntime

func GetPerformanceMetricsUsingRuntime() string

GetPerformanceMetricsUsingRuntime gathers memory and goroutine metrics.

func GetPerformanceMetricsWithMemStats

func GetPerformanceMetricsWithMemStats() string

GetPerformanceMetricsWithMemStats gathers memory and goroutine metrics.

func GetPlaceholderValues

func GetPlaceholderValues(
	sb *strings.Builder,
	record slog.Record,
	placeholders []string,
	getKeyValue func(string, *strings.Builder, bool) string,
) map[string]interface{}

GetPlaceholderValues returns the placeholder values.

func GetPlaceholders

func GetPlaceholders(format string) []string

GetPlaceholders returns the placeholders from the format.

func GetSlogLevel

func GetSlogLevel(level string) slog.Level

GetSlogLevel returns the slog.Level for the given level string.

func GetSourceValue

func GetSourceValue(
	level slog.Level,
	sb *strings.Builder,
	getKeyValue func(string, *strings.Builder, bool) string,
) string

GetSourceValue returns the source value.

func NewConsoleHandler

func NewConsoleHandler(opts CustomHandlerOptions) slog.Handler

NewConsoleHandler creates a console Handler with the specified options.

func NewFileHandler

func NewFileHandler(opts CustomHandlerOptions) (slog.Handler, error)

NewFileHandler creates a file Handler with the specified options.

func NewJSONHandler

func NewJSONHandler(
	opts CustomHandlerOptions,
	replaceAttr CustomReplaceAttr,
) (slog.Handler, error)

NewJSONHandler creates a JSON Handler with the specified options.

func NewTestLogger

func NewTestLogger(t *testing.T) (*Logger, *TestHandler)

NewTestLogger creates a new Logger instance with the given handler.

func Remove

func Remove(key string, a slog.Attr) slog.Attr

Remove removes the given key from the attributes.

func RemoveKey

func RemoveKey(key string) func(groups []string, a slog.Attr) slog.Attr

RemoveKey returns a function that removes the specified attribute key.

func RemovePlaceholderChars

func RemovePlaceholderChars(values map[string]interface{}) map[string]interface{}

RemovePlaceholderChars removes the placeholder characters from the values.

func TrimSpaces

func TrimSpaces(placeholders []string) []string

TrimSpaces trims the spaces from the placeholders.

Types

type Aggregator

type Aggregator []slog.Handler

Aggregator is a handler that forwards logs to multiple handlers.

func NewAggregator

func NewAggregator(handlers ...slog.Handler) Aggregator

NewAggregator creates a new aggregator with the given handlers.

func (Aggregator) Enabled

func (a Aggregator) Enabled(ctx context.Context, level slog.Level) bool

Enabled implements slog.Handler.

func (Aggregator) Handle

func (a Aggregator) Handle(ctx context.Context, r slog.Record) error

Handle implements slog.Handler.

func (Aggregator) WithAttrs

func (a Aggregator) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs implements slog.Handler.

func (Aggregator) WithGroup

func (a Aggregator) WithGroup(name string) slog.Handler

WithGroup implements slog.Handler.

type Config

type Config struct {
	Multilog LogConfig `yaml:"multilog"`
}

Config represents the configuration for the application.

func NewConfig

func NewConfig(filename string) (*Config, error)

NewConfig loads the configuration from the specified YAML file.

func NewConfigFromData

func NewConfigFromData(data []byte) (*Config, error)

NewConfigFromData loads the configuration from the provided YAML data.

func (*Config) GetCustomHandlerOptionsForHandler

func (c *Config) GetCustomHandlerOptionsForHandler(
	handlerConfig HandlerConfig,
) (CustomHandlerOptions, error)

GetCustomHandlerOptionsForHandler returns the custom handler options for the handler.

func (*Config) GetEnabledHandlers

func (c *Config) GetEnabledHandlers() []HandlerConfig

GetEnabledHandlers returns the list of enabled handlers from the configuration.

type ConsoleHandler

type ConsoleHandler struct {
	Handler CustomHandlerInterface
}

ConsoleHandler is a Handler for console logging.

func (*ConsoleHandler) Enabled

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

Enabled checks if the handler is enabled for the given level.

func (*ConsoleHandler) Handle

func (ch *ConsoleHandler) Handle(ctx context.Context, record slog.Record) error

Handle processes the log record and writes it to the console handler.

func (*ConsoleHandler) WithAttrs

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

WithAttrs creates a new handler with the given attributes.

func (*ConsoleHandler) WithGroup

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

WithGroup creates a new handler with the given group name.

type ContextLogger

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

ContextLogger wraps a Logger with a context

func (*ContextLogger) Debug

func (l *ContextLogger) Debug(msg string, args ...any)

Debug logs a debug message with structured key-value pairs.

func (*ContextLogger) DebugContext

func (l *ContextLogger) DebugContext(ctx context.Context, msg string, args ...any)

DebugContext logs a debug message

func (*ContextLogger) Debugf

func (l *ContextLogger) Debugf(msg string, args ...any)

Debugf logs a debug message with structured key-value pairs.

func (*ContextLogger) Error

func (l *ContextLogger) Error(msg string, args ...any)

Error logs an error message with structured key-value pairs.

func (*ContextLogger) ErrorContext

func (l *ContextLogger) ErrorContext(ctx context.Context, msg string, args ...any)

ErrorContext logs an error message

func (*ContextLogger) Errorf

func (l *ContextLogger) Errorf(msg string, args ...any)

Errorf logs an error message with structured key-value pairs.

func (*ContextLogger) Info

func (l *ContextLogger) Info(msg string, args ...any)

Info logs an informational message with structured key-value pairs.

func (*ContextLogger) InfoContext

func (l *ContextLogger) InfoContext(ctx context.Context, msg string, args ...any)

InfoContext logs an informational message

func (*ContextLogger) Infof

func (l *ContextLogger) Infof(msg string, args ...any)

Infof logs an informational message with structured key-value pairs.

func (*ContextLogger) Perf

func (l *ContextLogger) Perf(msg string, args ...any)

Perf logs performance metrics statically.

func (*ContextLogger) PerfContext

func (l *ContextLogger) PerfContext(ctx context.Context, msg string, args ...any)

PerfContext logs performance metrics dynamically.

func (*ContextLogger) Perff

func (l *ContextLogger) Perff(msg string, args ...any)

Perff logs performance metrics dynamically.

func (*ContextLogger) Warn

func (l *ContextLogger) Warn(msg string, args ...any)

Warn logs a warning message with structured key-value pairs.

func (*ContextLogger) WarnContext

func (l *ContextLogger) WarnContext(ctx context.Context, msg string, args ...any)

WarnContext logs a warning message

func (*ContextLogger) Warnf

func (l *ContextLogger) Warnf(msg string, args ...any)

Warnf logs a warning message with structured key-value pairs.

func (*ContextLogger) WithContext

func (l *ContextLogger) WithContext(ctx context.Context) LoggerInterface

WithContext for ContextLogger should return a new ContextLogger with the new context

func (*ContextLogger) WithField

func (l *ContextLogger) WithField(key string, value any) LoggerInterface

WithField ensures we maintain the context when adding fields

func (*ContextLogger) WithFields

func (l *ContextLogger) WithFields(fields map[string]any) LoggerInterface

WithFields ensures we maintain the context when adding fields

type CustomHandler

type CustomHandler struct {
	Opts *CustomHandlerOptions
	// contains filtered or unexported fields
}

CustomHandler is a base handler for logging.

func NewCustomHandler

func NewCustomHandler(
	customOpts *CustomHandlerOptions,
	writer *bufio.Writer,
	replaceAttr CustomReplaceAttr,
) *CustomHandler

NewCustomHandler creates a new handler with a given configuration.

func (*CustomHandler) Enabled

func (ch *CustomHandler) Enabled(ctx context.Context, level slog.Level) bool

Enabled determines if a log message should be logged based on its level.

func (*CustomHandler) GetKeyValue

func (ch *CustomHandler) GetKeyValue(key string, sb *strings.Builder, removeKey bool) string

GetKeyValue returns the value of a key.

func (*CustomHandler) GetOptions

func (ch *CustomHandler) GetOptions() *CustomHandlerOptions

GetOptions returns the handler options.

func (*CustomHandler) GetSlogHandler

func (ch *CustomHandler) GetSlogHandler() slog.Handler

GetSlogHandler returns the handler slog.Handler.

func (*CustomHandler) GetStringBuilder

func (ch *CustomHandler) GetStringBuilder() *strings.Builder

GetStringBuilder returns the handler string builder.

func (*CustomHandler) GetWriter

func (ch *CustomHandler) GetWriter() *bufio.Writer

GetWriter returns the handler writer.

func (*CustomHandler) Handle

func (ch *CustomHandler) Handle(ctx context.Context, record slog.Record) error

Handle processes the log record and outputs it.

func (*CustomHandler) WithAttrs

func (ch *CustomHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs adds attributes to the handler.

func (*CustomHandler) WithGroup

func (ch *CustomHandler) WithGroup(name string) slog.Handler

WithGroup creates a new handler with grouped attributes.

type CustomHandlerInterface

type CustomHandlerInterface interface {
	slog.Handler
	GetOptions() *CustomHandlerOptions
	GetStringBuilder() *strings.Builder
	GetKeyValue(key string, sb *strings.Builder, removeKey bool) string
	GetWriter() *bufio.Writer
	GetSlogHandler() slog.Handler
}

CustomHandlerInterface is an interface for the custom handler.

type CustomHandlerOptions

type CustomHandlerOptions struct {
	Level                string
	File                 string
	ValueSuffixChar      string
	ValuePrefixChar      string
	Pattern              string
	SubType              string
	PatternPlaceholders  []string
	MaxSize              int
	MaxAge               int
	MaxBackups           int
	UseSingleLetterLevel bool
	AddSource            bool
	Enabled              bool
}

CustomHandlerOptions contains configuration options for the handler.

type CustomReplaceAttr

type CustomReplaceAttr func(groups []string, a slog.Attr) slog.Attr

CustomReplaceAttr is a function type for replacing attributes.

func GenerateDefaultCustomReplaceAttr

func GenerateDefaultCustomReplaceAttr(
	opts CustomHandlerOptions,
	keysToRemove ...string,
) CustomReplaceAttr

GenerateDefaultCustomReplaceAttr returns a default CustomReplaceAttr function.

func RemoveGivenKeys

func RemoveGivenKeys(keys ...string) CustomReplaceAttr

RemoveGivenKeys returns a function that removes the given keys.

func RemoveKeys

func RemoveKeys() CustomReplaceAttr

RemoveKeys returns a function that removes the time, level, source, and message keys.

func ReplaceAttr

func ReplaceAttr(replaceMap map[string]string) CustomReplaceAttr

ReplaceAttr is a function type for replacing attributes.

type FileHandler

type FileHandler struct {
	Handler CustomHandlerInterface
}

FileHandler is a Handler for file logging.

func (*FileHandler) Enabled

func (fh *FileHandler) Enabled(ctx context.Context, level slog.Level) bool

Enabled checks if the handler is enabled for the given level.

func (*FileHandler) Handle

func (fh *FileHandler) Handle(ctx context.Context, record slog.Record) error

Handle processes the log record and writes it to the file handler.

func (*FileHandler) WithAttrs

func (fh *FileHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs creates a new handler with the given attributes.

func (*FileHandler) WithGroup

func (fh *FileHandler) WithGroup(name string) slog.Handler

WithGroup creates a new handler with the given group name.

type HandlerConfig

type HandlerConfig struct {
	Type                 string `yaml:"type"`
	SubType              string `yaml:"subtype,omitempty"`
	Level                string `yaml:"level"`
	Pattern              string `yaml:"pattern,omitempty"`
	PatternPlaceholders  string `yaml:"pattern_placeholders,omitempty"`
	ValuePrefixChar      string `yaml:"value_prefix_char,omitempty"`
	ValueSuffixChar      string `yaml:"value_suffix_char,omitempty"`
	File                 string `yaml:"file,omitempty"`
	MaxSize              int    `yaml:"max_size,omitempty"`
	MaxBackups           int    `yaml:"max_backups,omitempty"`
	MaxAge               int    `yaml:"max_age,omitempty"`
	Enabled              bool   `yaml:"enabled"`
	UseSingleLetterLevel bool   `yaml:"use_single_letter_level,omitempty"`
}

HandlerConfig represents the configuration for a specific handler.

type JSONHandler

type JSONHandler struct {
	Handler CustomHandlerInterface
}

JSONHandler is a Handler for JSON logging.

func (*JSONHandler) Enabled

func (jh *JSONHandler) Enabled(ctx context.Context, level slog.Level) bool

Enabled checks if the handler is enabled for the given level.

func (*JSONHandler) GetKeyValue

func (jh *JSONHandler) GetKeyValue(key string, sb *strings.Builder, removeKey bool) string

GetKeyValue retrieves the value associated with the given key from the JSON string.

func (*JSONHandler) Handle

func (jh *JSONHandler) Handle(ctx context.Context, record slog.Record) error

Handle processes the log record and writes it to the JSON handler.

func (*JSONHandler) WithAttrs

func (jh *JSONHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs creates a new handler with the given attributes.

func (*JSONHandler) WithGroup

func (jh *JSONHandler) WithGroup(name string) slog.Handler

WithGroup creates a new handler with the given group name.

type LogConfig

type LogConfig struct {
	Handlers []HandlerConfig `yaml:"handlers"`
}

LogConfig represents the logging configuration.

type LogRecord

type LogRecord struct {
	Time        string
	Message     string
	Format      LogRecordFormat
	Source      SourceInfo
	PerfMetrics PerfMetrics
	Level       slog.Level
}

LogRecord represents a log record with additional information.

type LogRecordFormat

type LogRecordFormat struct {
	Pattern string
}

LogRecordFormat represents the format of a log record.

type Logger

type Logger struct {
	Logger *slog.Logger
	// contains filtered or unexported fields
}

Logger wraps slog.Logger and allows configuration of handlers.

func NewLogger

func NewLogger(handlers ...slog.Handler) *Logger

NewLogger creates a new logger with the specified handlers.

func (*Logger) Debug

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

Debug logs a debug message with structured key-value pairs.

func (*Logger) DebugContext

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

DebugContext logs a debug message with structured key-value pairs.

func (*Logger) Debugf

func (l *Logger) Debugf(msg string, args ...any)

Debugf logs a debug message.

func (*Logger) Error

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

Error logs an error message with structured key-value pairs.

func (*Logger) ErrorContext

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

ErrorContext logs an error message with structured key-value pairs.

func (*Logger) Errorf

func (l *Logger) Errorf(msg string, args ...any)

Errorf logs an error message.

func (*Logger) GetLogger

func (l *Logger) GetLogger() *slog.Logger

GetLogger returns the underlying slog.Logger

func (*Logger) Info

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

Info logs an informational message with structured key-value pairs.

func (*Logger) InfoContext

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

InfoContext logs an informational message with structured key-value pairs.

func (*Logger) Infof

func (l *Logger) Infof(msg string, args ...any)

Infof logs an informational message.

func (*Logger) Perf

func (l *Logger) Perf(msg string, args ...any)

Perf logs performance metrics statically.

func (*Logger) PerfContext

func (l *Logger) PerfContext(ctx context.Context, msg string, args ...any)

PerfContext logs performance metrics dynamically.

func (*Logger) Perff

func (l *Logger) Perff(msg string, args ...any)

Perff logs performance metrics dynamically.

func (*Logger) Warn

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

Warn logs a warning message with structured key-value pairs.

func (*Logger) WarnContext

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

WarnContext logs a warning message with structured key-value pairs.

func (*Logger) Warnf

func (l *Logger) Warnf(msg string, args ...any)

Warnf logs a warning message.

func (*Logger) WithContext

func (l *Logger) WithContext(ctx context.Context) LoggerInterface

WithContext returns a logger with the context attached

func (*Logger) WithField

func (l *Logger) WithField(key string, value any) LoggerInterface

WithField returns a logger with the specified field attached to all messages

func (*Logger) WithFields

func (l *Logger) WithFields(fields map[string]any) LoggerInterface

WithFields returns a logger with the specified fields attached to all messages

func (*Logger) WithLevel

func (l *Logger) WithLevel(_ slog.Level) *Logger

WithLevel returns a new logger with the specified minimum level

type LoggerInterface

type LoggerInterface interface {
	Perff(msg string, args ...any)
	Perf(msg string, args ...any)
	Infof(msg string, args ...any)
	Warnf(msg string, args ...any)
	Errorf(msg string, args ...any)
	Debugf(msg string, args ...any)

	// Debug Structured logging methods
	Debug(msg string, args ...any)
	Info(msg string, args ...any)
	Warn(msg string, args ...any)
	Error(msg string, args ...any)

	// WithContext Context-aware logging methods
	WithContext(ctx context.Context) LoggerInterface
	PerfContext(ctx context.Context, msg string, args ...any)
	InfoContext(ctx context.Context, msg string, args ...any)
	WarnContext(ctx context.Context, msg string, args ...any)
	ErrorContext(ctx context.Context, msg string, args ...any)
	DebugContext(ctx context.Context, msg string, args ...any)

	// WithField Structured logging methods
	WithField(key string, value any) LoggerInterface
	WithFields(fields map[string]any) LoggerInterface

	// GetLogger Return the underlying logger for advanced usage
	GetLogger() *slog.Logger
}

LoggerInterface defines the logging methods available

type PerfMetrics

type PerfMetrics struct {
	NumGoroutines int
	NumCPUs       int
	MaxThreads    int
	GCHeapAllocs  uint64
	GCHeapFrees   uint64
	HeapFree      uint64
	HeapObjects   uint64
	HeapReleased  uint64
	HeapUnused    uint64
	TotalMemory   uint64
	TotalCPUUsage float64
	UserCPUUsage  float64
	Alloc         float64
	TotalAlloc    float64
	Sys           float64
	HeapAlloc     float64
	HeapSys       float64
	HeapIdle      float64
	HeapInuse     float64
	StackSys      float64
}

PerfMetrics represents performance metrics.

func CollectPerfMetrics

func CollectPerfMetrics() *PerfMetrics

CollectPerfMetrics collects performance metrics.

func CollectPerfMetricsWithMemStats

func CollectPerfMetricsWithMemStats() *PerfMetrics

CollectPerfMetricsWithMemStats collects performance metrics including memory stats.

type SourceInfo

type SourceInfo struct {
	File string
	Line int
}

SourceInfo represents the source information of a log record.

type TestHandler

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

TestHandler implements slog.Handler for testing purposes

func NewTestHandler

func NewTestHandler(t *testing.T) *TestHandler

NewTestHandler creates a new TestHandler for testing purposes.

func (*TestHandler) Called

func (h *TestHandler) Called() bool

Called returns whether the handler has been called.

func (*TestHandler) Enabled

func (h *TestHandler) Enabled(_ context.Context, _ slog.Level) bool

Enabled reports whether the handler is enabled for the given level.

func (*TestHandler) Handle

func (h *TestHandler) Handle(_ context.Context, r slog.Record) error

Handle processes the log record and sets the called flag.

func (*TestHandler) LastLevel added in v0.2.0

func (h *TestHandler) LastLevel() slog.Level

LastLevel returns the last logged level.

func (*TestHandler) LastMessage added in v0.2.0

func (h *TestHandler) LastMessage() string

LastMessage returns the last logged message.

func (*TestHandler) Reset

func (h *TestHandler) Reset()

Reset resets the handler's state for the next test.

func (*TestHandler) WithAttrs

func (h *TestHandler) WithAttrs(_ []slog.Attr) slog.Handler

WithAttrs creates a new handler with the given attributes.

func (*TestHandler) WithGroup

func (h *TestHandler) WithGroup(_ string) slog.Handler

WithGroup creates a new handler with the given group name.

type WriterHandler

type WriterHandler interface {
	CustomWrite(output string) error
}

WriterHandler is an interface for custom write operations.

Directories

Path Synopsis
Package main provides the entry point for the multilog application.
Package main provides the entry point for the multilog application.
Example of using a multilog package for logging with multiple handlers
Example of using a multilog package for logging with multiple handlers

Jump to

Keyboard shortcuts

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