Files
goplt/docs/content/adr/0012-logger-interface-design.md

1.6 KiB

ADR-0012: Logger Interface Design

Status

Accepted

Context

We're using zap for logging, but want to abstract it behind an interface for:

  • Testability (mock logger in tests)
  • Flexibility (could swap implementations)
  • Module compatibility (modules use interface, not concrete type)

We need to decide on the interface design.

Decision

Create a simple logger interface that matches zap's API pattern but uses generic types:

type Field interface {
    // Field represents a key-value pair for structured logging
}

type Logger interface {
    Debug(msg string, fields ...Field)
    Info(msg string, fields ...Field)
    Warn(msg string, fields ...Field)
    Error(msg string, fields ...Field)
    With(fields ...Field) Logger
}

Implementation:

  • Use zap.Field as the Field type (no abstraction needed for now)
  • Provide helper functions in pkg/logger for creating fields:
    func String(key, value string) Field
    func Int(key string, value int) Field
    func Error(err error) Field
    

Rationale:

  • Simple interface that modules can depend on
  • Matches zap's usage patterns
  • Easy to test with mock implementations
  • Allows future swap if needed (though unlikely)

Consequences

Positive

  • Clean abstraction for modules
  • Testable with mocks
  • Simple API for modules to use

Negative

  • Slight indirection overhead
  • Need to maintain interface compatibility

Implementation Notes

  • Define interface in pkg/logger/logger.go
  • Implement in internal/logger/zap_logger.go
  • Export helper functions in pkg/logger/fields.go
  • Modules import pkg/logger, not internal/logger