Documentation ¶
Overview ¶
Package blog is a simple async logger with file rotation and console logging.
Usage:
// Init blog. // // Parameters: // - DirPath: Path for log files. "." for current working directory or "" to disable file logging. // - Level: Desired logging level for filtering messages. // - IncludeLocation: When true, adds source file and line number to log messages (e.g., "main.go:42"). // - EnableConsole: When true, enables logging to the console in addition to files. // if err := blog.Init("logs", blog.INFO, false, true); err != nil { log.Printf("Error initializing logger: %v", err) } // Log messages from anywhere in the program blog.Info("This is an info message.") // Log messages with formatting blog.Warnf("This is an warn message with a format string: %v", err) // Synchronously cleanup the logger with a timeout; 0 means block indefinitely. // This should be called at the end of the program. blog.Cleanup(0) // for all other functions see `blog.go`. For access to the raw logger, see `logger.go`.
Performance Notes ¶
Defaults; All of these are modifiable at runtime via the public functions:
- Max buffer size: 4 KB.
- Max log file size: 1 GB. When this is reached the file is rotated.
- Flush interval: 15 seconds. For automatic flushing in low traffic scenarios.
A single thread is used to handle all logging operations. The channel that feeds it messages is buffered to 255 in the instance managed by the public functions. If you need control over it, you can create your own instance of the raw logger. Note interfacing with the raw logger is is different from the simplified public functions.
For contributors ¶
The approach is pretty straightforward. There is a slightly lower abstraction level logger in logger.go. This file creates and manages an instance of it for the common use case of a high abstraction singleton logger.
The logger is a struct with a few channels for communication and vars for configuration. When created it starts a goroutine that listens for messages/config updates via the chans then handles them. The logger's public functions don't interact with it's state directly, they do so through the channels. This makes it thread-safe and more performant, as relying on go's event system is better than mutexes in this case.
This has some nice benefits:
- Easily test multiple logger instances in parallel.
- Users don't need to manage the logger instance themselves.
Index ¶
- Constants
- Variables
- func Cleanup(timeout time.Duration) error
- func CopyNotNil[T any](dst, src *T)
- func Debug(msg string) error
- func Debugf(format string, args ...any) error
- func Error(msg string) error
- func Errorf(format string, args ...any) error
- func Fatal(exitCode int, timeout time.Duration, msg string) error
- func Fatalf(exitCode int, timeout time.Duration, format string, args ...any) error
- func Flush() error
- func GenRandomString(size int) (string, error)
- func Info(msg string) error
- func Infof(format string, args ...any) error
- func Init(DirPath string, Level LogLevel, IncludeLocation bool, EnableConsole bool) error
- func PadString(s string, length int) string
- func SetConsole(enable bool) error
- func SetDirectoryPath(path string) error
- func SetFlushInterval(d time.Duration) error
- func SetLevel(level LogLevel) error
- func SetMaxBufferSizeBytes(size int) error
- func SetMaxFileSizeBytes(size int) error
- func SyncFlush(timeout time.Duration) error
- func Ternary[T any](condition bool, a, b T) T
- func Warn(msg string) error
- func Warnf(format string, args ...any) error
- type Config
- type ConsoleLogger
- type LogLevel
- type LogMessage
- type Logger
- func (l *Logger) Debug(msg string)
- func (l *Logger) Debugf(format string, args ...any)
- func (l *Logger) Error(msg string)
- func (l *Logger) Errorf(format string, args ...any)
- func (l *Logger) Fatal(exitCode int, timeout time.Duration, msg string)
- func (l *Logger) Fatalf(exitCode int, timeout time.Duration, format string, args ...any)
- func (l *Logger) Flush()
- func (l *Logger) GetConfigCopy() Config
- func (l *Logger) Info(msg string)
- func (l *Logger) Infof(format string, args ...any)
- func (l *Logger) Shutdown(timeout time.Duration) error
- func (l *Logger) Start()
- func (l *Logger) SyncFlush(timeout time.Duration)
- func (l *Logger) UpdateConfig(cfg Config)
- func (l *Logger) Warn(msg string)
- func (l *Logger) Warnf(format string, args ...any)
Constants ¶
const ( MaxBufferSizeBytes = 4096 // 4 KB MaxLogFileSizeBytes = 1024 * 1024 * 1024 // 1 GB FlushInterval = 15 * time.Second )
Defaults for configuration settings.
Variables ¶
var ( ErrAlreadyInitialized = fmt.Errorf("blog: already initialized") ErrInvalidLogLevel = fmt.Errorf("blog: invalid log level") ErrUninitialized = fmt.Errorf("blog: uninitialized") ErrShutdown = fmt.Errorf("blog: logger has been shut down") ErrInvalidPath = fmt.Errorf("blog: invalid path") )
Functions ¶
func Cleanup ¶
Cleanup flushes the log write buffer and exits the logger. If timeout is 0, Cleanup blocks indefinitely.
func CopyNotNil ¶
func CopyNotNil[T any](dst, src *T)
CopyNotNil copies the value of src to dst if src is not nil.
func Fatal ¶
Fatal logs a fatal message and exits with the given exit code. This function will not return, it will exit the program after attempting to log the message.
func Fatalf ¶
Fatalf logs a fatal message with a format string and exits with the given exit code. This function will not return, it will exit the program after attempting to log the message.
func GenRandomString ¶
func Init ¶
Init sets up the logger with the specified configuration parameters.
Parameters:
- DirPath: Directory path for log files. Use "." for current working directory or "" to disable file logging.
- Level: Desired logging level for filtering messages.
- IncludeLocation: When true, adds source file and line number to log messages (e.g., "main.go:42").
- EnableConsole: When true, enables logging to the console in addition to files.
Returns:
- ErrAlreadyInitialized if logger was previously initialized,
- ErrInvalidPath if the directory path is invalid for any reason,
func SetConsole ¶
SetConsole enables or disables console logging.
func SetDirectoryPath ¶
SetDirectoryPath sets the directory path for the log files. To disable file logging, use an empty string.
func SetFlushInterval ¶
SetFlushInterval sets the interval at which the log write buffer is automatically flushed to the log file. This happens regardless of the buffer size. A value of 0 disables automatic flushing.
func SetMaxBufferSizeBytes ¶
SetMaxBufferSizeBytes sets the maximum size of the log write buffer. Larger values will increase memory usage and reduce the frequency of disk writes.
func SetMaxFileSizeBytes ¶
SetMaxFileSizeBytes sets the maximum size of the log file. When the log file reaches this size, it is renamed to the current timestamp and a new log file is created.
Types ¶
type Config ¶
type Config struct { Level *LogLevel // the minimum log level to write. Default is INFO. MaxBufferSizeBytes *int // the maximum size of the write buffer before it is flushed. Default is 4 KB. MaxFileSizeBytes *int // the maximum size of the log file before it is rotated. Default is 1 GB. FlushInterval *time.Duration // the interval at which the write buffer is flushed. Default is 15 seconds. DirectoryPath *string // the directory path where the log file is stored. Default is the current working directory ("."). To disable file logging, set this to an empty string. ConsoleOut *ConsoleLogger // the logger to write to the console. Default is ConsoleLogger{l: nil}. When l is nil, console logging is disabled. This is configurable for easy testing. }
Config holds the configuration settings for the Logger.
type ConsoleLogger ¶
type ConsoleLogger struct {
// contains filtered or unexported fields
}
ConsoleLogger wraps *log.Logger to allow nil value semantics for disabled state
type LogLevel ¶
type LogLevel int
func (*LogLevel) FromString ¶
FromString sets a LogLevel from a string, returning ErrInvalidLogLevel if the string is invalid. Case-insensitive. Example: "ERROR" -> ERROR, "error" -> ERROR, "Error" -> ERROR, etc.
type LogMessage ¶
type LogMessage struct {
// contains filtered or unexported fields
}
LogMessage represents a single log message.
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger is a simple, thread-safe logger. It supports various log levels, file and or console logging, basic performance tuning, automatic flushing, and size based log rotation.
func NewLogger ¶
NewLogger creates a new Logger instance with the provided configuration. It initializes all channels and starts the background logging goroutine.
The msgChanSize parameter controls the buffer size of the message channel, where 0 means unbuffered. LocationSkip controls the number of stack frames to skip when including the location in log messages (-1 to disable). For normal usage, LocationSkip should be set to 2.
Returns an error if the log directory path cannot be set.
func (*Logger) Fatal ¶
Fatal attempts to log a message and exits the program. It exits with the given exit code either when the message is logged or the timeout duration is reached. A timeout of 0 means block indefinitely.
func (*Logger) GetConfigCopy ¶
GetConfigCopy returns a copy of the current logger configuration.
func (*Logger) Shutdown ¶
Shutdown synchronously flushes and waits for the logger to shutdown it's goroutine for the given timeout duration. A timeout of 0 means block indefinitely. You may want to time.Sleep(20 * time.Millisecond) before calling this function to ensure all log messages are buffered.
func (*Logger) Start ¶
func (l *Logger) Start()
Start restarts the logger goroutine after a shutdown.
func (*Logger) SyncFlush ¶
SyncFlush synchronously flushes the log write buffer with the given timeout duration. A timeout of 0 means block indefinitely.
func (*Logger) UpdateConfig ¶
UpdateConfig updates the logger configuration with the provided settings. Nil fields are ignored.