Skip to content

Migration Guide ​

If you are using another log library, this guide helps you migrate your project to DD quickly.

From the Standard Library log ​

API Mapping ​

logDDNotes
log.Print(msg)dd.Info(msg)Info level
log.Printf(format, args)dd.Infof(format, args)Formatted
log.Println(msg)dd.Info(msg)Info level
log.Fatal(msg)dd.Fatal(msg)Fatal (calls os.Exit)
log.Fatalf(format, args)dd.Fatalf(format, args)Formatted Fatal
log.Panic(msg)dd.Error(msg) + panic()DD has no built-in Panic
—dd.InfoWith(msg, fields...)Structured logging (new)

Basic Migration ​

go
// Before: log
log.Printf("user %s login failed: %v", username, err)

// After: DD
dd.Infof("user %s login failed: %v", username, err)

// Or using structured logging
dd.ErrorWith("user login failed",
    dd.String("username", username),
    dd.Err(err),
)

Replace the Global Logger ​

go
// Before: log
log.SetOutput(file)
log.SetFlags(log.LstdFlags | log.Lshortfile)

// After: DD
logger, err := dd.New(dd.Config{
    Level:  dd.LevelInfo,
    Format: dd.FormatText,
    Targets: []dd.OutputTarget{
        dd.FileOutput("logs/app.log"),
    },
})
if err != nil {
    log.Fatal(err)
}
dd.SetDefault(logger)

From slog ​

API Mapping ​

slogDDNotes
slog.Info(msg)dd.Info(msg)Info level
slog.Info(msg, "key", value)dd.InfoWith(msg, dd.String("key", value))Structured
slog.Debug(msg)dd.Debug(msg)Debug level
slog.Error(msg, "err", err)dd.ErrorWith(msg, dd.Err(err))Error log
slog.Warn(msg)dd.Warn(msg)Warn level
slog.With("key", value)dd.WithFields(dd.String("key", value))Preset fields
slog.New(handler)dd.New(cfg)Create instance
slog.SetDefault(logger)dd.SetDefault(logger)Set global

Structured Logging Migration ​

go
// Before: slog
slog.Info("request completed",
    "method", "GET",
    "status", 200,
    "duration", 150*time.Millisecond,
)

// After: DD
dd.InfoWith("request completed",
    dd.String("method", "GET"),
    dd.Int("status", 200),
    dd.Duration("duration", 150*time.Millisecond),
)

Type Safety

slog uses any key-value pairs; DD uses type-specific field constructors. Type errors are caught at compile time.

From zap ​

API Mapping ​

zapDDNotes
zap.L().Info(msg, zap.Field...)dd.InfoWith(msg, dd.Field...)Structured
zap.String(key, val)dd.String(key, val)String field
zap.Int(key, val)dd.Int(key, val)Integer field
zap.Error(err)dd.Err(err)Error field
zap.Any(key, val)dd.Any(key, val)Any type
zap.Sugar().Infof(...)dd.Infof(...)Formatted
logger.With(zap.Field...)logger.WithFields(dd.Field...)Preset fields
zapcore.NewCore(...)dd.New(dd.Config{...})Create instance

Configuration Mapping ​

go
// Before: zap
cfg := zap.Config{
    Level:       zap.NewAtomicLevelAt(zap.InfoLevel),
    Encoding:    "json",
    OutputPaths: []string{"stdout", "logs/app.log"},
}
logger, _ := cfg.Build()

// After: DD
logger, err := dd.New(dd.Config{
    Level:  dd.LevelInfo,
    Format: dd.FormatJSON,
    Targets: []dd.OutputTarget{
        dd.ConsoleOutput(),
        dd.FileOutput("logs/app.json"),
    },
})
if err != nil {
    log.Fatal(err)
}

Field Mapping ​

go
// Before: zap
logger.Info("request",
    zap.String("method", "GET"),
    zap.Int("status", 200),
    zap.Duration("elapsed", 150*time.Millisecond),
    zap.Error(err),
)

// After: DD
dd.InfoWith("request",
    dd.String("method", "GET"),
    dd.Int("status", 200),
    dd.Duration("elapsed", 150*time.Millisecond),
    dd.Err(err),
)

From logrus ​

API Mapping ​

logrusDDNotes
logrus.Info(msg)dd.Info(msg)Info level
logrus.WithField("k", v)dd.WithField("k", v)Single field
logrus.WithFields(logrus.Fields{...})dd.WithFields(dd.String(...), ...)Multiple fields
logrus.SetLevel(logrus.InfoLevel)dd.SetLevel(dd.LevelInfo)Set level
logrus.SetFormatter(&logrus.JSONFormatter{})dd.New(dd.Config{Format: dd.FormatJSON})JSON format
logrus.SetOutput(file)dd.Config{Targets: ...}Output target
logrus.Fatal(msg)dd.Fatal(msg)Fatal

Field Migration ​

go
// Before: logrus
logrus.WithFields(logrus.Fields{
    "method":  "GET",
    "status":  200,
    "elapsed": 150 * time.Millisecond,
}).Info("Request completed")

// After: DD
dd.WithFields(
    dd.String("method", "GET"),
    dd.Int("status", 200),
    dd.Duration("elapsed", 150*time.Millisecond),
).Info("Request completed")

DD-Exclusive Features ​

After migrating, you can take advantage of DD's unique features:

FeatureDescriptionDocs
Sensitive-data filteringAuto-redact passwords, API keys, etc.Sensitive Data Filtering
Audit loggingAsynchronous security-event recordingAudit Logging
HMAC signingTamper-protection for logsHMAC Signing In Practice
Industry complianceHIPAA/PCI-DSS presetsIndustry Compliance Configuration
Lifecycle hooks6 hook eventsHook System
LoggerRecorderTest helperTesting Patterns

Next Steps ​