s99logger

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 12 Imported by: 0

README

S99Logger

s99logger is a small structured Go logger built around typed events, human-readable console output, JSON logs, and optional localization.

Console logs are colored by default when writing to a terminal. JSON logs keep stable machine fields such as message_id and service.

Features

  • Typed app-owned events.
  • Console, JSON, and multi-sink in the core package.
  • Process-wide default logger with a one-call rotation.Configure setup.
  • Integrated i18n and log rotation.
  • Configurable console prefixes, service prefix, and colors.
  • Optional context as the last log argument for per-request language.
  • Translation coverage checks with Translator.Verify.

Install

go get github.com/smegg99/s99logger

Shape

Log calls are event-first. Context is optional and goes last when needed.

event := s99logger.NewEvent("server_starting", s99logger.Int("port", 8080))
logger.Info(event)
logger.Info(event, s99logger.LanguageContext("pl"))

For named app events, wrap NewEvent in a small function. For plural translations, use s99logger.NewPluralEvent.

Global logger

For apps that would rather not thread a *Logger through every call, the package keeps a process-wide default. rotation.Configure builds a console logger (plus a rotating JSON file sink when EnableFiles is set) and installs it; Close releases the file sink at shutdown.

if err := rotation.Configure(rotation.Config{
    Service:     "api",
    Level:       "info",
    EnableFiles: true,
    Directory:   "logs",
}); err != nil {
    panic(err)
}
defer s99logger.Close()

s99logger.Info(s99logger.NewEvent("server_starting", s99logger.Int("port", 8080)))

s99logger.Default() returns the installed logger when you need a *Logger value (e.g. to derive a request-scoped child with With), and SetDefault swaps it directly when you build sinks yourself. The default is usable before configuration: it writes to stderr at debug level.

Fatal logs at error level, releases the sinks so the record reaches disk, and exits with status 1. Deferred functions do not run, so keep it to startup failures the application cannot continue past.

Use examples/ for complete, runnable code.

Examples

Run any example with go run ./examples/name.

Example Shows
minimal console logging with NewEvent
global process-wide default logger via rotation.Configure
basic TOML translations with go-i18n
pluralization plural messages selected by event count
mixedformats JSON, TOML, and YAML locale files together
localizedprefixes language-specific console prefixes/colors
consoleprefixes custom console prefixes, colors, and service style
jsonstdout newline-delimited JSON
multisink console and JSON from one log call
rotatingfile optional rotation package for daily JSON files
scopedattrs Logger.With and Options.MinLevel
verifytranslations Translator.Verify coverage check
customsink implementing Sink

License

MIT

Documentation

Index

Constants

View Source
const (
	// ANSIReset clears ANSI formatting.
	ANSIReset = "\x1b[0m"
	// ANSIFaint dims text in terminals that support ANSI styling.
	ANSIFaint = "\x1b[2m"

	ANSIBlack   = "\x1b[30m"
	ANSIRed     = "\x1b[31m"
	ANSIGreen   = "\x1b[32m"
	ANSIYellow  = "\x1b[33m"
	ANSIBlue    = "\x1b[34m"
	ANSIMagenta = "\x1b[35m"
	ANSICyan    = "\x1b[36m"
	ANSIWhite   = "\x1b[37m"

	ANSIBrightBlack   = "\x1b[90m"
	ANSIBrightRed     = "\x1b[91m"
	ANSIBrightGreen   = "\x1b[92m"
	ANSIBrightYellow  = "\x1b[93m"
	ANSIBrightBlue    = "\x1b[94m"
	ANSIBrightMagenta = "\x1b[95m"
	ANSIBrightCyan    = "\x1b[96m"
	ANSIBrightWhite   = "\x1b[97m"
)

Variables

This section is empty.

Functions

func Close added in v1.0.1

func Close() error

Close releases the closers registered with the current default Logger. Call it during shutdown. It is safe to call more than once.

func ContextWithLanguage

func ContextWithLanguage(ctx context.Context, lang string) context.Context

ContextWithLanguage returns a copy of ctx carrying lang. When a Logger logs with this context, lang overrides Options.Language for that call, which makes per-request or per-user localization possible without a logger per language.

func Debug added in v1.0.1

func Debug(event Event, ctx ...context.Context)

Debug logs event at debug level on the default Logger.

func Error added in v1.0.1

