rlog

package module
v0.0.0-...-cdbd557 Latest Latest
Warning

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

Go to latest
Published: Oct 20, 2025 License: MIT Imports: 12 Imported by: 0

README

rlog

rlog is a minimalistic, asynchronous logger for Go services that prefer best-effort throughput over perfect durability. It focuses on simplicity: format the message once, push it to a buffered channel, and let background writers take care of I/O.

Highlights

  • Structured around a tiny LogSink interface; mix and match sinks as needed.
  • Console writer with optional ANSI colouring for warnings and errors.
  • Buffered file writer with rotation and configurable size limits.
  • Built-in presets surface audit-level events on the console so operators don't miss key milestones.
  • Global helpers (rlog.Infof, rlog.Warnf, …) for applications that want a ready-to-use default logger.
  • Designed to keep the main code path non-blocking during normal operation.

Quick Start

package main

import (
	"time"

	"github.com/gavriva/rlog"
)

func main() {
	logger := rlog.NewLogger(
		rlog.NewBufferedSink(128, rlog.NewFileWriter("service", 200*1024*1024)),
		true, // include caller file:line
	)
	defer logger.Close()

	logger.Infof("service started")
	time.Sleep(time.Second)
	logger.Warnf("downstream latency exceeded: %s", time.Second)
}

Log levels

Level Purpose
rlog.Debug Noisy diagnostics for temporary troubleshooting.
rlog.Info Routine operational updates.
rlog.Audit High-level business events that operators should see on the console by default.
rlog.Warn Recoverable anomalies that merit attention.
rlog.Error Failures that need intervention.

Built-in sinks

  • ConsoleWriter — prints to STDOUT, optionally colourised.
  • FileWriter — rotates log files (app.log, app.1.log, app.2.log) once the size limit is reached.
  • BufferedSink — decouples the caller from I/O by dispatching logs through a bounded channel and periodic flushes.
  • MultiWriter — mirrors logs to two sinks (for example console + file). Combine sinks to match your deployment scenario:
logger := rlog.NewLogger(
	rlog.NewMultiWriter(
		rlog.NewConsoleWriter(rlog.Audit),
		rlog.NewBufferedSink(256, rlog.NewFileWriter("", 1e8)),
	),
	true,
)

Global logger

For applications that prefer a singleton logger, call one of the presets:

rlog.EnableDefaultLoggerForService()
defer rlog.Close()
rlog.Infof("ready to accept requests")

Remember to call rlog.Close() during shutdown to flush buffered output.

Design notes & trade-offs

  • BufferedSink uses a bounded channel. When the buffer is saturated the call to Log blocks until space is available. Pick a size that fits your burst rate to keep the hot path non-blocking.
  • There is no guarantee that every record is written before an unexpected process crash. If durable logging is critical, pair rlog with an external collector or append-only sink.
  • File rotation keeps the three most recent log files by default.

License

MIT — see LICENSE for details.

Documentation

Overview

Package rlog provides a minimal asynchronous logger tailored for high-throughput, best-effort recording of unstructured log messages. The package keeps the API surface tiny and accepts that queued log writes may block when downstream sinks stall.

Index

Constants

View Source
const (

	// Debug is the most verbose log level, intended for temporary diagnostic noise.
	Debug = 0
	// Info emits general information about application progress.
	Info = 1
	// Audit is for high-level business events that operators prefer to see by default.
	Audit = 2
	// Warn signals unexpected situations that the application can recover from.
	Warn = 3
	// Error indicates failures that require attention.
	Error = 4
)

Variables

This section is empty.

Functions

func Auditf

func Auditf(format string, v ...interface{})

Auditf logs using fmt.Sprintf semantics at Audit level.

func Close

func Close()

Close releases resources owned by the global logger and replaces it with a no-op logger.

func Debugf

func Debugf(format string, v ...interface{})

Debugf logs using fmt.Sprintf semantics at Debug level.

func EnableDefaultLoggerForLogServer

func EnableDefaultLoggerForLogServer()

EnableDefaultLoggerForLogServer configures the global logger for log-forwarding processes that only need durable file storage.

func EnableDefaultLoggerForService

func EnableDefaultLoggerForService()

EnableDefaultLoggerForService configures the global logger for services that run continuously, defaulting to warning level output on the console.

func EnableDefaultLoggerForUtility

func EnableDefaultLoggerForUtility()

EnableDefaultLoggerForUtility configures the global logger for short-lived command line utilities. It combines console output with a buffered file sink.

func Errorf

func Errorf(format string, v ...interface{})

Errorf logs using fmt.Sprintf semantics at Error level.

func Fatalf

func Fatalf(format string, v ...interface{})

Fatalf logs the message at error level and exits the process with status 1.

func Infof

func Infof(format string, v ...interface{})

Infof logs using fmt.Sprintf semantics at Info level.

func IsDebugEnabled

func IsDebugEnabled() bool

IsDebugEnabled reports whether the default logger has the Debug level enabled.

func Warnf

func Warnf(format string, v ...interface{})

Warnf logs using fmt.Sprintf semantics at Warn level.

Types

type BufferedSink

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

BufferedSink decouples producers from downstream sinks by writing log entries into a bounded channel. The background goroutine periodically flushes the downstream sink to amortize I/O calls.

func NewBufferedSink

func NewBufferedSink(size int, downstream LogSink) *BufferedSink

