Skip to main content

Overview

The New() function is the primary constructor for creating Logger instances in go_logs v3. It uses the Option pattern for flexible, readable configuration.

Function Signature

func New(opts ...Option) (Logger, error)
opts
...Option
Zero or more Option functions to configure the logger (WithLevel, WithOutput, WithFormatter, etc.)
Returns:
  • Logger - A configured Logger instance
  • error - An error if configuration fails (e.g., invalid file path)

Default Configuration

If no options are provided, the logger uses sensible defaults:
SettingDefault ValueDescription
LevelInfoLevelMinimum log level
Outputos.StdoutWhere logs are written
FormatterTextFormatterLog format (or from LOG_FORMAT env var)
Hooks[] (empty)No hooks configured
RedactornilNo redaction
CallerfalseCaller info disabled
StackTracefalseStack traces disabled
Example:
// Logger with all defaults
logger, err := go_logs.New()
if err != nil {
    log.Fatal(err)
}

logger.Info("Server started") // Uses defaults

Configuration Options

WithLevel

Sets the minimum log level threshold.
func WithLevel(level Level) Option
level
Level
required
Minimum level: TraceLevel (10), DebugLevel (20), InfoLevel (30), WarnLevel (40), ErrorLevel (50), FatalLevel (60), SilentLevel (0)
Example:
logger, _ := go_logs.New(
    go_logs.WithLevel(go_logs.DebugLevel),
)

logger.Debug("This will be logged")
logger.Trace("This will be filtered out")

WithOutput

Sets where logs are written.
func WithOutput(output io.Writer) Option
output
io.Writer
required
Any io.Writer (os.Stdout, os.Stderr, file, buffer, custom writer)
Example:
file, _ := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
defer file.Close()

logger, _ := go_logs.New(
    go_logs.WithOutput(file),
)

logger.Info("Logged to file")

WithFormatter

Sets the log format.
func WithFormatter(formatter Formatter) Option
formatter
Formatter
required
TextFormatter (colored output for development) or JSONFormatter (structured JSON for production)
Example:
// JSON formatter for production
logger, _ := go_logs.New(
    go_logs.WithFormatter(go_logs.NewJSONFormatter()),
)

logger.Info("User login", go_logs.String("user_id", "123"))
// Output: {"timestamp":"2026-03-03T10:30:00Z","level":"INFO","message":"User login","user_id":"123"}

// Text formatter for development
devLogger, _ := go_logs.New(
    go_logs.WithFormatter(go_logs.NewTextFormatter()),
)

devLogger.Info("Server started")
// Output: 2026/03/03 10:30:00 [INFO] Server started

WithRotatingFile

Configures automatic log file rotation by size.
func WithRotatingFile(filename string, maxSizeMB int, maxBackups int) Option
filename
string
required
Path to the log file (e.g., “/var/log/app.log”)
maxSizeMB
int
required
Maximum file size in MB before rotation (e.g., 100)
maxBackups
int
required
Number of backup files to keep (e.g., 5)
Example:
logger, err := go_logs.New(
    go_logs.WithRotatingFile("/var/log/app.log", 100, 5),
)
if err != nil {
    log.Fatal(err)
}

// Automatically rotates when app.log reaches 100MB
// Keeps: app.log, app.log.1, app.log.2, app.log.3, app.log.4, app.log.5

WithHook

Adds a hook for custom log processing.
func WithHook(hook Hook) Option
hook
Hook
required
A Hook interface implementation for custom processing (e.g., SlackHook, MetricsHook)
Example:
import "github.com/drossan/go_logs/hooks"

slackHook := hooks.NewSlackHook("xoxb-token", "C123456", go_logs.ErrorLevel)

logger, _ := go_logs.New(
    go_logs.WithHook(slackHook),
)

// Errors and above are sent to Slack
logger.Error("Database connection failed", go_logs.Err(err))

WithRedactor

Enables automatic redaction of sensitive fields.
func WithRedactor(keys ...string) Option
keys
...string
required
Field keys to redact (e.g., “password”, “token”, “api_key”)
Example:
logger, _ := go_logs.New(
    go_logs.WithRedactor("password", "token", "api_key"),
)

logger.Info("User login",
    go_logs.String("username", "john"),
    go_logs.String("password", "secret123"),
)
// Output: INFO User login username=john password=***
Common Redaction:
// Redacts: password, passwd, pwd, token, secret, api_key, apikey, authorization, auth
logger, _ := go_logs.New(
    go_logs.WithCommonRedaction(),
)

WithCaller

Enables automatic capture of caller information (file, line, function).
func WithCaller(enabled bool) Option
enabled
bool
required
true to enable caller information, false to disable
Example:
logger, _ := go_logs.New(
    go_logs.WithCaller(true),
)

logger.Info("Server started")
// Output: 2026/03/03 10:30:00 [INFO] main.go:42 main() Server started

WithCallerLevel

Enables automatic caller capture only for specific levels and above.
func WithCallerLevel(level Level) Option
level
Level
required
Minimum level for automatic caller capture (default: ErrorLevel)
Example:
logger, _ := go_logs.New(
    go_logs.WithCallerLevel(go_logs.ErrorLevel),
)

// No caller info for Info
logger.Info("Normal operation")

// Caller info automatically added for Error
logger.Error("Failed to connect", go_logs.Err(err))
// Output: 2026/03/03 10:30:00 [ERROR] service.go:123 Connect() Failed to connect error=...

WithStackTrace

