log

package
v0.1.72 Latest Latest
Warning

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

Go to latest
Published: Feb 13, 2026 License: MIT Imports: 7 Imported by: 27

README

Zap Logger Builder Package

A fluent, builder-pattern wrapper for Uber's Zap logger with context integration, designed to make logger configuration simple and readable.

Features

  • 🚀 Fluent Builder Pattern: Chain methods for clean, readable configuration
  • 🔧 Context Integration: Seamlessly attach loggers to Go contexts
  • High Performance: Built on top of Uber's Zap logger
  • 🎯 Type Safe: Full type safety with compile-time checks
  • 📦 Zero Dependencies: Only depends on go.uber.org/zap
  • 🛠️ Flexible Configuration: Support for most Zap configuration options

Installation

go get -u go.uber.org/zap
go get -u github.com/fmotalleb/log

Quick Start

Basic Usage
package main

import (
    "context"
    "github.com/fmotalleb/log"
)

func main() {
    // Create a simple logger
    logger := log.NewBuilder().
        Level("info").
        ServiceName("my-service").
        MustBuild()

    logger.Info("Hello, World!")

    // Create logger with context
    ctx := context.Background()
    ctx = log.WithNewLoggerForced(ctx,
        func(b *log.Builder) *log.Builder {
            return b.Level("debug").ServiceName("api-service")
        },
    )

    // Use logger from context
    log.FromContext(ctx).Info("Processing request")
}
Development vs Production
// Development logger (human-readable, colored output)
devLogger := log.NewBuilder().
    Development(true).
    Level("debug").
    ServiceName("my-app").
    MustBuild()

// Production logger (JSON, structured)
prodLogger := log.NewBuilder().
    Level("info").
    JSONEncoding().
    ServiceName("my-app").
    Version("1.0.0").
    Environment("production").
    MustBuild()

Builder Methods

Core Configuration
Method Description Default
Level(string) Set log level ("debug", "info", "warn", "error") "info"
Development(bool) Enable development mode (console + colors) false
ServiceName(string) Add service name to all logs -
Version(string) Add version to all logs -
Environment(string) Add environment to all logs -
Encoding Options
Method Description
JSONEncoding() Use JSON format (production)
ConsoleEncoding() Use console format (development)
ColorLevel() Enable colored log levels
LowercaseLevel() Use lowercase level names
CapitalLevel() Use capital level names
Time Formatting
Method Description
ISO8601Time() ISO8601 timestamp format
RFC3339Time() RFC3339 timestamp format
EpochTime() Unix epoch timestamp
CustomTime(layout) Custom time format
Output Configuration
Method Description
OutputPaths(paths...) Set output destinations
AddOutputPath(path) Add output destination
ErrorOutputPaths(paths...) Set error output destinations
DisableCaller(bool) Disable caller information
DisableStacktrace(bool) Disable stack traces
Advanced Options
Method Description
Sampling(initial, thereafter) Configure log sampling
NoSampling() Disable log sampling
AddHook(func) Add custom hook function
Name(string) Set logger name

Context Integration

Adding Logger to Context
// Method 1: Build and attach logger
ctx, err := log.WithNewLogger(ctx,
    func(b *log.Builder) *log.Builder {
        return b.Level("info").ServiceName("api")
    },
)

// Method 2: Attach existing logger
logger := log.NewBuilder().Level("debug").MustBuild()
ctx = log.WithLogger(ctx, logger)

// Method 3: Build and attach (panic on error)
ctx = log.WithNewLoggerForced(ctx,
    func(b *log.Builder) *log.Builder {
        return b.Development(true).ServiceName("debug-service")
    },
)
Using Logger from Context
func processRequest(ctx context.Context, userID string) {
    logger := log.FromContext(ctx)

    logger.Info("Processing request",
        zap.String("user_id", userID),
        zap.String("action", "process"),
    )

    // Logger automatically includes service name, version, etc.
    // from the builder configuration
}

Common Patterns

