Help us shape the future of Go! Take the 2026 Go Developer Survey

zslogfx

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Sep 17, 2026 License: MIT Imports: 14 Imported by: 0

README

zslogfx

CI Go Reference

A JSON log/slog logger backed by zap, with global slog.Default installation and Uber Fx lifecycle management.

Installation

go get github.com/uchaloop/zslogfx

Fx

fx.New(
	confx.Module(),
	confx.Provide[zslogfx.Config](),
	zslogfx.Module(),
).Run()

Config names its default instance log, which gives the prefix, so it reads LOG_LEVEL and the rest of LOG_*:

LOG_LEVEL=info
LOG_BUFFER_ENABLED=false

After installation, use the standard package-level API anywhere:

slog.Info("service started", "port", 8080)
slog.Error("request failed", "error", err)

The same *slog.Logger is also available through Fx dependency injection.

A Config assembled in Go works just as well, for a tool that reads no environment at all:

fx.New(
	fx.Supply(zslogfx.Config{Level: "info"}),
	zslogfx.Module(),
)

Configuration

Under the log instance name:

Variable Type Empty means
LOG_LEVEL string zap decides
LOG_CALLER_ENABLED bool on at debug level, off otherwise
LOG_BUFFER_ENABLED bool buffering off
LOG_BUFFER_SIZE int the zap default
LOG_BUFFER_FLUSH_INTERVAL duration the zap default

Nothing is required: a logger with no configuration at all is a working logger. confmaker.Manifest[zslogfx.Config]() lists the same set from the type itself.

Fields and options

Add fields resolved from the Fx container:

zslogfx.AsOptions(
	func(build BuildInfo) zslogfx.Option {
		return zslogfx.WithFields(
			slog.String("service.version", build.Version),
		)
	},
)

Static options can be supplied directly:

fx.Supply(
	zslogfx.WithFields(
		slog.String("service.name", "orders"),
	),
)

Available options include:

  • WithLevel
  • WithCaller
  • WithStacktraceLevel
  • WithFields
  • WithWriteSyncer
  • WithBuffer
  • WithoutBuffer

Without Fx:

logger, err := zslogfx.Make(cfg, opts...)
if err != nil {
	return err
}
defer logger.Close()

logger.Slog.Info("service started")

Output

Records are JSON with fields suitable for OpenSearch:

@timestamp
log.level
log.logger
message
caller
error.stack_trace

Durations are encoded as milliseconds. Values implementing slog.LogValuer, including secret.Secret, control their own representation.

Buffering

Buffering is disabled by default. Enable it through configuration or:

zslogfx.WithBuffer(4*1024*1024, time.Second)

Buffered records are flushed on graceful Fx shutdown. Abrupt termination can lose records that have not yet been flushed, so enable buffering only when its throughput benefit is needed.

Acknowledgements

I am grateful to the authors of zap, its zapslog bridge, and Uber Fx. Their work made this library possible.

License

MIT

Documentation

Overview

Package zslogfx builds a standard log/slog logger backed by zap and wires its ownership into an Uber Fx application.

Services use a plain *slog.Logger; zap is only the fast JSON backend, through Uber's official go.uber.org/zap/exp/zapslog handler. The output is one fixed JSON format, ECS-aligned for OpenSearch. Module installs the logger as slog.Default so any code can log without receiving it as an argument, and also provides it for explicit injection. Writes are unbuffered by default; buffering is opt-in.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AsOptions

func AsOptions(ctors ...any) fx.Option

AsOptions provides Option constructors to Module through an Fx value group. Constructors may depend on any other values in the Fx graph.

func Module

func Module() fx.Option

Module installs one application logger as slog.Default, provides *Logger and *slog.Logger, routes Fx events through it, and closes it on application shutdown.

The logger is constructed before any application component: fx.WithLogger and the eager fx.Invoke below both depend on it, so slog.Default is installed during fx.New - before OnStart hooks and application code run. This makes the logging sequence deterministic: no component logs before the logger is ready.

Module must be passed at the fx.New root because fx.WithLogger is scoped to the scope it is declared in.

Types

type BufferConfig

type BufferConfig struct {
	Enabled       bool          `env:"ENABLED"`
	Size          int           `env:"SIZE"`
	FlushInterval time.Duration `env:"FLUSH_INTERVAL"`
}

BufferConfig controls optional write buffering. Buffering is disabled by default. Size and FlushInterval use zap defaults when left at zero.

type CallerConfig

type CallerConfig struct {
	Enabled *bool `env:"ENABLED"`
}

CallerConfig controls caller annotations. Unless Enabled is explicitly set, caller annotations are enabled at debug level and disabled otherwise.

type Config

type Config struct {
	Level  string       `env:"LEVEL"`
	Caller CallerConfig `envPrefix:"CALLER_"`
	Buffer BufferConfig `envPrefix:"BUFFER_"`
}

Config is the serializable logger configuration.

The tags are deliberately passive: zslogfx does not read the environment. Applications may fill Config with github.com/uchaloop/confmaker, another configuration library, or plain Go code.

func (Config) ConfigName added in v0.3.1

func (Config) ConfigName() string

ConfigName is the default instance name, "log": a loader such as confmaker reads LOG_LEVEL and the rest of LOG_* unless the application names the instance itself.

func (Config) Validate

func (c Config) Validate() error

Validate checks values that can be validated independently of runtime Options. It is called automatically by confmaker, and reports every problem at once rather than the first: a deployment is fixed in a config map and rolled out, so one report is one round trip.

type Logger

type Logger struct {
	Slog *slog.Logger
	// contains filtered or unexported fields
}

Logger owns the slog view of the logging core and the resources behind it. zap is only the backend; the logger a service uses is a plain *slog.Logger.

Close is safe to call more than once. Fx applications normally do not need to call it directly; Module registers it with the application lifecycle.

func Make

func Make(cfg Config, opts ...Option) (*Logger, error)

Make builds a logger without installing it as slog.Default.

func (*Logger) Close

func (l *Logger) Close() error

Close flushes pending records and stops buffer resources, when enabled.

type Option

type Option func(*settings)

Option customizes logger construction after Config has been applied.

func WithBuffer

func WithBuffer(size int, flushInterval time.Duration) Option

WithBuffer enables the built-in buffer. Zero values select the defaults: 4 MiB and a one-second flush interval.

func WithCaller

func WithCaller(enabled bool) Option

WithCaller overrides Config.Caller.Enabled.

func WithFields

func WithFields(attrs ...slog.Attr) Option

WithFields adds slog attributes to every record.

func WithLevel

func WithLevel(level string) Option

WithLevel overrides Config.Level.

func WithStacktraceLevel

func WithStacktraceLevel(level slog.Level) Option

WithStacktraceLevel adds a stack trace to records at or above level.

func WithWriteSyncer

func WithWriteSyncer(ws zapcore.WriteSyncer) Option

WithWriteSyncer replaces stdout as the destination. A nil syncer is ignored (stdout stays the default). It does not enable the built-in buffer; wrap the destination yourself when custom buffering is required.

func WithoutBuffer

func WithoutBuffer() Option

WithoutBuffer disables buffering even when Config enables it.

Jump to

Keyboard shortcuts

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