mtlog

Quick Reference

A quick reference for all mtlog features and common usage patterns.

Basic Setup

import (
    "github.com/willibrandon/mtlog"
    "github.com/willibrandon/mtlog/core"
)

// Simple logger
logger := mtlog.New(mtlog.WithConsole())

// Production logger
logger := mtlog.New(
    mtlog.WithConsoleTheme("dark"),
    mtlog.WithSeq("http://localhost:5341", "api-key"),
    mtlog.WithMinimumLevel(core.InformationLevel),
)

Logging Methods

Traditional Methods

logger.Verbose("Verbose message")
logger.Debug("Debug: {Value}", value)
logger.Information("Info: {User} {Action}", user, action)
logger.Warning("Warning: {Count} items", count)
logger.Error("Error: {Error}", err)
logger.Fatal("Fatal: {Reason}", reason)

Generic Methods (Type-Safe)

logger.VerboseT("Verbose message")
logger.DebugT("Debug: {Value}", value)
logger.InformationT("Info: {User} {Action}", user, action)
logger.WarningT("Warning: {Count} items", count)
logger.ErrorT("Error: {Error}", err)
logger.FatalT("Fatal: {Reason}", reason)

Short Methods

logger.V("Verbose")
logger.D("Debug: {Value}", value)
logger.I("Info: {Message}", msg)
logger.W("Warning: {Issue}", issue)
logger.E("Error: {Error}", err)
logger.F("Fatal: {Reason}", reason)

Message Templates

Template Syntaxes

// Traditional syntax
log.Information("User {UserId} logged in from {IP}", userId, ipAddress)

// Go template syntax
log.Information("User {{.UserId}} logged in from {{.IP}}", userId, ipAddress)

// Mixed syntax
log.Information("User {UserId} ({{.Username}}) from {IP}", userId, username, ipAddress)

Capturing Hints

// @ - capture complex types
log.Information("Order {@Order} created", order)

// $ - force scalar rendering
log.Information("Error occurred: {$Error}", err)

Format Specifiers

// Numbers
log.Information("Count: {Count:000}", 42)        // 042
log.Information("Price: ${Price:F2}", 123.456)   // $123.46
log.Information("Usage: {Percent:P1}", 0.85)     // 85.0%

// Custom alignment
log.Information("Status: {Status,10}", "OK")     // "OK        "
log.Information("Code: {Code,-5}", "ABC")        // "ABC  "

Output Templates

Console Templates

// Simple
mtlog.WithConsoleTemplate("[${Level:u3}] ${Message}")

// With timestamp
mtlog.WithConsoleTemplate("[${Timestamp:HH:mm:ss} ${Level:u3}] ${Message}")

// Full details
mtlog.WithConsoleTemplate(
    "[${Timestamp:yyyy-MM-dd HH:mm:ss} ${Level:u3}] {SourceContext}: ${Message}${NewLine}${Exception}")

File Templates

mtlog.WithFileTemplate("app.log", 
    "[${Timestamp:o} ${Level:u3}] {SourceContext} ${Message}${NewLine}${Exception}")

Enrichers

// Built-in enrichers
logger := mtlog.New(
    mtlog.WithTimestamp(),
    mtlog.WithMachineName(),
    mtlog.WithProcessInfo(),
    mtlog.WithEnvironmentVariables("APP_ENV", "VERSION"),
    mtlog.WithThreadId(),
    mtlog.WithCallersInfo(),
    mtlog.WithSourceContext(),
)

// Custom enricher
type UserEnricher struct{ userID int }

func (e *UserEnricher) Enrich(event *core.LogEvent, factory core.LogEventPropertyFactory) {
    event.AddPropertyIfAbsent(factory.CreateProperty("UserId", e.userID))
}

logger := mtlog.New(
    mtlog.WithEnricher(&UserEnricher{userID: 123}),
)

Filters

// Level filtering
mtlog.WithMinimumLevel(core.WarningLevel)

// Level overrides by source
mtlog.WithMinimumLevelOverrides(map[string]core.LogEventLevel{
    "myapp/services": core.DebugLevel,
    "github.com/gin-gonic/gin": core.WarningLevel,
})

