or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

formatters.mdhooks.mdindex.mdinterfaces.md
tile.json

interfaces.mddocs/

Interfaces

Logrus provides several interfaces for compatibility with other logging systems and for abstraction in application code.

StdLogger Interface

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.

StdLogger Usage

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)
}

FieldLogger Interface

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.

FieldLogger Usage

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()
}

Ext1FieldLogger Interface

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{})
}

Formatter 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.

Custom Formatter Example

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)

Hook Interface

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.

BufferPool Interface

Interface for custom buffer pools. Implement this to provide custom buffer management for performance optimization.

type BufferPool interface {
    Put(*bytes.Buffer)
    Get() *bytes.Buffer
}

Custom BufferPool Example

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")
}

Interface Design Patterns

Dependency Injection

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,
    }
}

Testing with Interfaces

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")
}

Multi-level Abstraction

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")
}