Documentation
¶
Overview ¶
Package glow is a developer-focused structured logging library for Go.
Glow prioritizes readable development output while remaining production-ready through interchangeable handlers. The logging call sites stay identical when switching between development and structured (JSON) output.
Minimal API ¶
The stable call-site surface is intentionally small:
logger := glow.New()
logger.Info("Server started")
logger.Warn("Redis disconnected")
logger.Error("Database timeout", glow.Err(err))
logger.Debug("cache miss", glow.String("key", key))
logger.Fatal("unrecoverable configuration error")
logger.Panic("invariant violated")
auth := logger.Context("AuthService")
req := auth.With(glow.String("requestID", id))
child := req.Clone()
Behavioral Contracts ¶
The following contracts are part of Glow's public API stability guarantees. Implementations and handlers must honor them.
Message methods and the error path: Level methods accept a message string plus zero or more typed fields. First-class error rendering uses Err. When a log call includes an Err field and the message is empty, handlers use the error's message as the entry message. A nil error passed to Err is omitted from the entry (see Nil errors).
Duplicate keys: Within a single log call, and when merging logger-inherited fields with call-site fields, the last value for a given key wins. The winning field keeps the position of the key's first occurrence so field order remains stable and deterministic.
Reserved fields: Keys named by ReservedFieldKeys are owned by Glow metadata (timestamp, level, message, service, context, pid, caller). User fields that collide with a reserved key are emitted under the "user." prefix (for example, "user.level") and never overwrite metadata.
Invalid contexts: Logger.Context treats an empty or whitespace-only name as clearing the context (no component label). Non-empty names replace any prior context; contexts are not nested.
Nil errors: Err(nil) produces no field. Handlers never render a synthetic nil-error value for that constructor.
Fatal: Logger.Fatal emits a log entry at FatalLevel, then calls the configured exit function (default: os.Exit(1)). Tests should inject WithExitFunc so Fatal does not terminate the process.
Panic: Logger.Panic emits a log entry at PanicLevel, then panics with the message string. The panic always occurs after the entry has been handed to handlers, even if a handler returns an error.
Concurrency: A Logger value is safe for concurrent use. Logger.With, Logger.Context, and Logger.Clone return new loggers and never mutate the receiver. Concurrent writes through a shared logger are synchronized by the logger before reaching handlers.
Immutability: Derived loggers inherit fields and configuration by copy. Changes to a child logger never affect its parent or siblings.
Handlers and themes ¶
By default, New writes development-formatted output using ThemeDefault. Use WithTheme to switch presentation (Minimal, Compact, Classic) without changing call sites. NewJSONHandler produces deterministic structured output; register it with WithHandler. Color is enabled automatically for terminals unless WithColor or NO_COLOR overrides it.
Production controls ¶
Pipeline order for every log call is fixed: level gating → WithFilter → WithSampling → handler fan-out. Filters must be concurrency-safe and must not mutate entry fields. Sampling is per-level and probabilistic; unconfigured levels are never sampled.
Register multiple destinations with repeated WithHandler calls (or wrap them with Fanout). Sink failures are isolated across handlers; the logger discards handler errors after fan-out so a broken destination cannot interrupt callers. MultiWriter mirrors that isolation for raw io.Writer sinks and continues after short writes or errors (unlike io.MultiWriter).
Size-based rotating files live in the optional subpackage github.com/adamreaksmey/glow/rotate so rotation stays out of the core module path.
slog interoperability ¶
NewHandler returns a complete log/slog.Handler adapter. Records flow through Glow's pipeline so the same development and JSON handlers apply. Logger.SlogHandler adapts an existing logger. Use NewHandlerWithSource (or Logger.SlogHandlerWithSource) to attach slog source attributes when Record.PC is non-zero. Groups become nested maps; typed slog values map to Glow fields without reflection on the native kinds.
Safety and diagnostics ¶
Sensitive fields are redacted as RedactedValue in every built-in handler and in Field.FormatValue. Opting out requires an intentionally conspicuous API: WithUnsafeShowSensitive on the logger and/or AllowUnsafeSensitiveValues on a handler.
Caller captures the call-site file and line when present on a log call (or inherited via Logger.With). Paths are trimmed with WithProjectRoot when set.
Err fields render as structured ErrorDetail values (message, reason, unwrap chain, optional location/stack). Enable stacks with WithErrorStacks when errors expose StackTrace() []uintptr. Register third-party formatting through RegisterErrorRenderer without importing those packages into Glow.
Testing ¶
Package github.com/adamreaksmey/glow/glowtest provides an in-memory, concurrency-safe capture Handler and assertions for messages, fields, levels, and contexts. Keep it out of production code paths; wire it with WithHandler (or glowtest.NewLogger) only in tests.
Tracing ¶
TraceID and SpanID attach correlation fields that inherit through Logger.With, Logger.Context, and Logger.Clone. Empty IDs are omitted. Optional OpenTelemetry extraction lives in github.com/adamreaksmey/glow/integrations/otel: Enrich fills missing IDs from the active span without overriding explicit values; With applies extraction with normal last-write-wins merge semantics. Call-site fields always override inherited IDs.
HTTP middleware and integrations ¶
Package github.com/adamreaksmey/glow/middleware/http provides framework-neutral net/http request logging (method, path, status, latency) with panic-safe status capture, optional body limits/content-type filters, and sensitive header/body redaction. Framework adapters live in separate modules under github.com/adamreaksmey/glow/integrations so Gin, Echo, Fiber, Chi, Cobra, Bubble Tea, and OpenTelemetry never become dependencies of the core module.
Performance ¶
Benchmarks cover disabled logs, simple messages, typed fields, contexts, development and JSON output, caller capture, and handler fan-out. Allocation regression gates live alongside those benchmarks. Numbers measured against io.Discard are regression signals only: real writer I/O (files, terminals, network) dominates latency and can prevent strict allocation or timing guarantees. Prefer typed fields over Any on hot paths. See docs/PERFORMANCE.md in the repository.
Stability ¶
Glow follows semantic versioning. v1.0.0 graduates the minimal API above, typed field constructors, and these behavioral contracts to a stable surface. Breaking changes require a new major version. See docs/STABILITY.md, docs/SECURITY.md, and docs/MIGRATION.md in the repository.
Example ¶
package main
import (
"os"
"github.com/adamreaksmey/glow"
)
func main() {
logger := glow.New(
glow.WithService("api"),
glow.WithLevel(glow.InfoLevel),
glow.WithWriter(os.Stdout),
glow.WithTheme(glow.ThemeClassic),
glow.WithColor(false),
glow.WithExitFunc(func(int) {}),
)
auth := logger.Context("AuthService")
auth.Info("User logged in", glow.Int("id", 42), glow.String("role", "admin"))
}
Output: INFO [AuthService] User logged in id: 42 role: admin
Index ¶
- Constants
- func MultiWriter(writers ...io.Writer) io.Writer
- func NewHandler(options ...Option) slog.Handler
- func NewHandlerWithSource(options ...Option) slog.Handler
- func RegisterErrorRenderer(renderer ErrorRenderer)
- func ReservedFieldKeys() []string
- type DevelopmentHandler
- func (handler *DevelopmentHandler) AllowUnsafeSensitiveValues() *DevelopmentHandler
- func (handler *DevelopmentHandler) Enabled(level Level) bool
- func (handler *DevelopmentHandler) Handle(entry Entry) error
- func (handler *DevelopmentHandler) SetColor(enabled bool) *DevelopmentHandler
- func (handler *DevelopmentHandler) SetColorAuto() *DevelopmentHandler
- func (handler *DevelopmentHandler) SetErrorStacks(enabled bool) *DevelopmentHandler
- func (handler *DevelopmentHandler) SetMinLevel(level Level) *DevelopmentHandler
- func (handler *DevelopmentHandler) SetShowPID(show bool) *DevelopmentHandler
- func (handler *DevelopmentHandler) SetShowTimestamp(show bool) *DevelopmentHandler
- func (handler *DevelopmentHandler) SetTheme(theme Theme) *DevelopmentHandler
- type Entry
- type ErrorDetail
- type ErrorRenderOptions
- type ErrorRenderer
- type ErrorRendererFunc
- type Field
- func Any(key string, value any) Field
- func Bool(key string, value bool) Field
- func Caller() Field
- func Duration(key string, value time.Duration) Field
- func Err(err error) Field
- func Float64(key string, value float64) Field
- func Int(key string, value int) Field
- func Int64(key string, value int64) Field
- func MergeFields(inherited, callSite []Field) []Field
- func NamedErr(key string, err error) Field
- func Sensitive(key, value string) Field
- func SpanID(id string) Field
- func String(key, value string) Field
- func Time(key string, value time.Time) Field
- func TraceID(id string) Field
- func Uint64(key string, value uint64) Field
- type FieldKind
- type FilterFunc
- type Handler
- type JSONHandler
- func (handler *JSONHandler) AllowUnsafeSensitiveValues() *JSONHandler
- func (handler *JSONHandler) Enabled(level Level) bool
- func (handler *JSONHandler) Handle(entry Entry) error
- func (handler *JSONHandler) SetErrorStacks(enabled bool) *JSONHandler
- func (handler *JSONHandler) SetMinLevel(level Level) *JSONHandler
- type Level
- type Logger
- func (logger *Logger) Clone() *Logger
- func (logger *Logger) Context(name string) *Logger
- func (logger *Logger) Debug(msg string, fields ...Field)
- func (logger *Logger) Enabled(level Level) bool
- func (logger *Logger) Error(msg string, fields ...Field)
- func (logger *Logger) Fatal(msg string, fields ...Field)
- func (logger *Logger) Info(msg string, fields ...Field)
- func (logger *Logger) Panic(msg string, fields ...Field)
- func (logger *Logger) SlogHandler() slog.Handler
- func (logger *Logger) SlogHandlerWithSource() slog.Handler
- func (logger *Logger) Warn(msg string, fields ...Field)
- func (logger *Logger) With(fields ...Field) *Logger
- func (logger *Logger) WithUnlessPresent(fields ...Field) *Logger
- type Option
- func WithColor(enabled bool) Option
- func WithErrorStacks() Option
- func WithExitFunc(exit func(int)) Option
- func WithFilter(filter FilterFunc) Option
- func WithHandler(handler Handler) Option
- func WithLevel(level Level) Option
- func WithPID() Option
- func WithProjectRoot(path string) Option
- func WithSampling(level Level, rate float64) Option
- func WithService(name string) Option
- func WithTheme(theme Theme) Option
- func WithTimestamp() Option
- func WithUnsafeShowSensitive() Option
- func WithWriter(writer io.Writer) Option
- type Theme
Examples ¶
Constants ¶
const ( ReservedKeyTimestamp = "timestamp" ReservedKeyLevel = "level" ReservedKeyMessage = "message" ReservedKeyService = "service" ReservedKeyContext = "context" ReservedKeyPID = "pid" ReservedKeyCaller = "caller" // ReservedKeyPrefix is prepended to user field keys that collide with // reserved metadata keys (for example, "level" becomes "user.level"). ReservedKeyPrefix = "user." )
Reserved metadata field keys owned by Glow. User fields that collide with these keys are rewritten with the ReservedKeyPrefix by MergeFields.
const ( Debug = DebugLevel Info = InfoLevel Warn = WarnLevel Error = ErrorLevel Fatal = FatalLevel Panic = PanicLevel )
Ergonomic aliases matching the documented call-site API.
const ( FieldTraceID = "traceID" FieldSpanID = "spanID" )
Canonical field keys for distributed tracing metadata.
These are ordinary user fields (not reserved metadata). Prefer TraceID and SpanID so keys stay consistent across call sites, HTTP middleware, and OpenTelemetry extraction.
const RedactedValue = "[REDACTED]"
RedactedValue is the placeholder emitted for Sensitive fields when redaction is active (the default).
const Version = "v1.0.0"
Version is the current stable release of the core module.
Variables ¶
This section is empty.
Functions ¶
func MultiWriter ¶
MultiWriter returns an io.Writer that duplicates each write to every non-nil destination.
Partial-write / sink-failure contract: each destination is attempted independently. An error or short write on one destination does not stop writes to the others. After all destinations are attempted, Write returns (len(p), firstErr) where firstErr is the first failure observed, or nil.
This differs from io.MultiWriter, which stops at the first error.
func NewHandler ¶
NewHandler returns an slog.Handler backed by New with the given options.
handler := glow.NewHandler(glow.WithHandler(glow.NewJSONHandler(os.Stdout))) logger := slog.New(handler)
Example ¶
package main
import (
"bytes"
"fmt"
"log/slog"
"github.com/adamreaksmey/glow"
)
func main() {
var output bytes.Buffer
handler := glow.NewHandler(
glow.WithService("api"),
glow.WithHandler(glow.NewDevelopmentHandler(&output).
SetTheme(glow.ThemeClassic).
SetColor(false)),
)
slog.New(handler).Info("via slog", "role", "admin")
fmt.Print(output.String())
}
Output: INFO via slog role: admin
func NewHandlerWithSource ¶
NewHandlerWithSource is like NewHandler but includes a slog.SourceKey attribute (file, line, function) when Record.PC is non-zero.
func RegisterErrorRenderer ¶
func RegisterErrorRenderer(renderer ErrorRenderer)
RegisterErrorRenderer appends a renderer consulted before the default unwrap-based rendering. Renderers are tried in registration order; the first that returns ok=true wins. Safe for concurrent use; typically called from init.
func ReservedFieldKeys ¶
func ReservedFieldKeys() []string
ReservedFieldKeys lists every metadata key that user fields must not overwrite.
Types ¶
type DevelopmentHandler ¶
type DevelopmentHandler struct {
// contains filtered or unexported fields
}
DevelopmentHandler writes human-readable, theme-aware log lines. Color is applied only when writing to a terminal unless overridden.
func NewDevelopmentHandler ¶
func NewDevelopmentHandler(writer io.Writer) *DevelopmentHandler
NewDevelopmentHandler constructs a development handler writing to writer. Defaults match New: ThemeDefault with timestamps and PID enabled.
func (*DevelopmentHandler) AllowUnsafeSensitiveValues ¶
func (handler *DevelopmentHandler) AllowUnsafeSensitiveValues() *DevelopmentHandler
AllowUnsafeSensitiveValues disables redaction for Sensitive fields handled by this handler. Intentionally conspicuous; prefer the default redaction.
func (*DevelopmentHandler) Enabled ¶
func (handler *DevelopmentHandler) Enabled(level Level) bool
Enabled reports whether the handler accepts entries at level.
func (*DevelopmentHandler) Handle ¶
func (handler *DevelopmentHandler) Handle(entry Entry) error
Handle formats and writes a development log line.
func (*DevelopmentHandler) SetColor ¶
func (handler *DevelopmentHandler) SetColor(enabled bool) *DevelopmentHandler
SetColor forces ANSI color on or off.
func (*DevelopmentHandler) SetColorAuto ¶
func (handler *DevelopmentHandler) SetColorAuto() *DevelopmentHandler
SetColorAuto restores terminal auto-detection (and NO_COLOR) for color.
func (*DevelopmentHandler) SetErrorStacks ¶
func (handler *DevelopmentHandler) SetErrorStacks(enabled bool) *DevelopmentHandler
SetErrorStacks enables stack output for error fields when available.
func (*DevelopmentHandler) SetMinLevel ¶
func (handler *DevelopmentHandler) SetMinLevel(level Level) *DevelopmentHandler
SetMinLevel sets the minimum severity this handler accepts. Entries below the minimum are skipped by DevelopmentHandler.Enabled.
func (*DevelopmentHandler) SetShowPID ¶
func (handler *DevelopmentHandler) SetShowPID(show bool) *DevelopmentHandler
SetShowPID controls Default-theme process ID display.
func (*DevelopmentHandler) SetShowTimestamp ¶
func (handler *DevelopmentHandler) SetShowTimestamp(show bool) *DevelopmentHandler
SetShowTimestamp controls Default-theme timestamps.
func (*DevelopmentHandler) SetTheme ¶
func (handler *DevelopmentHandler) SetTheme(theme Theme) *DevelopmentHandler
SetTheme selects the presentation theme. Returns the handler for chaining.
type Entry ¶
type Entry struct {
Time time.Time
Level Level
Message string
Service string
Context string
PID int
Caller string
Fields []Field
}
Entry is the immutable unit of work passed through the logging pipeline. Handlers serialize Entries; changing a handler never changes call sites.
type ErrorDetail ¶
type ErrorDetail struct {
Message string
Reason string
Chain []string
Location string
Stack string
}
ErrorDetail is the structured rendering of an error for handlers.
func RenderError ¶
func RenderError(err error, options ErrorRenderOptions) ErrorDetail
RenderError builds an ErrorDetail for err. Registered renderers run first; otherwise Glow walks the unwrap chain. A nil error yields a zero detail.
type ErrorRenderOptions ¶
type ErrorRenderOptions struct {
IncludeStack bool
}
ErrorRenderOptions controls optional parts of RenderError.
type ErrorRenderer ¶
type ErrorRenderer interface {
Render(err error) (ErrorDetail, bool)
}
ErrorRenderer converts a specific error type into ErrorDetail. Register renderers for third-party error packages in an integration's init so Glow's core never imports those packages.
type ErrorRendererFunc ¶
type ErrorRendererFunc func(err error) (ErrorDetail, bool)
ErrorRendererFunc adapts a function to ErrorRenderer.
func (ErrorRendererFunc) Render ¶
func (render ErrorRendererFunc) Render(err error) (ErrorDetail, bool)
Render calls the function.
type Field ¶
type Field struct {
Key string
Kind FieldKind
Integer int64
Unsigned uint64
Float float64
String string
Boolean bool
Interface any
}
Field is an ordered, typed key/value pair attached to a log entry or logger. Fields are values; copying a Field does not share mutable state.
func Any ¶
Any stores an arbitrary value. Prefer typed constructors on hot paths; Any may require reflection in handlers and is not allocation-free.
func Caller ¶
func Caller() Field
Caller requests capture of the call-site file and line. The key is ignored by handlers; caller metadata uses the reserved "caller" key. Prefer the zero-argument form at call sites.
func Err ¶
Err constructs a first-class error field.
A nil error returns a zero Field with Kind FieldKindInvalid, which MergeFields and entry builders omit. Non-nil errors use key "error" unless a custom key is needed via NamedErr.
func MergeFields ¶
MergeFields combines inherited and call-site fields under Glow's field contracts: invalid fields are dropped, reserved keys are prefixed, duplicate keys keep first-seen order with last-write-wins values, and call-site fields override inherited fields with the same key.
func NamedErr ¶
NamedErr constructs an error field with an explicit key. A nil error returns a zero Field that callers must treat as absent.
func Sensitive ¶
Sensitive marks a string value for redaction in every built-in handler. Redaction is enabled by default; opting out requires an explicit handler configuration that is intentionally conspicuous.
Example ¶
package main
import (
"os"
"github.com/adamreaksmey/glow"
)
func main() {
logger := glow.New(
glow.WithService("api"),
glow.WithWriter(os.Stdout),
glow.WithTheme(glow.ThemeClassic),
glow.WithColor(false),
)
logger.Info("API request", glow.Sensitive("apiKey", "super-secret"))
}
Output: INFO API request apiKey: [REDACTED]
func SpanID ¶
SpanID constructs a string field with key FieldSpanID. An empty id is omitted (same contract as Err(nil)).
func TraceID ¶
TraceID constructs a string field with key FieldTraceID. An empty id is omitted (same contract as Err(nil)).
Example ¶
package main
import (
"os"
"github.com/adamreaksmey/glow"
)
func main() {
logger := glow.New(
glow.WithService("api"),
glow.WithWriter(os.Stdout),
glow.WithTheme(glow.ThemeClassic),
glow.WithColor(false),
)
logger = logger.With(glow.TraceID("abc-123-def"), glow.SpanID("xyz-789"))
logger.Context("AuthService").Info("Processing request")
}
Output: INFO [AuthService] Processing request traceID: abc-123-def spanID: xyz-789
func (Field) ErrorValue ¶
ErrorValue returns the error payload when Kind is FieldKindError.
func (Field) FormatValue ¶
FormatValue renders a debug representation of the field value. FieldKindSensitive values are always shown as RedactedValue here so accidental debug printing cannot leak secrets; use the field's String only after an explicit unsafe override.
type FieldKind ¶
type FieldKind uint8
FieldKind identifies the typed payload stored in a Field.
const ( FieldKindInvalid FieldKind = iota FieldKindString FieldKindInt FieldKindInt64 FieldKindUint64 FieldKindFloat64 FieldKindBool FieldKindDuration FieldKindTime FieldKindError FieldKindSensitive FieldKindCaller FieldKindAny )
Supported typed field kinds. Native constructors never use reflection.
type FilterFunc ¶
FilterFunc decides whether an entry should be emitted. Returning false drops the entry.
Pipeline order: level gating → filter → sampling → handlers. Filters run only for enabled levels and before sampling. A filter that returns false skips sampling and handler fan-out entirely.
FilterFuncs must be safe for concurrent use and must not mutate entry.Fields.
type Handler ¶
Handler serializes and writes log entries to one or more destinations. Handlers own formatting; themes affect only development handlers.
When multiple handlers are registered with WithHandler, each enabled handler receives every emitted entry. Sink failures are isolated: one handler error does not prevent later handlers from running. The logger discards handler errors after fan-out (best-effort logging).
func Fanout ¶
Fanout returns a Handler that delivers each entry to every non-nil handler in registration order.
Sink failures are isolated: an error from one handler does not prevent later handlers from running. After every handler is attempted, Fanout returns the first non-nil error, or nil if all handlers succeeded.
Prefer registering multiple handlers with WithHandler when configuring a Logger. Fanout is useful when a single Handler value must wrap several sinks (for example, when composing handlers for adapters).
Example ¶
package main
import (
"bytes"
"fmt"
"github.com/adamreaksmey/glow"
)
func main() {
var development bytes.Buffer
var jsonOut bytes.Buffer
logger := glow.New(
glow.WithService("api"),
glow.WithHandler(glow.NewDevelopmentHandler(&development).
SetTheme(glow.ThemeClassic).
SetColor(false)),
glow.WithHandler(glow.NewJSONHandler(&jsonOut)),
)
logger.Info("dual sink")
fmt.Print(development.String())
}
Output: INFO dual sink
type JSONHandler ¶
type JSONHandler struct {
// contains filtered or unexported fields
}
JSONHandler writes deterministic, machine-readable JSON log lines. Output never includes ANSI styling. Metadata keys use stable names and order; user fields follow call order with typed JSON values.
func NewJSONHandler ¶
func NewJSONHandler(writer io.Writer) *JSONHandler
NewJSONHandler constructs a JSON handler writing one object per line.
Example ¶
package main
import (
"bytes"
"encoding/json"
"fmt"
"github.com/adamreaksmey/glow"
)
func main() {
var output bytes.Buffer
logger := glow.New(
glow.WithService("api"),
glow.WithHandler(glow.NewJSONHandler(&output)),
)
logger.Context("AuthService").Info("User logged in", glow.Int("id", 42))
var payload map[string]any
if err := json.Unmarshal(output.Bytes(), &payload); err != nil {
panic(err)
}
fmt.Println(payload["level"], payload["message"], payload["id"])
}
Output: info User logged in 42
func (*JSONHandler) AllowUnsafeSensitiveValues ¶
func (handler *JSONHandler) AllowUnsafeSensitiveValues() *JSONHandler
AllowUnsafeSensitiveValues disables redaction for Sensitive fields handled by this handler. Intentionally conspicuous; prefer the default redaction.
func (*JSONHandler) Enabled ¶
func (handler *JSONHandler) Enabled(level Level) bool
Enabled reports whether the handler accepts entries at level.
func (*JSONHandler) Handle ¶
func (handler *JSONHandler) Handle(entry Entry) error
Handle encodes the entry as a single JSON object followed by a newline.
func (*JSONHandler) SetErrorStacks ¶
func (handler *JSONHandler) SetErrorStacks(enabled bool) *JSONHandler
SetErrorStacks enables stack output for error fields when available.
func (*JSONHandler) SetMinLevel ¶
func (handler *JSONHandler) SetMinLevel(level Level) *JSONHandler
SetMinLevel sets the minimum severity this handler accepts. Entries below the minimum are skipped by JSONHandler.Enabled.
type Level ¶
type Level int
Level represents the severity of a log entry.
Severity levels in ascending order of importance.
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger is an immutable, concurrency-safe structured logger.
Methods that change configuration or fields ([With], [Context], [Clone]) return a new Logger. Level methods emit entries through the configured handlers without mutating the receiver.
func New ¶
New constructs a Logger with optional configuration. With no options, the logger writes at InfoLevel to os.Stdout using the executable base name as the service name.
Options are applied in order; later options override earlier ones for the same setting. WithHandler appends; it does not replace prior handlers.
func (*Logger) Clone ¶
Clone returns a derived logger with the same configuration, context, and fields as the receiver. The parent and clone do not share field slices.
func (*Logger) Context ¶
Context returns a derived logger labeled with name. Empty or whitespace-only names clear the context.
func (*Logger) Debug ¶
Debug logs a message at DebugLevel.
func (*Logger) Enabled ¶
Enabled reports whether an entry at level would be emitted after level gating.
func (*Logger) Error ¶
Error logs a message at ErrorLevel.
Prefer attaching errors with Err. When msg is empty and an error field is present, the error's message becomes the entry message.
func (*Logger) Fatal ¶
Fatal logs a message at FatalLevel, then calls the configured exit function with code 1. Use WithExitFunc in tests.
func (*Logger) Panic ¶
Panic logs a message at PanicLevel, then panics with msg. The panic occurs even when the level is disabled, after a best-effort log.
func (*Logger) SlogHandler ¶
SlogHandler returns an slog.Handler that emits through this logger. Derived slog handlers share the logger's configuration, context, and fields.
func (*Logger) SlogHandlerWithSource ¶
SlogHandlerWithSource is like Logger.SlogHandler but includes source location when Record.PC is non-zero.
func (*Logger) With ¶
With returns a derived logger that includes fields on every subsequent entry. Fields are merged with call-site fields under MergeFields contracts.
Example ¶
package main
import (
"os"
"github.com/adamreaksmey/glow"
)
func main() {
logger := glow.New(
glow.WithService("api"),
glow.WithWriter(os.Stdout),
glow.WithTheme(glow.ThemeClassic),
glow.WithColor(false),
)
request := logger.With(glow.String("requestID", "req-1"))
request.Info("accepted")
}
Output: INFO accepted requestID: req-1
func (*Logger) WithUnlessPresent ¶
WithUnlessPresent returns a derived logger that adds fields only for keys that are not already inherited. Existing keys keep their values and first-seen positions. Call-site fields still override inherited values via MergeFields.
Use this when attaching defaults such as extracted OpenTelemetry IDs so explicit TraceID/SpanID values set earlier on the logger win.
type Option ¶
type Option func(*loggerConfig)
Option configures a Logger at construction time.
func WithColor ¶
WithColor forces ANSI color on (true) or off (false). When unset, color is enabled only when the writer is a terminal.
func WithErrorStacks ¶
func WithErrorStacks() Option
WithErrorStacks enables stack traces on error fields when the error implements StackTrace() []uintptr (as used by popular error packages). Stacks are omitted when the error does not expose program counters.
func WithExitFunc ¶
WithExitFunc replaces os.Exit for Logger.Fatal. The function receives the process exit code (always 1 for Fatal). Tests must set this to avoid terminating the test process.
func WithFilter ¶
func WithFilter(filter FilterFunc) Option
WithFilter installs a dynamic entry filter. A nil filter clears filtering. See FilterFunc for pipeline ordering and concurrency requirements.
func WithHandler ¶
WithHandler appends a Handler to the logger's fan-out list.
When at least one handler is configured, the default development writer path (WithWriter) is not used unless that destination is also registered explicitly as a handler (for example, NewDevelopmentHandler(os.Stdout)). Later WithHandler calls append; they do not replace earlier handlers.
Fan-out isolates sink failures across handlers. See Handler and Fanout.
func WithLevel ¶
WithLevel sets the minimum enabled severity. Entries below this level are discarded before fields are merged or handlers run.
func WithPID ¶
func WithPID() Option
WithPID enables inclusion of the process ID in development output. PID is always present on structured Entry values for handlers.
func WithProjectRoot ¶
WithProjectRoot sets the directory prefix stripped from Caller paths. When empty, caller paths are emitted as cleaned absolute (slash-normalized) paths. Trailing separators are optional.
func WithSampling ¶
WithSampling sets a per-level probabilistic sample rate in the range [0, 1]. Rates outside that range are clamped. A rate of 1.0 keeps every entry; 0.0 drops all entries at that level. Levels without a configured rate are never sampled (always kept).
Sampling runs after level gating and filtering, and is safe for concurrent use. Calling WithSampling repeatedly for the same level keeps the last rate.
Example ¶
package main
import (
"os"
"github.com/adamreaksmey/glow"
)
func main() {
logger := glow.New(
glow.WithLevel(glow.DebugLevel),
glow.WithSampling(glow.DebugLevel, 0),
glow.WithWriter(os.Stdout),
glow.WithTheme(glow.ThemeClassic),
glow.WithColor(false),
glow.WithService("api"),
)
logger.Debug("sampled out")
logger.Info("always kept when unconfigured")
}
Output: INFO always kept when unconfigured
func WithService ¶
WithService overrides the automatic executable-derived service name.
func WithTheme ¶
WithTheme selects the development presentation theme. Themes affect only development formatting; JSON and custom handlers ignore them.
func WithTimestamp ¶
func WithTimestamp() Option
WithTimestamp enables inclusion of timestamps in development output. Timestamps are always present on structured Entry values for handlers.
func WithUnsafeShowSensitive ¶
func WithUnsafeShowSensitive() Option
WithUnsafeShowSensitive disables redaction of Sensitive fields for this logger. The name is intentionally conspicuous: secrets will appear in every handler that honors the entry as built. Prefer leaving redaction enabled.
func WithWriter ¶
WithWriter sets the default destination for the built-in development handler. When no explicit handlers are configured, Glow writes theme-formatted development output to this writer (default: os.Stdout).
type Theme ¶
type Theme int
Theme selects a development presentation style. Themes affect formatting only; logging behavior is unchanged.
const ( // ThemeDefault is NestJS-inspired: service, PID, timestamp, level, context, message. ThemeDefault Theme = iota // ThemeMinimal shows time-of-day, level, and message. ThemeMinimal // ThemeCompact shows a one-letter level and the message. ThemeCompact // ThemeClassic shows an uppercase level and the message. ThemeClassic )
Built-in development themes.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package glowtest provides concurrency-safe log capture and assertions for tests.
|
Package glowtest provides concurrency-safe log capture and assertions for tests. |
|
middleware
|
|
|
http
Package http provides framework-neutral net/http request logging for Glow.
|
Package http provides framework-neutral net/http request logging for Glow. |
|
Package rotate provides a size-based rotating file writer for Glow.
|
Package rotate provides a size-based rotating file writer for Glow. |







