Logrus provides several interfaces for compatibility with other logging systems and for abstraction in application code.
Interface compatible with Go's standard library logger. Allows functions to accept both stdlib logger and logrus logger.
type StdLogger interface {
Print(...interface{})
Printf(string, ...interface{})
Println(...interface{})
Fatal(...interface{})
Fatalf(string, ...interface{})
Fatalln(...interface{})
Panic(...interface{})
Panicf(string, ...interface{})
Panicln(...interface{})
}Both *logrus.Logger and *logrus.Entry implement this interface, as does *log.Logger from the standard library.
import (
"log"
logrus "github.com/sirupsen/logrus"
)
// Function accepts any standard logger
func ProcessWithLogging(logger logrus.StdLogger) {
logger.Printf("Processing started")
logger.Println("Processing complete")
}
func main() {
// Use with standard library logger
stdLogger := log.New(os.Stdout, "app: ", log.LstdFlags)
ProcessWithLogging(stdLogger)
// Use with logrus
logrusLogger := logrus.New()
ProcessWithLogging(logrusLogger)
// Use with logrus entry
entry := logrusLogger.WithField("component", "processor")
ProcessWithLogging(entry)
}Interface that generalizes Logger and Entry types. Use in application code to accept either logger instances or entries with fields.
type FieldLogger interface {
WithField(key string, value interface{}) *Entry
WithFields(fields Fields) *Entry
WithError(err error) *Entry
Debugf(format string, args ...interface{})
Infof(format string, args ...interface{})
Printf(format string, args ...interface{})
Warnf(format string, args ...interface{})
Warningf(format string, args ...interface{})
Errorf(format string, args ...interface{})
Fatalf(format string, args ...interface{})
Panicf(format string, args ...interface{})
Debug(args ...interface{})
Info(args ...interface{})
Print(args ...interface{})
Warn(args ...interface{})
Warning(args ...interface{})
Error(args ...interface{})
Fatal(args ...interface{})
Panic(args ...interface{})
Debugln(args ...interface{})
Infoln(args ...interface{})
Println(args ...interface{})
Warnln(args ...interface{})
Warningln(args ...interface{})
Errorln(args ...interface{})
Fatalln(args ...interface{})
Panicln(args ...interface{})
}Both *logrus.Logger and *logrus.Entry implement this interface.
import (
logrus "github.com/sirupsen/logrus"
)
type Service struct {
logger logrus.FieldLogger
}
func NewService(logger logrus.FieldLogger) *Service {
return &Service{
logger: logger,
}
}
func (s *Service) DoWork() {
s.logger.Info("Starting work")
// Add fields to context
workLogger := s.logger.WithFields(logrus.Fields{
"task": "processing",
"id": 123,
})
workLogger.Debug("Processing item")
workLogger.Info("Work complete")
}
func main() {
// Use with logger
logger := logrus.New()
service1 := NewService(logger)
service1.DoWork()
// Use with entry (already has fields)
entry := logger.WithField("component", "worker")
service2 := NewService(entry)
service2.DoWork()
}Extension of FieldLogger that adds Trace-level methods. Superfluous interface kept for consistency. Use Logger or Entry directly instead.
type Ext1FieldLogger interface {
FieldLogger
Tracef(format string, args ...interface{})
Trace(args ...interface{})
Traceln(args ...interface{})
}Interface for custom log formatters. Implement this to create custom output formats.
type Formatter interface {
Format(*Entry) ([]byte, error)
}Both TextFormatter and JSONFormatter implement this interface.
import (
"fmt"
"bytes"
logrus "github.com/sirupsen/logrus"
)
type CustomFormatter struct{}
func (f *CustomFormatter) Format(entry *logrus.Entry) ([]byte, error) {
var b *bytes.Buffer
if entry.Buffer != nil {
b = entry.Buffer
} else {
b = &bytes.Buffer{}
}
// Custom format: [LEVEL] Message (field1=value1, field2=value2)
b.WriteString(fmt.Sprintf("[%s] %s", entry.Level.String(), entry.Message))
if len(entry.Data) > 0 {
b.WriteString(" (")
first := true
for k, v := range entry.Data {
if !first {
b.WriteString(", ")
}
b.WriteString(fmt.Sprintf("%s=%v", k, v))
first = false
}
b.WriteString(")")
}
b.WriteByte('\n')
return b.Bytes(), nil
}
func main() {
logger := logrus.New()
logger.SetFormatter(&CustomFormatter{})
logger.WithFields(logrus.Fields{
"animal": "walrus",
"size": 10,
}).Info("A walrus appears")
}Output:
[info] A walrus appears (animal=walrus, size=10)Interface for log hooks. Implement this to extend logging functionality.
type Hook interface {
Levels() []Level
Fire(*Entry) error
}See Hooks for detailed documentation and examples.
Interface for custom buffer pools. Implement this to provide custom buffer management for performance optimization.
type BufferPool interface {
Put(*bytes.Buffer)
Get() *bytes.Buffer
}import (
"bytes"
"sync"
logrus "github.com/sirupsen/logrus"
)
type CustomBufferPool struct {
pool sync.Pool
}
func (p *CustomBufferPool) Put(buf *bytes.Buffer) {
buf.Reset()
p.pool.Put(buf)
}
func (p *CustomBufferPool) Get() *bytes.Buffer {
buf := p.pool.Get()
if buf == nil {
return &bytes.Buffer{}
}
return buf.(*bytes.Buffer)
}
func main() {
logger := logrus.New()
logger.SetBufferPool(&CustomBufferPool{})
logger.Info("Using custom buffer pool")
}Use interfaces to inject loggers into components for testability:
type UserService struct {
logger logrus.FieldLogger
db Database
}
func NewUserService(logger logrus.FieldLogger, db Database) *UserService {
return &UserService{
logger: logger.WithField("component", "user-service"),
db: db,
}
}Use test hooks or null loggers for testing:
import (
"testing"
logrus "github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
)
func TestUserService(t *testing.T) {
logger, hook := test.NewNullLogger()
service := NewUserService(logger, mockDB)
service.CreateUser("test")
assert.Equal(t, 1, len(hook.AllEntries()))
assert.Contains(t, hook.LastEntry().Message, "user created")
}Accept StdLogger for minimal functionality, FieldLogger for structured logging:
// Minimal logging - accepts stdlib or logrus
func SimpleFunction(logger logrus.StdLogger) {
logger.Println("Simple message")
}
// Structured logging - accepts logrus logger or entry
func StructuredFunction(logger logrus.FieldLogger) {
logger.WithField("key", "value").Info("Structured message")
}