Enables stack trace capture.
func WithStackTrace(enabled bool) Option
enabled
bool
required
true to enable stack traces, false to disable
Example:
logger, _ := go_logs.New(
    go_logs.WithStackTrace(true),
    go_logs.WithStackTraceLevel(go_logs.ErrorLevel),
)

logger.Error("Critical error", go_logs.Err(err))
// Output includes full stack trace for errors

WithMultiOutput

Writes logs to multiple outputs simultaneously.
func WithMultiOutput(writers ...io.Writer) Option
writers
...io.Writer
required
Multiple io.Writer destinations (e.g., stdout + file)
Example:
file, _ := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
defer file.Close()

logger, _ := go_logs.New(
    go_logs.WithMultiOutput(os.Stdout, file),
)

// Logs to both console and file
logger.Info("Server started")

Complete Examples

Development Logger

devLogger, err := go_logs.New(
    go_logs.WithLevel(go_logs.DebugLevel),
    go_logs.WithFormatter(go_logs.NewTextFormatter()),
    go_logs.WithOutput(os.Stdout),
    go_logs.WithCaller(true),
)
if err != nil {
    log.Fatal(err)
}

devLogger.Debug("Starting service", go_logs.String("env", "development"))

Production Logger

prodLogger, err := go_logs.New(
    go_logs.WithLevel(go_logs.InfoLevel),
    go_logs.WithFormatter(go_logs.NewJSONFormatter()),
    go_logs.WithRotatingFile("/var/log/app.log", 100, 10),
    go_logs.WithCommonRedaction(),
    go_logs.WithCallerLevel(go_logs.ErrorLevel),
    go_logs.WithStackTraceLevel(go_logs.ErrorLevel),
)
if err != nil {
    log.Fatal(err)
}
defer prodLogger.Sync()

prodLogger.Info("Application started",
    go_logs.String("version", "1.0.0"),
    go_logs.String("env", "production"),
)

Service Logger with Hooks

import "github.com/drossan/go_logs/hooks"

slackHook := hooks.NewSlackHook(
    os.Getenv("SLACK_TOKEN"),
    os.Getenv("SLACK_CHANNEL_ID"),
    go_logs.ErrorLevel,
)

logger, err := go_logs.New(
    go_logs.WithLevel(go_logs.InfoLevel),
    go_logs.WithFormatter(go_logs.NewJSONFormatter()),
    go_logs.WithOutput(os.Stdout),
    go_logs.WithHook(slackHook),
)
if err != nil {
    log.Fatal(err)
}

// Errors are logged to stdout AND sent to Slack
logger.Error("Payment processing failed",
    go_logs.String("order_id", "12345"),
    go_logs.Err(err),
)

Multi-Environment Logger

func NewLogger(env string) (go_logs.Logger, error) {
    opts := []go_logs.Option{
        go_logs.WithLevel(go_logs.InfoLevel),
    }

    switch env {
    case "development":
        opts = append(opts,
            go_logs.WithLevel(go_logs.DebugLevel),
            go_logs.WithFormatter(go_logs.NewTextFormatter()),
            go_logs.WithOutput(os.Stdout),
            go_logs.WithCaller(true),
        )
    case "production":
        opts = append(opts,
            go_logs.WithFormatter(go_logs.NewJSONFormatter()),
            go_logs.WithRotatingFile("/var/log/app.log", 100, 10),
            go_logs.WithCommonRedaction(),
            go_logs.WithCallerLevel(go_logs.ErrorLevel),
        )
    }

    return go_logs.New(opts...)
}

Error Handling

Configuration Errors

logger, err := go_logs.New(
    go_logs.WithRotatingFile("/invalid/path/app.log", 100, 5),
)
if err != nil {
    // Handle configuration errors
    log.Fatalf("Failed to create logger: %v", err)
}

Common Errors

ErrorCauseSolution
”failed to create rotating file writer”Invalid file path or permissionsCheck path exists and is writable
”failed to create enhanced rotating file writer”Invalid rotation configurationVerify maxSizeMB > 0 and maxBackups >= 0

Environment Variables

The New() function respects environment variables for default configuration:
# Set default log level
export LOG_LEVEL=debug

# Set default format (text or json)
export LOG_FORMAT=json
Example:
// Uses LOG_FORMAT and LOG_LEVEL from environment
logger, _ := go_logs.New()

// Override environment with explicit options
logger, _ := go_logs.New(
    go_logs.WithLevel(go_logs.InfoLevel), // Overrides LOG_LEVEL
)

Performance Considerations

Zero Overhead Options

The following options have zero performance overhead:
  • WithLevel - Fast-path filtering
  • WithFormatter - Same performance for Text/JSON
  • WithOutput - Direct write

Low Overhead Options

Minimal performance impact:
  • WithRedactor - Only processes configured keys
  • WithCallerLevel - Only captures when level threshold met
  • WithRotatingFile - Buffered writes

Higher Overhead Options

Use these selectively:
  • WithCaller(true) - Runtime stack inspection on every log
  • WithStackTrace(true) - Full stack capture
  • WithHook - Depends on hook implementation

Thread Safety

The New() function is thread-safe. You can create multiple loggers concurrently:
var wg sync.WaitGroup
loggers := make([]go_logs.Logger, 10)

for i := 0; i < 10; i++ {
    wg.Add(1)
    go func(idx int) {
        defer wg.Done()
        logger, _ := go_logs.New(
            go_logs.WithLevel(go_logs.InfoLevel),
        )
        loggers[idx] = logger
    }(i)
}

wg.Wait()

See Also

Build docs developers (and LLMs) love