// Custom filter
mtlog.WithFilter(filters.NewPredicateFilter(func(e *core.LogEvent) bool {
    return !strings.Contains(e.MessageTemplate.Text, "health-check")
}))

// Rate limiting
mtlog.WithFilter(filters.NewRateLimitFilter(100, time.Minute))

// Sampling
mtlog.WithFilter(filters.NewSamplingFilter(0.1)) // 10% of events

Sinks

Console

// Themes
mtlog.WithConsoleTheme(sinks.LiterateTheme())
mtlog.WithConsoleTheme(sinks.DarkTheme())
mtlog.WithConsoleTheme(sinks.LightTheme())
mtlog.WithConsoleTheme(sinks.NoColorTheme())

File

// Simple file
mtlog.WithFileSink("app.log")

// Rolling by size
mtlog.WithRollingFile("app.log", 10*1024*1024) // 10MB

// Rolling by time
mtlog.WithRollingFileTime("app.log", time.Hour)

Seq

// Basic
mtlog.WithSeq("http://localhost:5341")

// With API key
mtlog.WithSeq("http://localhost:5341", "your-api-key")

// Dynamic level control
levelOption, levelSwitch, controller := mtlog.WithSeqLevelControl(
    "http://localhost:5341",
    mtlog.SeqLevelControllerOptions{
        CheckInterval: 30*time.Second,
    },
)

Async & Durable

// Async wrapper
mtlog.WithAsync(mtlog.WithFileSink("app.log"))

// Durable buffering
mtlog.WithDurable(
    mtlog.WithSeq("http://localhost:5341"),
    sinks.WithDurableDirectory("./logs/buffer"),
    sinks.WithDurableMaxSize(100*1024*1024),
)

ForType - Type-Based Logging

// Automatic SourceContext from types
userLogger := mtlog.ForType[User](logger)
userLogger.Information("User created") // SourceContext: "User"

// Service pattern
type UserService struct {
    logger core.Logger
}

func NewUserService(base core.Logger) *UserService {
    return &UserService{
        logger: mtlog.ForType[UserService](base),
    }
}

// Advanced options
opts := mtlog.TypeNameOptions{
    IncludePackage: true,
    Prefix: "MyApp.",
}
name := mtlog.ExtractTypeName[User](opts) // "MyApp.mypackage.User"

LogContext - Scoped Properties

// Add properties to context
ctx := context.Background()
ctx = mtlog.PushProperty(ctx, "RequestId", "req-123")
ctx = mtlog.PushProperty(ctx, "UserId", userId)

// Use with logger
log := logger.WithContext(ctx)
log.Information("Processing request") // Includes RequestId & UserId

// Property precedence
ctx = mtlog.PushProperty(ctx, "UserId", 123)
logger.WithContext(ctx).Information("Test")                          // UserId=123
logger.WithContext(ctx).ForContext("UserId", 456).Information("Test") // UserId=456
logger.WithContext(ctx).Information("User {UserId}", 789)            // UserId=789

Dynamic Level Control

// Manual control
levelSwitch := mtlog.NewLoggingLevelSwitch(core.InformationLevel)
logger := mtlog.New(
    mtlog.WithLevelSwitch(levelSwitch),
    mtlog.WithConsole(),
)

// Change at runtime
levelSwitch.SetLevel(core.DebugLevel)

// Fluent interface
levelSwitch.Debug().Information().Warning()

// Check if enabled
if levelSwitch.IsEnabled(core.VerboseLevel) {
    // Expensive operation
}

Ecosystem Compatibility

slog (Standard Library)

// Use mtlog as slog backend
slogger := mtlog.NewSlogLogger(
    mtlog.WithSeq("http://localhost:5341"),
    mtlog.WithMinimumLevel(core.InformationLevel),
)

// Set as default
slog.SetDefault(slogger)

// Use slog API
slog.Info("user logged in", "user_id", 123, "ip", "192.168.1.1")

logr (Kubernetes)

// Use mtlog as logr backend
import mtlogr "github.com/willibrandon/mtlog/adapters/logr"

logrLogger := mtlogr.NewLogger(
    mtlog.WithConsole(),
    mtlog.WithMinimumLevel(core.DebugLevel),
)

// Use logr API
logrLogger.Info("reconciling", "namespace", "default", "name", "my-app")
logrLogger.Error(err, "failed to update resource")