func Error(event Event, ctx ...context.Context)

Error logs event at error level on the default Logger.

func Fatal added in v1.1.0

func Fatal(event Event, ctx ...context.Context)

Fatal logs event at error level on the default Logger, releases its sinks so the record reaches disk, and terminates the process with status 1. Deferred functions do not run; reserve it for startup failures the application cannot continue past.

func Info added in v1.0.1

func Info(event Event, ctx ...context.Context)

Info logs event at info level on the default Logger.

func LanguageContext

func LanguageContext(lang string) context.Context

LanguageContext returns a background context carrying lang.

func LanguageFromContext

func LanguageFromContext(ctx context.Context) (string, bool)

LanguageFromContext returns the language stored by ContextWithLanguage, and whether one was present (and non-empty).

func SetDefault added in v1.0.1

func SetDefault(l *Logger, sinkClosers ...io.Closer)

SetDefault installs l as the process-wide Logger. Any sinks that need cleanup at shutdown (such as file sinks) should be passed as sinkClosers; they are closed by Close. Closers registered by a previous SetDefault are closed here, so reconfiguring the logger releases the old file handles.

func Warn added in v1.0.1

func Warn(event Event, ctx ...context.Context)

Warn logs event at warn level on the default Logger.

Types

type Attr

type Attr struct {
	Key   string
	Value any
}

Attr is a single structured key/value pair attached to an event. Attrs are emitted in the log record and are also used as template data by translators.

func Any

func Any(key string, value any) Attr

Any returns an attribute with an arbitrary value.

func Bool

func Bool(key string, value bool) Attr

Bool returns a boolean attribute.

func Duration

func Duration(key string, value time.Duration) Attr

Duration returns a duration attribute. The duration renders as text (e.g. "1.5s") both in log output and in translation templates.

func Err

func Err(err error) Attr

Err returns an attribute carrying an error message under the "error" key.

func Int

func Int(key string, value int) Attr

Int returns an integer attribute.

func String

func String(key, value string) Attr

String returns a string attribute.

type ConsoleSink

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

ConsoleSink writes human-readable, optionally colored lines, suited for the terminal. Color is auto-enabled when the writer is a terminal. Level prefixes and colors can be customized, including per-language prefixes selected from each record's language. It is safe for concurrent use.

func NewConsoleSink

func NewConsoleSink(w io.Writer) *ConsoleSink

NewConsoleSink returns a ConsoleSink writing to w. Color is enabled only when w is a terminal.

func (*ConsoleSink) WithColor

func (s *ConsoleSink) WithColor(on bool) *ConsoleSink

WithColor forces color on or off, overriding terminal detection.

func (*ConsoleSink) WithFieldColor

func (s *ConsoleSink) WithFieldColor(color string) *ConsoleSink

WithFieldColor sets the ANSI color used for structured field keys. Empty color disables field-key coloring.

func (*ConsoleSink) WithLevelColor

func (s *ConsoleSink) WithLevelColor(level Level, color string) *ConsoleSink

WithLevelColor sets the default ANSI color for level. Empty color disables coloring for that level.

func (*ConsoleSink) WithLevelColors

func (s *ConsoleSink) WithLevelColors(colors map[Level]string) *ConsoleSink

WithLevelColors sets default ANSI colors for levels. Missing levels keep their existing color.

func (*ConsoleSink) WithLevelPrefix

func (s *ConsoleSink) WithLevelPrefix(level Level, prefix string) *ConsoleSink

WithLevelPrefix sets the default console prefix for level.

func (*ConsoleSink) WithLevelPrefixes

func (s *ConsoleSink) WithLevelPrefixes(prefixes map[Level]string) *ConsoleSink

WithLevelPrefixes sets default console prefixes. Missing levels keep their existing prefix.

func (*ConsoleSink) WithLocalizedLevelColor

func (s *ConsoleSink) WithLocalizedLevelColor(lang string, level Level, color string) *ConsoleSink

WithLocalizedLevelColor sets the ANSI color for level when a record uses lang. An empty lang configures the default color.

func (*ConsoleSink) WithLocalizedLevelColors

func (s *ConsoleSink) WithLocalizedLevelColors(lang string, colors map[Level]string) *ConsoleSink

WithLocalizedLevelColors sets ANSI colors for records using lang. Missing levels keep their existing color.

func (*ConsoleSink) WithLocalizedLevelPrefix

