Skip to content

Minimalistic go logging package with opinionated logging levels

License

Notifications You must be signed in to change notification settings

akademic/go-logger

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

What it for?

This package is a simple logging library for Go. It uses "log" package from stdlib to print logs, but wraps it with minimal logging levels and prefixes support.

FEATURES

  • Only stdlib dependencies
  • Error, Info, Debug levels (Errors print always, Info and Debug only if configured)
  • Logging with prefixes. Log output with particular prefix can be controlled with config with same levels (Error, Info, Debug)

INSTALL

go get github.com/akademic/go-logger

USAGE

Full example

package main

import (
    "github.com/akademic/go-logger"
)

func main() {
    l := logger.New("", logger.Config{
        Level: logger.LogDebug,
        ComponentLevel: map[string]logger.LogLevel{
            "db": logger.LogError,
            "api": logger.LogInfo,
        },
    })

    l.Error("number: %d", 1) // [err] number: 1
    l.Info("number: %d", 2) // [inf] number: 2
    l.Debug("number: %d", 3) // [dbg] number: 3

    dbL := l.WithPrefix("db")

    dbL.Error("number: %d", 1) // [err] [db] number: 1
    dbL.Info("number: %d", 2) // nothing because db level is set to Error
    dbL.Debug("number: %d", 3) // nothing because db level is set to Error

    apiL := l.WithPrefix("api")

    apiL.Error("number: %d", 1) // [err] [api] number: 1
    apiL.Info("number: %d", 2) // [inf] [api] number: 2
    apiL.Debug("number: %d", 3) // nothing because api level is set to Info
}

Architecture example

Prefixes can be used to control log output for different components of the application. In this example, we have a database and an API. We want to log only errors from the database and info from the API.

package main

import (
    "github.com/akademic/go-logger"
)

func main() {
	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer stop()

    l := logger.New("", logger.Config{
        Level: logger.LogDebug,
        ComponentLevel: map[string]logger.LogLevel{
            "db": logger.LogError,
            "api": logger.LogInfo,
        },
    })

    dbL := l.WithPrefix("db")
    repository, err := NewRepository(dbL)
    if err != nil {
        l.Error("failed to create repository: %v", err)
        return
    }

    apiL := l.WithPrefix("api")
    api, err := NewAPI(apiL, repository)
    if err != nil {
        l.Error("failed to create api: %v", err)
        return
    }

    go api.Start()

    <-ctx.Done()
}

Interface

This package provides a simple interface for logging.

type Logger interface {
    WithPrefix(prefix string) Logger // returns a new logger with a prefix, prefix is replaced with new
    Error(format string, args ...interface{})
    Info(format string, args ...interface{})
    Debug(format string, args ...interface{})
}

Use it to receive a logger instance.

func NewAPI(l logger.Logger) (*API, error) {
    // ...
    l.Info("api started")
    // ...
    adminApiLogger := l.WithPrefix("admin-api")

    adminApiLogger.Info("admin api started") // [inf] [admin-api] admin api started

    customerApiLogger := l.WithPrefix("customer-api")

    customerApiLogger.Info("customer api started") // [inf] [customer-api] customer api started
}

Output redirection

As it uses "log" package from stdlib, you can redirect output to a file or any other io.Writer.

Redirect to a file

package main

import (
    "github.com/akademic/go-logger"
    "log"
    "os"
)

func main() {
    f, err := os.OpenFile("log.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        fmt.Fatalf("failed to open log file: %v", err)
    }
    defer f.Close()

    log.SetOutput(f)

    l := logger.New("", logger.Config{
        Level: logger.LogDebug,
        ComponentLevel: map[string]logger.LogLevel{
            "db": logger.LogError,
            "api": logger.LogInfo,
        },
    })

    l.Info("number: %d", 2) // [inf] number: 2
}

Redirect to remote syslog over udp

package main

import (
    "github.com/akademic/go-logger"
    "log"
    "log/syslog"
)

func main() {
    syslogWriter, err := syslog.Dial("udp", "syslog-server:514", syslog.LOG_INFO, "myapp")
    if err != nil {
        fmt.Fatalf("failed to connect to syslog server: %v", err)
    }

    log.SetOutput(syslogWriter)

    l := logger.New("", logger.Config{
        Level: logger.LogDebug,
        ComponentLevel: map[string]logger.LogLevel{
            "db": logger.LogError,
            "api": logger.LogInfo,
        },
    })

    l.Info("number: %d", 2) // [inf] number: 2
}

About

Minimalistic go logging package with opinionated logging levels

Topics

Resources

License

Stars

Watchers

Forks

Languages