Skip to content

Repository files navigation

rlog

Go Reference

rlog is a small, fast logger for services and command-line tools that need bounded asynchronous delivery of unstructured text logs. It deliberately targets a narrow set of use cases instead of providing a configurable logging framework.

Installation

go get github.com/gavriva/rlog

InfoF and the other capital-F methods use github.com/gavriva/format, which is pulled in as a module dependency.

Quick start

package main

import "github.com/gavriva/rlog"

func main() {
	file := rlog.NewBufferedSink(
		3000,
		rlog.NewFileSink("service", 100e6, 3),
		false,
	)
	console := rlog.NewBufferedSink(
		200,
		rlog.NewConsoleSink(),
		true,
	)

	log := rlog.NewLogger(rlog.NewMultiSink(
		file,
		console,
		rlog.LevelDebug,
		rlog.LevelWarn,
	), true)
	defer log.Close()

	log.InfoF("listening on {}:{}", "127.0.0.1", 8080)
}

Each terminal sink has its own BufferedSink. This allows the file and console workers to consume their queues independently.

Logging APIs

Each level has three forms:

log.Infof("connected to %s in %v", host, elapsed) // fmt.Printf syntax
log.InfoF("connected to {} in {}", host, elapsed) // format.Format syntax
log.Info(func(dst []byte) []byte {                 // direct append path
	dst = append(dst, "connected to "...)
	dst = append(dst, host...)
	return dst
})

The package also exposes the same methods through a global default logger. Use SetDefaultLogger to install it and rlog.Close() during shutdown. SetDefaultLogger closes the previous logger and panics when passed nil or the logger that is already current. Package-level Err reports only the current default logger; replacing or closing it forgets errors from the previous one.

Sinks and concurrency

FileSink and ConsoleSink are sequential terminal sinks. Concurrent logging requires a BufferedSink before every terminal sink. MultiSink does not serialize its destinations, so the recommended topology is:

Logger
  └─ MultiSink
       ├─ BufferedSink ─ FileSink
       └─ BufferedSink ─ ConsoleSink

BufferedSink owns a bounded queue and a single downstream worker. When its queue is full, dropWhenFull=false blocks the producer and dropWhenFull=true drops the new record. It also flushes downstream periodically. Logger.Flush waits for records queued before the flush request; Logger.Close drains the queue and closes downstream.

MultiSink routes a record independently to destinations whose minimum level is satisfied. A record below both thresholds is discarded.

DropSink discards all records and is useful for disabling logging without special cases in application code.

File output and errors

NewFileSink(baseName, maxSize, maxFiles) writes to baseName.log and rotates older files to baseName.log.1, baseName.log.2, and so on. maxFiles includes the active file; use 1 to disable rotation. maxSize is clamped to the range 10 MB through 100 GB. An empty baseName derives the name from the executable.

Opening is lazy. An open, write, or flush failure stores the first error, reports it once to standard error, stops repeated I/O attempts for five seconds, and then retries when another record arrives. Records received during the backoff are discarded. A failure while removing or renaming rotated files permanently disables the sink. Failure to create or inspect the new active file after rotation does the same. Rotation errors are not retried automatically. Logger.Err() returns the first stored sink error, including through buffered and multi-sink compositions, and remains non-nil after successful I/O recovery.

ConsoleSink writes colored output to standard output when attached to a terminal. Console output is best effort: write errors are intentionally ignored and are not returned by Logger.Err().

Event timestamps

NewEventTimeLogger returns a logger and a timestamp setter. It is intended for replaying or processing events whose source time should be written instead of wall-clock time. Until the setter is called, records use the Unix epoch. The setter may run concurrently with logging.

Presets

The package includes three opinionated default-logger presets:

  • EnableDefaultLoggerForUtility logs debug and above to a blocking file queue, and audit and above to a dropping console queue.
  • EnableDefaultLoggerForService uses the same file policy and emits warn and above to the console.
  • EnableDefaultLoggerForLogServer uses only buffered file output.

Performance

The hot paths reuse records and byte buffers. The append-callback API avoids general-purpose formatting, while the capital-F API uses github.com/gavriva/format. Run the repository benchmarks on the target machine:

go test -run '^$' -bench . -benchmem ./...

Non-goals

rlog intentionally does not provide structured fields, configuration files, arbitrary user-defined sinks, hooks, or a general logging abstraction. Sink implementations and the pooled record protocol remain private so the package can keep its contracts small and its hot paths predictable.

About

Fast, lightweight Go logger for bounded asynchronous delivery of unstructured text logs.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages