circularlogger

package module
v0.0.0-...-54deaf7 Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2025 License: GPL-3.0 Imports: 10 Imported by: 0

README

CircularLogger: A Thread-Safe Circular Buffer Logger for Go

Description

CircularLogger is a Go package that provides a thread-safe logging mechanism using a circular buffer. It is designed to store a fixed number of log entries, making it ideal for applications where memory usage needs to be controlled. The logger supports multiple log levels (TRACE, INFO, WARN, FATAL), optional file and line information, and customizable log formatting, including JSON output.

Motivation

I want to be able to log within packages. The standard to build go apps should be to write packages and one or more simple "mains" in cmd/... I like this approach but logging was always a bit of a painpoint since writing somewhere would need to make assumptions I don't want make when in package. Storing in memory creates the risk that it will be hogging a potentially infinite amount of ram depending on how its used. A circular buffer will never take more than what has initially been assigned to it. You decide how many entries you want to keep.

Features

  • Thread-safe logging
  • Circular buffer to limit the number of stored logs
  • Support for log levels: TRACE, INFO, WARN, FATAL
  • Optional inclusion of file name and line number in logs
  • Customizable log formatting, including JSON
  • Methods for formatted logging (e.g., Infof, Warnf)

Installation

To use CircularLogger in your Go project, first ensure your project is set up as a Go module:

go get codeberg.org/slaxor/circularlogger

Usage

In your package you can do this:

package thefoo

import (
	"codeberg.org/slaxor/circularlogger"
)

var log = circularlogger.NewCircularLogger(10)
var Log = log

func init() {
	log.SetShortFile(true)                         // Enable file and line info
	log.SetFormatter(circularlogger.AnsiFormatter) // Color lines
	log.SetLevel(circularlogger.DEBUG)             // Log debug or more severe
}

func Foo(s string) {
	log.Debugf("called Foo(%q)", s)
}

And then in your main:

package main

import (
	"fmt"
	"thefoo"
)

func main() {
	thefoo.Foo("bar")
	fmt.Print(thefoo.Log.String())
}

A nice trick to do realtime logging is:

package main

import (
	"context"
	"thefoo"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	thefoo.Log.Watch(ctx)
	for i := range 12 {
		thefoo.Foo("bar")
		thefoo.Log.Infof("% 2d", i)
	}
}

License

This is free software it can be used in any way the Gnu General Public License allows. You may want to have a look at it here

Documentation

Overview

CircularLogger: A Thread-Safe Circular Buffer Logger for Go

## Description CircularLogger is a Go package that provides a thread-safe logging mechanism using a circular buffer. It is designed to store a fixed number of log entries, making it ideal for applications where memory usage needs to be controlled. The logger supports multiple log levels (TRACE, INFO, WARN, FATAL), optional file and line information, and customizable log formatting, including JSON output.

## Motivation I want to be able to log within packages. The standard to build go apps should be to write packages and one or more simple "mains" in cmd/... I like this approach but logging was always a bit of a painpoint since writing somewhere would need to make assumptions I don't want make when in package. Storing in memory creates the risk that it will be hogging a potentially infinite amount of ram depending on how its used. A circular buffer will never take more than what has initially been assigned to it. You decide how many entries you want to keep.

## Features - Thread-safe logging - Circular buffer to limit the number of stored logs - Support for log levels: TRACE, INFO, WARN, FATAL - Optional inclusion of file name and line number in logs - Customizable log formatting, including JSON - Methods for formatted logging (e.g., Infof, Warnf)

## Installation To use CircularLogger in your Go project, first ensure your project is set up as a Go module: ```sh go get codeberg.org/slaxor/circularlogger ``` ## Usage

In your package you can do this: ```go package thefoo

import (

"codeberg.org/slaxor/circularlogger"

)

var log = circularlogger.NewCircularLogger(10) var Log = log

func init() {
	log.SetShortFile(true)                         // Enable file and line info
	log.SetFormatter(circularlogger.AnsiFormatter) // Color lines
	log.SetLevel(circularlogger.DEBUG)             // Log debug or more severe
}
func Foo(s string) {
	log.Debugf("called Foo(%q)", s)
}

```

And then in your main: ```go package main

import (

"fmt"
"thefoo"

)

func main() {
	thefoo.Foo("bar")
	fmt.Print(thefoo.Log.String())
}

```

A nice trick to do realtime logging is:

```go package main

import (

"context"
"thefoo"

)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	thefoo.Log.Watch(ctx)
	for i := range 12 {
		thefoo.Foo("bar")
		thefoo.Log.Infof("% 2d", i)
	}
}

```

Index

Examples

Constants

View Source
const (
	FATAL = Level(iota)
	ERROR
	WARN
	INFO
	DEBUG
	TRACE
)

Variables