HTTP Server with Request Logging
func httpHandler(w http.ResponseWriter, r *http.Request) {
    // Create request-scoped logger
    ctx := log.WithNewLoggerForced(r.Context(),
        func(b *log.Builder) *log.Builder {
            return b.
                Level("info").
                ServiceName("api-server").
                AddInitialField("request_id", generateRequestID()).
                AddInitialField("method", r.Method).
                AddInitialField("path", r.URL.Path)
        },
    )

    logger := log.FromContext(ctx)
    logger.Info("Request started")

    // Process request with context
    processRequest(ctx)

    logger.Info("Request completed")
}
File Logging
fileLogger := log.NewBuilder().
    Level("warn").
    JSONEncoding().
    OutputPaths("/var/log/app.log").
    ErrorOutputPaths("/var/log/app-error.log").
    ServiceName("file-processor").
    MustBuild()
Multiple Output Destinations
multiLogger := log.NewBuilder().
    Level("info").
    OutputPaths("stdout", "/var/log/app.log", "syslog").
    ErrorOutputPaths("stderr", "/var/log/error.log").
    ServiceName("multi-output-service").
    MustBuild()
Custom Hook for Monitoring
monitoringLogger := log.NewBuilder().
    Level("info").
    AddHook(func(entry zapcore.Entry) error {
        if entry.Level >= zapcore.ErrorLevel {
            // Send to monitoring system (Sentry, DataDog, etc.)
            sendToMonitoring(entry)
        }
        return nil
    }).
    ServiceName("monitored-service").
    MustBuild()

Configuration Examples

Minimal Logger
logger := log.NewBuilder().MustBuild()
Development Logger
logger := log.NewBuilder().
    Development(true).
    Level("debug").
    ServiceName("my-service").
    MustBuild()
Production Logger
logger := log.NewBuilder().
    Level("info").
    JSONEncoding().
    ISO8601Time().
    ServiceName("my-service").
    Version("1.2.3").
    Environment("production").
    Sampling(100, 100).
    MustBuild()
Custom Field Keys
logger := log.NewBuilder().
    TimeKey("ts").
    LevelKey("severity").
    MessageKey("msg").
    CallerKey("source").
    ServiceName("custom-service").
    MustBuild()
Zap logger from environment vars
  • Namespace Prefix: All variables use ZAPLOG_ prefix to avoid conflicts
  • Simplified Configuration: Focuses on core logging configuration options
  • Type Safety: Boolean and integer values are properly parsed with fallbacks
  • Comma-Separated Lists: Output paths support multiple destinations via comma separation
Variable Type Description Default Valid Values
ZAPLOG_LEVEL string Logging level "info" "debug", "info", "warn", "error", "dpanic", "panic", "fatal"
ZAPLOG_DEVELOPMENT bool Development mode (console + colors) false "true", "false", "1", "0"
ZAPLOG_TIME_FORMAT string Timestamp format "iso8601" "iso8601", "rfc3339", "epoch", custom layout
ZAPLOG_LEVEL_FORMAT string Log level format "lowercase" "lowercase", "capital", "color"
ZAPLOG_OUTPUT_PATHS []string Output destinations (comma-separated) "stdout" "stdout", "/path/to/file", "syslog"
ZAPLOG_ERROR_PATHS []string Error output destinations (comma-separated) "stderr" "stderr", "/path/to/error.log"
ZAPLOG_DISABLE_CALLER bool Disable caller information false "true", "false", "1", "0"
ZAPLOG_DISABLE_STACKTRACE bool Disable stack traces false "true", "false", "1", "0"
ZAPLOG_ENABLE_SAMPLING bool Enable log sampling false "true", "false", "1", "0"
ZAPLOG_SAMPLING_INITIAL int Initial sampling rate 100 Any positive integer
ZAPLOG_SAMPLING_THEREAFTER int Subsequent sampling rate 100 Any positive integer
Configuration Examples
Development Environment
export ZAPLOG_LEVEL=debug
export ZAPLOG_DEVELOPMENT=true
export ZAPLOG_TIME_FORMAT=iso8601
export ZAPLOG_LEVEL_FORMAT=color
export ZAPLOG_OUTPUT_PATHS=stdout
export ZAPLOG_DISABLE_CALLER=false
export ZAPLOG_DISABLE_STACKTRACE=false
Production Environment
export ZAPLOG_LEVEL=info
export ZAPLOG_DEVELOPMENT=false
export ZAPLOG_TIME_FORMAT=iso8601
export ZAPLOG_LEVEL_FORMAT=lowercase
export ZAPLOG_OUTPUT_PATHS=stdout,/var/log/app.log
export ZAPLOG_ERROR_PATHS=stderr,/var/log/app-error.log
export ZAPLOG_ENABLE_SAMPLING=true
export ZAPLOG_SAMPLING_INITIAL=100
export ZAPLOG_SAMPLING_THEREAFTER=100
export ZAPLOG_DISABLE_CALLER=false
export ZAPLOG_DISABLE_STACKTRACE=false
Docker Compose Example
services:
  app:
    image: my-app:latest
    environment:
      - ZAPLOG_LEVEL=info
      - ZAPLOG_DEVELOPMENT=false
      - ZAPLOG_TIME_FORMAT=iso8601
      - ZAPLOG_LEVEL_FORMAT=lowercase
      - ZAPLOG_OUTPUT_PATHS=stdout,/var/log/app.log
      - ZAPLOG_ERROR_PATHS=stderr,/var/log/error.log
      - ZAPLOG_ENABLE_SAMPLING=true
      - ZAPLOG_SAMPLING_INITIAL=100
      - ZAPLOG_SAMPLING_THEREAFTER=100
    volumes:
      - ./logs:/var/log
