Documentation
¶
Overview ¶
Package srog is a structured logger built on zerolog that speaks Serilog's message-template language. Named holes in a template become typed structured fields, while an optional human-readable message is rendered alongside them:
log := srog.MustNew(srog.WithConsole())
log.Information("User {Username} logged in from {IP}", "neo", "10.0.0.1")
A logger fans out to any number of sinks, each with its own format and level — for example pretty console plus rotated JSON files that Fluent Bit can tail:
log, err := srog.New(
srog.WithConsole(srog.MinLevel(srog.DebugLevel)),
srog.WithFile("/var/log/app.log",
srog.MinLevel(srog.InformationLevel),
srog.Rotate(srog.Rotation{MaxSizeMB: 100, MaxBackups: 10, Compress: true, Every: srog.Daily}),
),
)
defer log.Close()
The API mirrors Serilog (Verbose/Debug/Information/Warning/Error/Fatal and ForContext) while keeping zerolog's zero-allocation event model underneath.
Index ¶
- Constants
- func AddContextField(fn ContextFieldFunc)
- func Debug(tmpl string, args ...any)
- func DebugCtx(ctx context.Context, tmpl string, args ...any)
- func Error(err error, tmpl string, args ...any)
- func ErrorCtx(ctx context.Context, err error, tmpl string, args ...any)
- func Fatal(err error, tmpl string, args ...any)
- func FatalCtx(ctx context.Context, err error, tmpl string, args ...any)
- func Info(tmpl string, args ...any)
- func InfoCtx(ctx context.Context, tmpl string, args ...any)
- func Information(tmpl string, args ...any)
- func InformationCtx(ctx context.Context, tmpl string, args ...any)
- func NewContext(ctx context.Context, l *Logger) context.Context
- func NewID() string
- func RegisterSinkType(name string, factory SinkFactory)
- func SetDefault(l *Logger)
- func Verbose(tmpl string, args ...any)
- func VerboseCtx(ctx context.Context, tmpl string, args ...any)
- func Warning(tmpl string, args ...any)
- func WarningCtx(ctx context.Context, tmpl string, args ...any)
- type Config
- type ContextFieldFunc
- type Field
- type Format
- type Interval
- type Level
- type Logger
- func Ctx(ctx context.Context) *Logger
- func Default() *Logger
- func ForContext(name string, value any) *Logger
- func FromContext(ctx context.Context) *Logger
- func MustNew(opts ...Option) *Logger
- func New(opts ...Option) (*Logger, error)
- func NewConsole() *Logger
- func NewFromConfig(c Config) (*Logger, error)
- func NewFromConfigFile(path string) (*Logger, error)
- func (l *Logger) Close() error
- func (l *Logger) Debug(tmpl string, args ...any)
- func (l *Logger) Enabled(level Level) bool
- func (l *Logger) Error(err error, tmpl string, args ...any)
- func (l *Logger) Fatal(err error, tmpl string, args ...any)
- func (l *Logger) ForContext(name string, value any) *Logger
- func (l *Logger) ForContextValues(fields map[string]any) *Logger
- func (l *Logger) Info(tmpl string, args ...any)
- func (l *Logger) Information(tmpl string, args ...any)
- func (l *Logger) IntoContext(ctx context.Context) context.Context
- func (l *Logger) Named(service string) *Logger
- func (l *Logger) Verbose(tmpl string, args ...any)
- func (l *Logger) Warning(tmpl string, args ...any)
- func (l *Logger) WithLevel(level Level) *Logger
- func (l *Logger) WithStackTrace(on bool) *Logger
- type Option
- func WithCaller(on bool) Option
- func WithConsole(opts ...SinkOption) Option
- func WithErrorHandler(fn func(error)) Option
- func WithFile(path string, opts ...SinkOption) Option
- func WithLevel(l Level) Option
- func WithRenderedMessage(on bool) Option
- func WithSampling(s Sampler) Option
- func WithStackTrace(on bool) Option
- func WithTimeFormat(layout string) Option
- func WithTimestamp(on bool) Option
- func WithWriter(w io.Writer, opts ...SinkOption) Option
- type Rotation
- type RotationSpec
- type Sampler
- type SinkFactory
- type SinkOption
- type SinkSpec
Constants ¶
const ( // TimeRFC3339 is ISO 8601 with second precision — the default layout. TimeRFC3339 = time.RFC3339 // TimeRFC3339Nano is ISO 8601 with nanosecond precision. TimeRFC3339Nano = time.RFC3339Nano // TimeDateTime is "2006-01-02 15:04:05" — a human-friendly datetime. TimeDateTime = time.DateTime // TimeDateOnly is "2006-01-02". TimeDateOnly = time.DateOnly // TimeOnly is "15:04:05". TimeOnly = time.TimeOnly // TimeKitchen is "3:04PM". TimeKitchen = time.Kitchen // TimeUnix emits epoch seconds as a JSON number. TimeUnix = zerolog.TimeFormatUnix // TimeUnixMs emits epoch milliseconds as a JSON number. TimeUnixMs = zerolog.TimeFormatUnixMs // TimeUnixMicro emits epoch microseconds as a JSON number. TimeUnixMicro = zerolog.TimeFormatUnixMicro // TimeUnixNano emits epoch nanoseconds as a JSON number. TimeUnixNano = zerolog.TimeFormatUnixNano )
Common timestamp layouts for WithTimeFormat. The first group are ISO/Go time layouts rendered as JSON strings; the epoch group re-exports zerolog's sentinels (emitted as JSON numbers) so callers need not import zerolog.
const StackFieldName = stackFieldName
StackFieldName is the exported name of the field under which srog stores a captured stack trace, and which console sinks pretty-print. Integrations that capture their own stack (for example panic recovery, where the useful frames only exist at recover time) should attach it under this key.
Variables ¶
This section is empty.
Functions ¶
func AddContextField ¶
func AddContextField(fn ContextFieldFunc)
AddContextField registers fn so that Ctx and the *Ctx package helpers enrich every context-scoped log with the fields fn extracts. Call it once at startup (it is safe for concurrent use). Integrations provide ready-made extractors — e.g. the srogotel module registers OpenTelemetry trace_id/span_id.
func Information ¶
func NewContext ¶
NewContext returns a copy of ctx carrying l. Middleware and interceptors use it to propagate a request-scoped logger (already enriched with a request ID, service name, etc.) down the call chain.
func NewID ¶
func NewID() string
NewID returns a random 128-bit identifier as a 32-character hex string, suitable as a request/correlation ID. It is safe for concurrent use.
func RegisterSinkType ¶ added in v1.1.0
func RegisterSinkType(name string, factory SinkFactory)
RegisterSinkType makes factory available to Config under the given type name (case-insensitive), letting external modules plug their sinks into the declarative JSON/YAML config. The built-in names (console, file, stdout, stderr) always win and cannot be overridden. Modules typically register in init, so importing e.g. srog/srogotel enables `"type": "otlp"`. Safe for concurrent use; a repeated name replaces the earlier factory.
func SetDefault ¶
func SetDefault(l *Logger)
SetDefault replaces the package-level logger used by the top-level functions.
Types ¶
type Config ¶
type Config struct {
// Level is the default minimum level: one of verbose, debug, information
// (or info), warning (or warn), error, fatal. Empty means Information.
Level string `json:"level,omitempty" yaml:"level,omitempty"`
// Render toggles the human-readable message. Pointer so that an explicit
// false is distinguishable from "unset" (which defaults to true).
Render *bool `json:"render,omitempty" yaml:"render,omitempty"`
// Caller annotates each event with the calling file and line.
Caller bool `json:"caller,omitempty" yaml:"caller,omitempty"`
// Timestamp adds a timestamp to each event. Pointer so an explicit false is
// distinguishable from "unset" (which defaults to true).
Timestamp *bool `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
// StackTrace captures a stack when an error is logged.
StackTrace bool `json:"stackTrace,omitempty" yaml:"stackTrace,omitempty"`
// TimeFormat is a friendly name (rfc3339, rfc3339nano, datetime, dateonly,
// timeonly, kitchen, unix, unixms, unixmicro, unixnano) or a raw Go layout.
// Empty leaves the default (RFC3339).
TimeFormat string `json:"timeFormat,omitempty" yaml:"timeFormat,omitempty"`
// Sinks lists the output destinations. Empty yields New's default (JSON to
// stdout).
Sinks []SinkSpec `json:"sinks,omitempty" yaml:"sinks,omitempty"`
}
Config is a declarative, serializable description of a Logger, suitable for loading from a JSON or YAML file (or any source that unmarshals into it). It mirrors the functional Option API: every field maps to one With* option, and an empty/zero field leaves that option at its default. Build it programmatically or decode it, then call Build:
c, err := srog.LoadConfigFile("logging.json")
if err != nil { ... }
log, err := c.Build()
The struct carries both `json` and `yaml` tags, so it decodes with the standard library or with gopkg.in/yaml.v3 without srog itself depending on a YAML parser.
func LoadConfig ¶
LoadConfig decodes a JSON Config from r.
func LoadConfigFile ¶
LoadConfigFile reads and decodes a JSON Config from path.
func (Config) Build ¶
Build constructs a Logger from the Config, returning an error if any field is invalid or a file sink cannot be opened.
type ContextFieldFunc ¶
ContextFieldFunc pulls zero or more structured fields out of a context. It is how correlation data that lives in the context — OpenTelemetry trace/span IDs, a tenant, a deadline — is attached to logs without srog depending on those packages. Register implementations with AddContextField.
type Format ¶
type Format uint8
Format selects how a sink serializes events.
const ( // FormatJSON writes newline-delimited JSON (NDJSON) — the machine-readable // form consumed by log shippers such as Fluent Bit. FormatJSON Format = iota // FormatConsole writes colorized, human-friendly lines with structured // parameters omitted (they remain available via a JSON sink). FormatConsole // FormatECS writes NDJSON using Elastic Common Schema field names // (@timestamp, log.level, error.message, ...), so events index cleanly into // Elasticsearch and render in Kibana without a Logstash mapping. FormatECS // FormatOTel writes each event as a single OpenTelemetry log record encoded // as OTLP/JSON (one LogRecord per line), so events feed straight into an // OpenTelemetry logs pipeline (Collector -> Loki/Elastic/...). FormatOTel // FormatTemplate renders each event through a Serilog-style output template // supplied with AsTemplate — literal text plus placeholders like // {Timestamp:15:04:05}, {Level:u3}, {Message}, {Properties}, or any event // field by name, each honoring ",alignment" and ":format" specifiers. FormatTemplate )
type Interval ¶
type Interval uint8
Interval selects time-based rotation cadence for a file sink. It composes with size-based rotation: a file rolls over when either trigger fires.
type Level ¶
type Level int8
Level mirrors Serilog's severity ladder. Values map onto zerolog levels.
func ParseLevel ¶
ParseLevel resolves a Serilog-style level name (case-insensitive) to a Level.
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger is an immutable, concurrency-safe logger. Derive enriched loggers with ForContext; the zero value is not usable — construct one with New/MustNew.
func Ctx ¶
Ctx returns the logger for ctx, enriched with any fields produced by the registered ContextFieldFuncs (see AddContextField). It resolves the base logger with FromContext (falling back to Default), so it never returns nil and is the idiomatic entry point for context-scoped logging:
srog.Ctx(ctx).Information("processing {OrderId}", id) // carries trace_id, etc.
With no extractors registered it costs no more than FromContext.
func ForContext ¶
ForContext derives an enriched logger from the package default.
func FromContext ¶
FromContext returns the Logger stored in ctx, or the package Default logger when none is present. It never returns nil, so callers can log unconditionally:
srog.FromContext(ctx).Information("processing {OrderId}", id)
func MustNew ¶
MustNew is like New but panics on error. Use it for configurations that cannot fail (no file sinks) or when a startup failure should abort the process.
func New ¶
New constructs a Logger from the given options. With no sink option it defaults to a single JSON sink on os.Stdout at Information level. It returns an error if a file sink cannot be opened.
func NewConsole ¶
func NewConsole() *Logger
NewConsole is a convenience constructor for development: colorized console output at Debug level with pretty stack traces on errors.
func NewFromConfig ¶
NewFromConfig builds a Logger from an already-parsed Config. It is shorthand for Config.Build.
func NewFromConfigFile ¶
NewFromConfigFile loads a JSON Config from path and builds a Logger from it.
func (*Logger) Close ¶
Close releases any file sinks held by the logger. Call it once on the root logger during shutdown; derived (ForContext) loggers share the same sinks.
func (*Logger) Error ¶
Error logs a failure. Pass the triggering error as err; it is attached under the standard "error" field. Use nil when there is no associated error.
func (*Logger) Fatal ¶
Fatal logs a failure, flushes all sinks, and then calls os.Exit(1). The flush ensures the final event reaches file/async sinks before the process dies.
func (*Logger) ForContext ¶
ForContext returns a child logger that includes the given property on every event, equivalent to Serilog's ForContext. The receiver is left unchanged.
func (*Logger) ForContextValues ¶
ForContextValues returns a child logger enriched with several properties.
func (*Logger) Information ¶
Information logs a normal, expected event.
func (*Logger) IntoContext ¶
IntoContext stores the receiver in ctx and returns the derived context. It is the fluent counterpart of NewContext:
ctx = log.ForContext("RequestId", id).IntoContext(ctx)
func (*Logger) Named ¶
Named returns a child logger tagged with a "service" property, the idiomatic way to identify which component or service emitted an event:
svcLog := log.Named("billing")
svcLog.Information("charged {Amount}", 999) // every event carries service=billing
func (*Logger) WithStackTrace ¶
WithStackTrace returns a child logger that captures (or stops capturing) a stack trace on logged errors. It is the per-logger counterpart of the WithStackTrace construction option — useful when a caller has already captured a stack (e.g. a panic recovery) and wants to attach it under the "stack" field itself without srog adding a second, less useful one from the recovery site.
type Option ¶
type Option func(*config)
Option customizes a Logger at construction time.
func WithCaller ¶
WithCaller annotates each event with the calling file and line.
func WithConsole ¶
func WithConsole(opts ...SinkOption) Option
WithConsole adds a colorized console sink writing to os.Stdout. Use Target to redirect (e.g. os.Stderr) and the sink options above to tune it.
func WithErrorHandler ¶
WithErrorHandler installs fn to be called when a sink's underlying Write fails. By default such errors are dropped (zerolog's behavior); a handler lets you count them, alert, or fall back to stderr. fn must be safe for concurrent use and should not itself log through the same logger.
func WithFile ¶
func WithFile(path string, opts ...SinkOption) Option
WithFile adds a JSON file sink at path. Combine with Rotate for rotation and retention. The parent directory must already exist.
func WithLevel ¶
WithLevel sets the default minimum level emitted by sinks that do not specify their own via MinLevel.
func WithRenderedMessage ¶
WithRenderedMessage toggles rendering of the human-readable message into the "message" field. Disable it for maximum throughput when you only consume the structured fields plus the raw template. Enabled by default. Console sinks rely on the rendered message, so keep it on when using them.
func WithSampling ¶
WithSampling applies s to every event before it reaches the sinks. Sampling is evaluated after level filtering. Combine samplers to taste; see EveryN and BurstLimit.
func WithStackTrace ¶
WithStackTrace captures a call stack whenever an error is logged via Error or Fatal. The stack is stored in the structured "stack" field (always present in JSON output) and pretty-printed by console sinks.
func WithTimeFormat ¶
WithTimeFormat sets the timestamp layout for this logger's JSON output. Pass a Go time layout (e.g. time.RFC3339Nano) or one of the package's Time* constants (TimeRFC3339Nano, TimeDateTime, TimeUnix, TimeUnixMs, ...) for ISO or epoch timestamps without importing zerolog. The format is applied per-logger via a hook, so unlike setting zerolog.TimeFieldFormat directly it does not leak into other loggers in the process. The default, RFC3339, is ISO 8601 and parses cleanly in Fluent Bit with `Time_Key time`.
func WithTimestamp ¶
WithTimestamp adds a timestamp to each event. Enabled by default.
func WithWriter ¶
func WithWriter(w io.Writer, opts ...SinkOption) Option
WithWriter adds a sink writing to an arbitrary io.Writer. It defaults to JSON; pass AsConsole to format it for human reading instead.
type Rotation ¶
type Rotation struct {
// MaxSizeMB rotates the file once it grows beyond this many megabytes.
// Zero means no size-based trigger.
MaxSizeMB int
// MaxBackups caps how many rotated files are retained (0 = keep all).
MaxBackups int
// MaxAgeDays deletes rotated files older than this many days (0 = no limit).
MaxAgeDays int
// Compress gzips rotated files.
Compress bool
// LocalTime uses local time (instead of UTC) in backup timestamps and for
// computing rotation boundaries.
LocalTime bool
// Every selects an additional time-based rotation cadence.
Every Interval
}
Rotation configures rotation and retention for a file sink. The zero value performs no rotation. Size-based rotation triggers when the active file exceeds MaxSizeMB; time-based rotation triggers when Every elapses.
type RotationSpec ¶
type RotationSpec struct {
MaxSizeMB int `json:"maxSizeMB,omitempty" yaml:"maxSizeMB,omitempty"`
MaxBackups int `json:"maxBackups,omitempty" yaml:"maxBackups,omitempty"`
MaxAgeDays int `json:"maxAgeDays,omitempty" yaml:"maxAgeDays,omitempty"`
Compress bool `json:"compress,omitempty" yaml:"compress,omitempty"`
LocalTime bool `json:"localTime,omitempty" yaml:"localTime,omitempty"`
Every string `json:"every,omitempty" yaml:"every,omitempty"`
}
RotationSpec is the serializable form of Rotation. Every is a friendly cadence name ("", "none", "hourly", "daily") instead of the Interval enum.
type Sampler ¶
Sampler decides which events are emitted, for flood control. It aliases zerolog's Sampler so the built-in samplers below (and any custom one) compose.
func BurstLimit ¶
BurstLimit emits up to burst events per period, then defers to next for the overflow (pass nil to drop everything past the burst). Use it to cap a hot log site without losing the first events of each window:
srog.WithSampling(srog.BurstLimit(100, time.Second, srog.EveryN(100)))
type SinkFactory ¶ added in v1.1.0
SinkFactory builds the destination writer for an externally registered sink type. cfg is the full Config being built, so a factory can inherit logger-wide settings (such as TimeFormat); spec is the sink's own entry, with its type-specific settings in spec.Options. The returned writer receives events serialized in format (unless spec.Format overrides it); if the writer also implements io.Closer it is closed by Logger.Close.
type SinkOption ¶
type SinkOption func(*sinkConfig)
SinkOption customizes a single sink (console, file, or writer).
func AsConsole ¶
func AsConsole() SinkOption
AsConsole forces colorized console output for this sink.
func AsECS ¶
func AsECS() SinkOption
AsECS forces Elastic Common Schema NDJSON output for this sink (see FormatECS).
func AsOTel ¶ added in v1.1.0
func AsOTel() SinkOption
AsOTel forces OpenTelemetry OTLP/JSON log-record output for this sink (see FormatOTel).
func AsTemplate ¶ added in v1.2.0
func AsTemplate(tmpl string) SinkOption
AsTemplate renders this sink through a Serilog-style output template (see FormatTemplate). The classic console layout, for example:
srog.WithConsole(srog.AsTemplate("[{Timestamp:15:04:05} {Level:u3}] {Message}{NewLine}{Exception}"))
Built-in placeholders: {Timestamp[:layout]}, {Level[:u3|w3|u|w]}, {Message}, {MessageTemplate}, {Exception}, {Caller}, {NewLine}, {Properties[:j]}; any other name prints that event field. All support ",alignment" (e.g. {Level,-7}) and use "{{"/"}}" for literal braces. Malformed holes render as literal text, matching message-template behavior. Structured fields not referenced by the template are omitted unless {Properties} is present.
func Async ¶
func Async(bufferSize int) SinkOption
Async offloads this sink's writes to a background goroutine backed by a queue of bufferSize events (a non-positive size uses a default). It keeps a slow destination — a file on a busy disk, a network stream — off the request path. If the queue fills the sink drops events rather than block the caller, and reports the total dropped through the error handler (see WithErrorHandler) on Close. Always Close the logger so the queue drains before exit.
func MinLevel ¶
func MinLevel(l Level) SinkOption
MinLevel sets the minimum level this sink emits, overriding the logger-wide level for this destination only. This is what lets a console sink show Debug while a file sink keeps only Warning and above.
func Rotate ¶
func Rotate(r Rotation) SinkOption
Rotate enables size/time/age-based rotation for a file sink. It has no effect on non-file sinks.
type SinkSpec ¶
type SinkSpec struct {
// Type is "console", "file", "stdout", "stderr", or any name registered via
// RegisterSinkType (e.g. "otlp" once srog/srogotel is imported). Required.
Type string `json:"type" yaml:"type"`
// Target selects the stream for a "console" sink: "stdout" (default) or
// "stderr". Ignored for other types.
Target string `json:"target,omitempty" yaml:"target,omitempty"`
// Path is the file path for a "file" sink. Required for that type.
Path string `json:"path,omitempty" yaml:"path,omitempty"`
// Level overrides the logger-wide minimum level for this sink only.
Level string `json:"level,omitempty" yaml:"level,omitempty"`
// Format overrides the sink's default serialization: "json", "console",
// "ecs", "otel" (OpenTelemetry OTLP/JSON log records), or "template"
// (Serilog-style output template; requires Template).
Format string `json:"format,omitempty" yaml:"format,omitempty"`
// Template is a Serilog-style output template (see AsTemplate), e.g.
// "[{Timestamp:15:04:05} {Level:u3}] {Message}{NewLine}{Exception}".
// Setting it implies Format "template".
Template string `json:"template,omitempty" yaml:"template,omitempty"`
// NoColor disables ANSI colors for a console sink.
NoColor bool `json:"noColor,omitempty" yaml:"noColor,omitempty"`
// Rotation configures rotation/retention for a "file" sink.
Rotation *RotationSpec `json:"rotation,omitempty" yaml:"rotation,omitempty"`
// Options carries type-specific settings for sinks registered via
// RegisterSinkType; built-in types ignore it. Factories typically read it
// through DecodeOptions.
Options map[string]any `json:"options,omitempty" yaml:"options,omitempty"`
}
SinkSpec is the serializable form of one sink.
func (SinkSpec) DecodeOptions ¶ added in v1.1.0
DecodeOptions re-marshals the sink's Options map into v (a pointer to a struct with json tags), so a SinkFactory can parse its type-specific settings without touching the raw map. A nil Options leaves v unchanged.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
srogecho
module
|
|
|
srogelastic
module
|
|
|
sroggrpc
module
|
|
|
Package sroghttp provides net/http middleware that attaches a request-scoped srog logger to each request: it assigns a request ID, propagates the logger through the request context, and logs request completion with structured fields.
|
Package sroghttp provides net/http middleware that attaches a request-scoped srog logger to each request: it assigns a request ID, propagates the logger through the request context, and logs request completion with structured fields. |
|
srogotel
module
|