This section is empty.

Functions

func AnsiFormatter

func AnsiFormatter(entry LogEntry) string

func DefaultFormatter

func DefaultFormatter(entry LogEntry) string

DefaultFormatter is the Formatter that is used if none was defined

func JSONFormatter

func JSONFormatter(entry LogEntry) string

JSONFormatter formats a LogEntry as a JSON string

func Redact

func Redact(msg string) string

Types

type CircularLogger

type CircularLogger struct {
	Formatter Formatter
	// contains filtered or unexported fields
}

CircularLogger is a thread-safe circular buffer for logging

Example
log := NewCircularLogger(10)
log.SetShortFile(true)          // Enable file and line info
log.SetFormatter(JSONFormatter) // Optional: for line-by-line JSON in String()

log.Info("Starting application")
log.Warnf("Value is %d", 42)

fmt.Println("Line-by-line output:")
fmt.Print(log.String())

fmt.Println("\nJSON array output:")
js, err := json.Marshal(log.GetLogs())
if err != nil {
	log.Fatalf("%s", err)
}
fmt.Printf("%s", js)

func NewCircularLogger

func NewCircularLogger(capacity int) *CircularLogger

Update NewCircularLogger to initialize the channel

func (*CircularLogger) Debug

func (cl *CircularLogger) Debug(message string)

Debug logs a message at DEBUG level

func (*CircularLogger) Debugf

func (cl *CircularLogger) Debugf(format string, args ...any)

Debugf logs a formatted message at DEBUG level

func (*CircularLogger) Error

func (cl *CircularLogger) Error(message string)

Error logs a message at ERROR level

func (*CircularLogger) Errorf

func (cl *CircularLogger) Errorf(format string, args ...any)

Errorf logs a formatted message at ERROR level

func (*CircularLogger) Fatal

func (cl *CircularLogger) Fatal(message string)

Fatal logs a message at FATAL level and exits the program

func (*CircularLogger) Fatalf

func (cl *CircularLogger) Fatalf(format string, args ...any)

Fatalf logs a formatted message at FATAL level and exits the program

func (*CircularLogger) GetLogs

func (cl *CircularLogger) GetLogs() []LogEntry

GetLogs returns all current log entries in order

func (*CircularLogger) Info

func (cl *CircularLogger) Info(message string)

Info logs a message at INFO level

func (*CircularLogger) Infof

func (cl *CircularLogger) Infof(format string, args ...any)

Infof logs a formatted message at INFO level

func (*CircularLogger) Log

func (cl *CircularLogger) Log(message string)

Log adds a message to the circular buffer (for compatibility)

func (*CircularLogger) SetFormatter

func (cl *CircularLogger) SetFormatter(formatter Formatter)

SetFormatter sets a custom formatter function for log entries

func (*CircularLogger) SetLevel

func (cl *CircularLogger) SetLevel(l Level)

SetShortFile enables or disables including file and line information in logs

func (*CircularLogger) SetShortFile

func (cl *CircularLogger) SetShortFile(enabled bool)

SetShortFile enables or disables including file and line information in logs

func (*CircularLogger) String

func (cl *CircularLogger) String() string

String returns a formatted string of all log entries

func (*CircularLogger) Trace

func (cl *CircularLogger) Trace(message string)

Trace logs a message at TRACE level

func (*CircularLogger) Tracef

func (cl *CircularLogger) Tracef(format string, args ...any)

Tracef logs a formatted message at TRACE level

func (*CircularLogger) Warn

func (cl *CircularLogger) Warn(message string)

Warn logs a message at WARN level

func (*CircularLogger) Warnf

func (cl *CircularLogger) Warnf(format string, args ...any)

Warnf logs a formatted message at WARN level

func (*CircularLogger) Watch

func (cl *CircularLogger) Watch(ctx context.Context)

Watch adds a watcher that runs as a goroutine

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
log.Watch(ctx)

type Formatter

type Formatter func(entry LogEntry) string

Formatter is a function type for custom log formatting

type Level

type Level int

func ParseLevel

func ParseLevel(s string) (Level, error)

func (Level) MarshalJSON

func (l Level) MarshalJSON() ([]byte, error)

func (Level) String

func (l Level) String() string

func (*Level) UnmarshalJSON

func (l *Level) UnmarshalJSON(bs []byte) error

type LogEntry

type LogEntry struct {
	Timestamp time.Time `json:"timestamp"`
	Level     Level     `json:"level"`
	File      string    `json:"file,omitempty"`
	Line      int       `json:"line,omitempty"`
	Message   string    `json:"message"`
}

LogEntry represents a single log entry with timestamp, level, message, and optional file info. A word of caution: The file:line info is really costly (~10 times). So if performance is an issue consider perhaps not using it.

Jump to

Keyboard shortcuts

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