Usage in Go Code
package main

import (
    "context"
    "os"
    "your-project/log"
)

func main() {
    // Set environment variables programmatically (for testing)
    os.Setenv("ZAPLOG_LEVEL", "debug")
    os.Setenv("ZAPLOG_DEVELOPMENT", "true")
    os.Setenv("ZAPLOG_TIME_FORMAT", "rfc3339")
    os.Setenv("ZAPLOG_LEVEL_FORMAT", "color")
    os.Setenv("ZAPLOG_OUTPUT_PATHS", "stdout,/tmp/app.log")

    // Create logger from environment
    logger := log.NewBuilder().FromEnv().MustBuild()
    logger.Info("Logger configured from ZAPLOG_ environment variables")

    // Create context with environment-configured logger
    ctx := context.Background()
    ctx = log.WithNewEnvLoggerForced(ctx)

    log.FromContext(ctx).Debug("Debug message with environment configuration")
}
Variable Details
ZAPLOG_TIME_FORMAT
  • "iso8601": 2006-01-02T15:04:05.000Z0700 format
  • "rfc3339": 2006-01-02T15:04:05Z07:00 format
  • "epoch": Unix timestamp (seconds since epoch)
  • Custom layout: Any Go time layout string (e.g., "2006-01-02 15:04:05")
ZAPLOG_OUTPUT_PATHS / ZAPLOG_ERROR_PATHS
  • "stdout" / "stderr": Standard output/error
  • File paths: /var/log/app.log, /tmp/debug.log
  • "syslog": System log (Unix systems)
  • Multiple paths: Comma-separated list: "stdout,/var/log/app.log"
ZAPLOG_SAMPLING_*
  • Sampling reduces log volume in high-traffic scenarios
  • INITIAL: Log first N messages per second
  • THEREAFTER: Log every Nth message after initial quota
  • Example: INITIAL=100, THEREAFTER=100 logs first 100/sec, then every 100th message

Error Handling

The builder provides two build methods:

  • Build() - Returns (*zap.Logger, error) for explicit error handling
  • MustBuild() - Returns *zap.Logger and panics on error (suitable for initialization)
// Explicit error handling
logger, err := log.NewBuilder().Level("info").Build()
if err != nil {
    return fmt.Errorf("failed to create logger: %w", err)
}

// Panic on error (initialization time)
logger := log.NewBuilder().Level("info").MustBuild()

Best Practices

  1. Use Context Integration: Always pass loggers through context for request-scoped logging
  2. Set Service Metadata: Include service name, version, and environment in production
  3. Choose Appropriate Levels: Use debug for development, info for production
  4. Structure Your Logs: Prefer structured fields over string formatting
  5. Handle Errors Gracefully: Use Build() for runtime configuration, MustBuild() for initialization

Performance Notes

  • The builder creates a new instance for each method call (immutable pattern)
  • Context operations are lightweight and safe for concurrent use
  • FromContext() returns a no-op logger if none is found (safe to use anywhere)
  • Zap's underlying performance characteristics are preserved