func (s *ConsoleSink) WithLocalizedLevelPrefix(lang string, level Level, prefix string) *ConsoleSink

WithLocalizedLevelPrefix sets the console prefix for level when a record uses lang. An empty lang configures the default prefix.

func (*ConsoleSink) WithLocalizedLevelPrefixes

func (s *ConsoleSink) WithLocalizedLevelPrefixes(lang string, prefixes map[Level]string) *ConsoleSink

WithLocalizedLevelPrefixes sets console prefixes for records using lang. Missing levels keep their existing prefix.

func (*ConsoleSink) WithServiceColor

func (s *ConsoleSink) WithServiceColor(color string) *ConsoleSink

WithServiceColor sets the ANSI color used for the service prefix. Empty color disables service-prefix coloring.

func (*ConsoleSink) WithServicePrefixStyle

func (s *ConsoleSink) WithServicePrefixStyle(open, close string) *ConsoleSink

WithServicePrefixStyle sets the strings around the service prefix. The default style renders service as [service].

func (*ConsoleSink) Write

func (s *ConsoleSink) Write(_ context.Context, rec Record) error

Write renders rec as a single human-readable line.

type Event

type Event interface {
	// MessageID returns the stable identifier for this event.
	MessageID() MessageID
	// Attrs returns the structured attributes for this event.
	Attrs() []Attr
	// PluralCount returns the count used for plural translation selection.
	// The boolean is false for events that are not pluralized.
	PluralCount() (int, bool)
}

Event is a typed log event. Most simple events can use NewEvent or NewPluralEvent; applications can still define structs implementing this interface when they want stronger domain types or custom behavior.

type JSONSink

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

JSONSink writes records as newline-delimited JSON to an io.Writer. It is safe for concurrent use.

func NewJSONSink

func NewJSONSink(w io.Writer) *JSONSink

NewJSONSink returns a JSONSink writing to w.

func (*JSONSink) Write

func (s *JSONSink) Write(_ context.Context, rec Record) error

Write encodes rec as a single JSON object followed by a newline.

type Level

type Level int

Level is the severity of a log record.

const (
	LevelDebug Level = iota
	LevelInfo
	LevelWarn
	LevelError
)

func ParseLevel added in v1.0.1

func ParseLevel(name string) Level

ParseLevel maps a case-insensitive level name to a Level, defaulting to LevelInfo for empty or unrecognized input. TRACE maps to debug; FATAL and PANIC map to error.

func (Level) String

func (l Level) String() string

String returns the lowercase name of the level, used in log output.

type Logger

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

Logger emits typed events to a Sink, optionally localizing them through a Translator. A Logger holds no global state and is safe for concurrent use as long as its Sink is.

func Default added in v1.0.1

func Default() *Logger

Default returns the process-wide Logger. It is never nil; before SetDefault is called it writes to stderr at debug level.

func New

func New(sink Sink, opts Options) *Logger

New returns a Logger that writes to sink using the given options. A nil sink discards records.

func With added in v1.0.1

func With(attrs ...Attr) *Logger

With returns a child of the default Logger that attaches attrs to every record it emits. It is a shorthand for Default().With and is handy for request- or scope-specific loggers. See Logger.With.

func (*Logger) Debug

func (l *Logger) Debug(event Event, ctx ...context.Context)

Debug logs an event at debug level.

func (*Logger) Error

func (l *Logger) Error(event Event, ctx ...context.Context)

Error logs an event at error level.

func (*Logger) Info

func (l *Logger) Info(event Event, ctx ...context.Context)

Info logs an event at info level.

func (*Logger) Warn

func (l *Logger) Warn(event Event, ctx ...context.Context)

Warn logs an event at warn level.

func (*Logger) With

func (l *Logger) With(attrs ...Attr) *Logger

With returns a child Logger that attaches attrs to every record it emits, in addition to each event's own attrs. The receiver is unchanged, so it is safe to derive request- or scope-specific loggers concurrently.

type MessageID

type MessageID string

MessageID is a stable, language-independent identifier for a log message. It is always emitted alongside the localized message, and is used as the fallback message when no translator is configured or translation fails.

type NoPlural

type NoPlural struct{}

NoPlural can be embedded in event structs that are not pluralized, so they satisfy Event without implementing PluralCount themselves.

func (NoPlural) PluralCount

