logstox

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 9, 2025 License: Apache-2.0 Imports: 4 Imported by: 1

README

logstox

A small logging facade and hub: log anywhere, route everywhere, zero lock-in. Keep your stack; fits beside any logger.

[!WARNING]

This project is currently in its very early stages and is subject to volatile changes until this notice is removed.

This project is also a learning experience since there are several concepts and technologies I want to explore that aren't my expertise... yet 😏

TL;DR: this whole thing is a WIP :shipit:

This README will be filled out with further details as the project progresses.

Why logstox?

What it is:

  • A tiny logging facade: one small, stable interface across projects.
  • Drop-in: sits beside whichever logger you use today (zap, slog, stdlib), or want to use tomorrow.
  • An optional hub that can fan-out entries to multiple data sinks (files, s3, http).
  • A handful of sane defaults and helpers such that you don't need to write a bespoke app-local module from scratch everytime.

What it isn't:

  • Not a "unify every feature" abstraction.
  • Not sticky -- zero lock-in and escape hatches to the underlying logger.
  • Not an exhaustive list of backend providers -- you can write your own (perhaps contribute it?).

Ideology

  • Keep the surface small (easy to learn, hard to misuse, impossible to wrangle with).
  • Choose backends freely, keep call sites unchanged.
  • Route logs anywhere via a separate hub/ fan-out layer (files, s3, http) without touching call sites.

FAQ

  • Q: Does this bloat my binary?

    A: No. Go links only what you import. If you import logstox and provider/zapx, you don't "pay" for slogx or data sinks you don't import.

  • Q: Why not wrap every feature of zap/ slog?

    A: Scope creep and potential lock-in. This facade exposes only the common path; escape hatches let you drop down to the underlying logger when needed.

    Your app-local wrapper will leverage this facade and can tailor the interface to suit your needs rather than forcing it on everyone.

    That said, if there is enough demand, we can explore expanding the standard layer.

Roadmap (preview)

This is not a comprehensive outline nor necessarily the order of priorities but it's currently the way I'll tackle this project (subject to change):

  • Stellar README.
  • Core standardized interfaces.
  • Core standardized fields.
  • Implement adapter functionality to be able to convert for standard.
  • Add logging backend provider (eg zap).
  • Add stdlib backend provider.
  • Data sink: jsonl encoder, file sink.
  • Data sink: s3 sink?
  • Examples.

Contributing

Bug reports and PRs are welcome. Please open an issue first for discussion.

Keep the core surface minimal: avoid adding provider-specific concepts to the facade unless they belong in the standard interface. This should be clear through a conversation in an issue.

Feel free to open an issue if you spot something iffy or have a hot tip 🤷

License

Apache-2.0. See LICENSE. If applicable, see NOTICE.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Backend

type Backend[FT any] interface {
	New(Options[FT]) Logger[FT]
}

Backend builds a Logger from Options all parameterized by the field type FT. Backends live in subpackages (eg backend/zapx, backend/slogx). Or consumers roll out their custom backend.

type Level

type Level int8

Level is an implementation-agnostic log severity. Higher numbers are more severe. The zero value is InfoLevel.

const (
	// DebugLevel enables verbose diagnostic output, usually disabled in production.
	DebugLevel Level = -1
	// InfoLevel describes normal application operations (default).
	InfoLevel Level = 0
	// WarnLevel indicates unusual conditions that may need attention, but don't need individual human review.
	WarnLevel Level = 1
	// ErrorLevel records unexpected errors. If an application is running smoothly, it shouldn't generate any
	// error-level logs.
	ErrorLevel Level = 2
	// DPanicLevel is intended for development-only severe errors
	// (often treated like Panic in dev and Error in prod by loggers).
	DPanicLevel Level = 3
	// PanicLevel is intended for errors after which a logger will panic.
	PanicLevel Level = 4
	// FatalLevel is intended for errors after which a logger will exit.
	FatalLevel Level = 5
)

func ParseLevel

func ParseLevel(s string) (Level, error)

ParseLevel parses s (case-insensitive, leading/trailing spaces ignored) into a Level.

func (Level) MarshalText

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

MarshalText implements encoding.TextMarshaler.

func (Level) String

func (l Level) String() string

String implements fmt.Stringer, returning the lower-case name of the log level.

func (*Level) UnmarshalText

func (l *Level) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler.

func (Level) Valid

func (l Level) Valid() bool

Valid reports whether l is one of the defined levels.

type LevelCheck

type LevelCheck interface {
	Enabled(Level) bool
}

LevelCheck is an optional extension that reports if a level is enabled. Backends that can answer cheaply may implement this.

type Logger

type Logger[FT any] interface {
	// DEBUG (-1): for recording messages useful for debugging.
	Debug(string, ...FT)
	// INFO (0): for messages describing normal application operations.
	Info(string, ...FT)
	// WARN (1): for recording messages indicating something unusual happened that may need attention before it escalates to a more severe issue.
	Warn(string, ...FT)
	// ERROR (2): for recording unexpected error conditions in the program.
	Error(string, ...FT)
	// DPANIC (3): for recording severe error conditions in development. It behaves like PANIC in development and ERROR in production.
	DPanic(string, ...FT)
	// PANIC (4): calls panic() after logging an error condition.
	Panic(string, ...FT)
	// FATAL (5): calls os.Exit(1) after logging an error condition.
	Fatal(string, ...FT)

	// With creates a child logger and adds structured context to it. Fields added
	// to the child don't affect the parent, and vice versa. Any fields that
	// require evaluation (such as Objects) are evaluated upon invocation of With.
	With(...FT) Logger[FT]
	// Named adds a new path segment to the logger's name. Segments are joined by
	// periods. By default, Loggers are unnamed.
	Named(string) Logger[FT]
	// Sync calls the underlying Core's Sync method, flushing any buffered log
	// entries. Applications should take care to call Sync before exiting.
	Sync() error
}

type Options

type Options[FT any] struct {
	Level      Level     // minimum level to record
	AddSource  bool      // include file:line when supported
	Name       string    // initial logger scope
	Writer     io.Writer // preferred sink (backend may ignore)
	TimeLayout string    // eg time.RFC3339Nano (backend may ignore)
	Fields     []FT      // default fields for the base logger
}

Options are hints used by a Backend when constructing a Logger. Backends may choose to ignore some fields.

Directories

Path Synopsis
backend
zapx module

Jump to

Keyboard shortcuts

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