License

This package wraps Uber's Zap logger. Please refer to Zap's license for usage terms.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	DefaultLevel                             = zapcore.InfoLevel
	DefaultFormat                            = zapcore.LowercaseLevelEncoder
	DefaultDevelopment                       = false
	DefaultSampling      *zap.SamplingConfig = nil
	DefaultDebugSampling                     = 100
)

Functions

func FromContext

func FromContext(ctx context.Context) *zap.Logger

FromContext extracts logger from context, or returns a nop logger if it was not found.

func Of

func Of(ctx context.Context) *zap.Logger

Of is an alias to FromContext.

func SetDebugDefaults

func SetDebugDefaults()

func WithLogger

func WithLogger(ctx context.Context, logger *zap.Logger) context.Context

WithLogger adds logger to context.

func WithNewEnvLogger

func WithNewEnvLogger(
	ctx context.Context,
	builders ...BuilderFunc,
) (context.Context, error)

WithNewEnvLogger builds logger using env variables and attach it to given context.

func WithNewEnvLoggerForced

func WithNewEnvLoggerForced(
	ctx context.Context,
	builders ...BuilderFunc,
) context.Context

WithNewLoggerForced does what WithNewLogger does but panics if fails.

func WithNewLogger

func WithNewLogger(
	ctx context.Context,
	builders ...BuilderFunc,
) (context.Context, error)

WithNewLogger builds logger and attach it to given context.

func WithNewLoggerForced

func WithNewLoggerForced(
	ctx context.Context,
	builders ...BuilderFunc,
) context.Context

WithNewLoggerForced does what WithNewLogger does but panics if fails.

Types

type Builder

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

Builder provides a fluent interface for configuring zap logger.

func NewBuilder

func NewBuilder() *Builder

NewBuilder creates a new LoggerBuilder with default values.

func (*Builder) AddErrorOutputPath

func (b *Builder) AddErrorOutputPath(path string) *Builder

AddErrorOutputPath adds an error output path.

func (*Builder) AddHook

func (b *Builder) AddHook(hook func(zapcore.Entry) error) *Builder

AddHook adds a hook function.

func (*Builder) AddInitialField

func (b *Builder) AddInitialField(key string, value interface{}) *Builder

AddInitialField adds an initial field.

func (*Builder) AddOutputPath

func (b *Builder) AddOutputPath(path string) *Builder

AddOutputPath adds an output path.

func (*Builder) Build

func (b *Builder) Build() (*zap.Logger, error)

Build creates the zap logger with the configured options.

func (*Builder) CallerKey

func (b *Builder) CallerKey(key string) *Builder

CallerKey sets the caller field key.

func (*Builder) CapitalLevel

func (b *Builder) CapitalLevel() *Builder

CapitalLevel sets capital level encoding.

func (*Builder) ColorLevel

func (b *Builder) ColorLevel() *Builder

ColorLevel sets colored level encoding.

func (*Builder) ConsoleEncoding

func (b *Builder) ConsoleEncoding() *Builder

ConsoleEncoding sets console encoding.

func (*Builder) CustomTime

func (b *Builder) CustomTime(layout string) *Builder

CustomTime sets custom time encoding.

func (*Builder) Development

func (b *Builder) Development(dev bool) *Builder

Development enables/disables development mode (console logger).

func (*Builder) DisableCaller

func (b *Builder) DisableCaller(disable bool) *Builder

DisableCaller enables/disables caller information.

func (*Builder) DisableStacktrace

func (b *Builder) DisableStacktrace(disable bool) *Builder

DisableStacktrace enables/disables stacktrace.

func (*Builder) EncodeCaller

func (b *Builder) EncodeCaller(encoder zapcore.CallerEncoder) *Builder

EncodeCaller sets the caller encoder.

func (*Builder) EncodeDuration

func (b *Builder) EncodeDuration(encoder zapcore.DurationEncoder) *Builder

EncodeDuration sets the duration encoder.

func (*Builder) EncodeLevel

func (b *Builder) EncodeLevel(encoder zapcore.LevelEncoder) *Builder

EncodeLevel sets the level encoder.

func (*Builder) EncodeTime