NewBufferedSink constructs a bounded queue backed sink. When the queue is full producers block until there is space, trading off log retention for back pressure.

func (*BufferedSink) Close

func (self *BufferedSink) Close()

func (*BufferedSink) Flush

func (self *BufferedSink) Flush()

func (*BufferedSink) IsEnabled

func (self *BufferedSink) IsEnabled(level int) bool

func (*BufferedSink) Log

func (self *BufferedSink) Log(when time.Time, level int, message string)

type ConsoleWriter

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

ConsoleWriter renders log lines to the process STDOUT. When STDOUT is detected as an interactive terminal it applies ANSI colors to warn and error messages.

func NewConsoleWriter

func NewConsoleWriter(minLevel int) *ConsoleWriter

NewConsoleWriter creates a console sink that only prints messages at or above the provided log level.

func (*ConsoleWriter) Close

func (self *ConsoleWriter) Close()

func (*ConsoleWriter) Flush

func (self *ConsoleWriter) Flush()

func (*ConsoleWriter) IsEnabled

func (self *ConsoleWriter) IsEnabled(level int) bool

func (*ConsoleWriter) Log

func (self *ConsoleWriter) Log(when time.Time, level int, message string)

type FileWriter

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

FileWriter appends log records to rolling log files on disk. Rotation occurs once the active file exceeds maxFileSize bytes.

func NewFileWriter

func NewFileWriter(filename string, maxSize int64) *FileWriter

NewFileWriter creates a writer that rotates when the file exceeds maxSize bytes. When filename is empty it derives the executable name automatically.

func (*FileWriter) Close

func (self *FileWriter) Close()

func (*FileWriter) Flush

func (self *FileWriter) Flush()

func (*FileWriter) IsEnabled

func (self *FileWriter) IsEnabled(level int) bool

func (*FileWriter) Log

func (self *FileWriter) Log(when time.Time, level int, message string)

non reentrant

type LogFormatter

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

LogFormatter marshals formatted log messages and forwards them to the sink. It optionally annotates records with caller file/line metadata.

func (*LogFormatter) Auditf

func (self *LogFormatter) Auditf(format string, a ...interface{})

func (*LogFormatter) Close

func (self *LogFormatter) Close()

func (*LogFormatter) Debugf

func (self *LogFormatter) Debugf(format string, a ...interface{})

func (*LogFormatter) Errorf

func (self *LogFormatter) Errorf(format string, a ...interface{})

func (*LogFormatter) Flush

func (self *LogFormatter) Flush()

func (*LogFormatter) Infof

func (self *LogFormatter) Infof(format string, a ...interface{})

func (*LogFormatter) IsEnabled

func (self *LogFormatter) IsEnabled(level int) bool

func (*LogFormatter) Log

func (self *LogFormatter) Log(when time.Time, level int, message string)

func (*LogFormatter) Warnf

func (self *LogFormatter) Warnf(format string, a ...interface{})

type LogSink

type LogSink interface {
	IsEnabled(level int) bool // reentrant
	Log(when time.Time, level int, message string)
	Flush()
	Close()
}

LogSink represents a destination for log records. Implementations are invoked by the thread-safe LogFormatter, so they do not need their own synchronization unless they perform internal background work. Non-blocking behavior is still encouraged to keep log calls responsive.

type Logger

type Logger interface {
	LogSink
	Debugf(format string, a ...interface{})
	Infof(format string, a ...interface{})
	Auditf(format string, a ...interface{})
	Warnf(format string, a ...interface{})
	Errorf(format string, a ...interface{})
}

Logger represents the public logging surface. All methods are concurrency-safe and forward to the wrapped LogSink implementation.

func GetDefaultLogger

func GetDefaultLogger() Logger

GetDefaultLogger returns the globally configured logger.

func NewDefaultForService

func NewDefaultForService() Logger

NewDefaultForService combines console and file sinks for long-running daemons.

func NewDefaultLogToConsole

func NewDefaultLogToConsole(minLevel int) Logger

NewDefaultLogToConsole returns a convenience logger that writes to STDOUT/STDERR using the ConsoleWriter with the supplied minimum log level.

func NewLogger

func NewLogger(sink LogSink, showFileLine bool) Logger

NewLogger constructs a thread-safe Logger around the provided sink. When showFileLine is true the resulting logger prepends caller information to each message, which is handy for troubleshooting utilities.

type MultiWriter

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

MultiWriter fans records out to two sinks. It is useful when the same log stream needs both a durable and an interactive destination.

func NewMultiWriter

func NewMultiWriter(first, second LogSink) MultiWriter

NewMultiWriter constructs a composite sink that duplicates log records to both provided sinks.

func (MultiWriter) Close

func (self MultiWriter) Close()

func (MultiWriter) Flush

func (self MultiWriter) Flush()

func (MultiWriter) IsEnabled

func (self MultiWriter) IsEnabled(level int) bool

func (MultiWriter) Log

func (self MultiWriter) Log(when time.Time, level int, message string)

type NopSink

type NopSink struct{}

NopSink discards every log message and reports all levels as disabled. It is primarily used to keep the global logger in a safe, inert state.

func (NopSink) Close

func (self NopSink) Close()

func (NopSink) Flush

func (self NopSink) Flush()

func (NopSink) IsEnabled

func (self NopSink) IsEnabled(level int) bool

func (NopSink) Log

func (self NopSink) Log(when time.Time, level int, message string)

Jump to

Keyboard shortcuts

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