func (NoPlural) PluralCount() (int, bool)

PluralCount reports that the event is not pluralized.

type Options

type Options struct {
	// Language is the default target language passed to the Translator. It can
	// be overridden per call with ContextWithLanguage.
	Language string
	// Service is the service name attached to every record.
	Service string
	// MinLevel is the lowest level that is logged; lower levels are dropped
	// before any translation or sink work. The zero value (LevelDebug) logs
	// everything.
	MinLevel Level
	// Translator localizes events. If nil, messages are the message id.
	Translator Translator
	// Clock supplies the record timestamp. If nil, time.Now is used.
	Clock func() time.Time
}

Options configures a Logger. The zero value is usable: Clock defaults to time.Now and Translator may be nil (messages fall back to the message id).

type Record

type Record struct {
	Time      time.Time
	Level     Level
	Service   string
	Lang      string
	MessageID MessageID
	Message   string
	Attrs     []Attr
}

Record is a fully resolved log entry handed to a Sink. Message holds the localized text (or the message id, when translation is unavailable), while MessageID always holds the stable identifier.

type SimpleEvent

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

SimpleEvent is a small immutable Event implementation for common log events. Use NewEvent or NewPluralEvent when a dedicated event struct would only repeat the message id and attrs.

func NewEvent

func NewEvent(id MessageID, attrs ...Attr) SimpleEvent

NewEvent returns a non-pluralized event with id and attrs.

func NewPluralEvent

func NewPluralEvent(id MessageID, count int, attrs ...Attr) SimpleEvent

NewPluralEvent returns an event whose count drives plural translation selection.

func (SimpleEvent) Attrs

func (e SimpleEvent) Attrs() []Attr

Attrs returns the structured attributes for this event.

func (SimpleEvent) MessageID

func (e SimpleEvent) MessageID() MessageID

MessageID returns the stable identifier for this event.

func (SimpleEvent) PluralCount

func (e SimpleEvent) PluralCount() (int, bool)

PluralCount returns the count used for plural translation selection.

func (SimpleEvent) With

func (e SimpleEvent) With(attrs ...Attr) SimpleEvent

With returns a copy of e with attrs appended.

func (SimpleEvent) WithPluralCount

func (e SimpleEvent) WithPluralCount(count int) SimpleEvent

WithPluralCount returns a copy of e marked as pluralized with count.

type Sink

type Sink interface {
	Write(ctx context.Context, rec Record) error
}

Sink writes resolved log records to a destination. Implementations must be safe for concurrent use. The returned error is for the sink's own use (e.g. custom sinks and tests); the Logger discards it, like slog.

func MultiSink

func MultiSink(sinks ...Sink) Sink

MultiSink returns a Sink that writes each record to every given sink. This is the usual way to send colored lines to the terminal and JSON to a file at the same time. Sink errors are joined; the Logger discards them anyway.

type Translator

type Translator interface {
	Translate(ctx context.Context, lang string, event Event) (string, error)
}

Translator turns a typed event into a localized message for a language. It is implemented outside this package (e.g. by the i18n adapter) so that this package never depends on any translation library.

When Translate returns an error, the Logger still emits the record, falling back to the event's MessageID as the message.

Directories

Path Synopsis
examples
basic command
consoleprefixes command
examples/consoleprefixes/main.go
examples/consoleprefixes/main.go
customsink command
global command
examples/global/main.go
examples/global/main.go
internal/sampleevents
examples/internal/sampleevents/events.go
examples/internal/sampleevents/events.go
jsonstdout command
localizedprefixes command
examples/localizedprefixes/main.go
examples/localizedprefixes/main.go
minimal command
mixedformats command
multisink command
examples/multisink/main.go
examples/multisink/main.go
pluralization command
examples/pluralization/main.go
examples/pluralization/main.go
rotatingfile command
examples/rotatingfile/main.go
examples/rotatingfile/main.go
scopedattrs command
examples/scopedattrs/main.go
examples/scopedattrs/main.go
verifytranslations command
examples/verifytranslations/main.go
examples/verifytranslations/main.go
Package i18n is the official go-i18n adapter for s99logger.
Package i18n is the official go-i18n adapter for s99logger.
Package rotation provides optional timberjack-backed JSON log rotation for s99logger.
Package rotation provides optional timberjack-backed JSON log rotation for s99logger.

Jump to

Keyboard shortcuts

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