func (b *Builder) EncodeTime(encoder zapcore.TimeEncoder) *Builder

EncodeTime sets the time encoder.

func (*Builder) Encoding

func (b *Builder) Encoding(encoding string) *Builder

Encoding sets the log encoding format.

func (*Builder) Environment

func (b *Builder) Environment(env string) *Builder

Environment adds environment to initial fields.

func (*Builder) EpochTime

func (b *Builder) EpochTime() *Builder

EpochTime sets epoch time encoding.

func (*Builder) ErrorOutputPaths

func (b *Builder) ErrorOutputPaths(paths ...string) *Builder

ErrorOutputPaths sets the error output paths.

func (*Builder) FromEnv

func (b *Builder) FromEnv() *Builder

FromEnv configures the builder using environment variables with sane defaults.

func (*Builder) FullCaller

func (b *Builder) FullCaller() *Builder

FullCaller sets full caller encoding.

func (*Builder) ISO8601Time

func (b *Builder) ISO8601Time() *Builder

ISO8601Time sets ISO8601 time encoding.

func (*Builder) InitialFields

func (b *Builder) InitialFields(fields map[string]interface{}) *Builder

InitialFields sets initial fields.

func (*Builder) JSONEncoding

func (b *Builder) JSONEncoding() *Builder

JSONEncoding sets JSON encoding.

func (*Builder) Level

func (b *Builder) Level(level string) *Builder

Level sets the logging level (Default info).

func (*Builder) LevelKey

func (b *Builder) LevelKey(key string) *Builder

LevelKey sets the level field key.

func (*Builder) LevelValue

func (b *Builder) LevelValue(level zapcore.Level) *Builder

LevelValue sets the logging level using zapcore.Level.

func (*Builder) LineEnding

func (b *Builder) LineEnding(ending string) *Builder

LineEnding sets the line ending.

func (*Builder) LowercaseLevel

func (b *Builder) LowercaseLevel() *Builder

LowercaseLevel sets lowercase level encoding.

func (*Builder) MessageKey

func (b *Builder) MessageKey(key string) *Builder

MessageKey sets the message field key.

func (*Builder) MustBuild

func (b *Builder) MustBuild() *zap.Logger

MustBuild creates the logger and panics on error.

func (*Builder) Name

func (b *Builder) Name(name string) *Builder

Name sets the logger name.

func (*Builder) NameKey

func (b *Builder) NameKey(key string) *Builder

NameKey sets the name field key.

func (*Builder) NanosDuration

func (b *Builder) NanosDuration() *Builder

NanosDuration sets nanoseconds duration encoding.

func (*Builder) NoSampling

func (b *Builder) NoSampling() *Builder

NoSampling disables sampling.

func (*Builder) OutputPaths

func (b *Builder) OutputPaths(paths ...string) *Builder

OutputPaths sets the output paths.

func (*Builder) RFC3339Time

func (b *Builder) RFC3339Time() *Builder

RFC3339Time sets RFC3339 time encoding.

func (*Builder) Sampling

func (b *Builder) Sampling(initial int, thereafter int) *Builder

Sampling sets the sampling configuration.

func (*Builder) SecondsDuration

func (b *Builder) SecondsDuration() *Builder

SecondsDuration sets seconds duration encoding.

func (*Builder) ServiceName

func (b *Builder) ServiceName(name string) *Builder

ServiceName adds service name to initial fields.

func (*Builder) ShortCaller

func (b *Builder) ShortCaller() *Builder

ShortCaller sets short caller encoding.

func (*Builder) Silent

func (b *Builder) Silent() *Builder

Silent log messages (mostly used for testing).

func (*Builder) StacktraceKey

func (b *Builder) StacktraceKey(key string) *Builder

StacktraceKey sets the stacktrace field key.

func (*Builder) StringDuration

func (b *Builder) StringDuration() *Builder

StringDuration sets string duration encoding.

func (*Builder) TimeKey

func (b *Builder) TimeKey(key string) *Builder

TimeKey sets the time field key.

func (*Builder) Version

func (b *Builder) Version(version string) *Builder

Version adds version to initial fields.

type BuilderFunc

type BuilderFunc = func(*Builder) *Builder

Jump to

Keyboard shortcuts

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