log

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2022 License: MIT Imports: 10 Imported by: 8

README

Log

Go simple yet powerful logging library

Build status GitHub last commit GitHub commit activity GitHub issues

Focus

This log library focuses on:

  • Human readable logs
  • Dependency injected loggers
  • Thread safety
  • Write to multiple writers

Setup

go get github.com/qdm12/log

Usage

Default logger

The logger constructor log.New() uses functional options.

By default the logger:

package main

import "github.com/qdm12/log"

func main() {
    logger := log.New()
    logger.Info("my message")
    // 2022-03-28T10:03:29Z INFO my message
}

➡️ Source code file

Formatting methods

Each level log method such as Warn(s string) has a corresponding formatting method with a trailing f such as Warnf(format string, args ...interface{}). For example:

package main

import "github.com/qdm12/log"

func main() {
    logger := log.New()
    logger.Warnf("message number %d", 1)
    // 2022-03-29T07:40:12Z WARN message number 1
}

➡️ Source code file

Custom logger

You can customize the logger creation with for example:

package main

import "github.com/qdm12/log"

func main() {
    logger := log.New(
        log.SetLevel(log.LevelDebug),
        log.SetTimeFormat(time.RFC822),
        log.SetWriters(os.Stdout, os.Stderr),
        log.SetComponent("module"),
        log.SetCallerFile(true),
        log.SetCallerFunc(true),
        log.SetCallerLine(true))
    logger.Info("my message")
    // 29 Mar 22 07:16 UTC INFO [module] my message    main.go:L19:main
    // 29 Mar 22 07:16 UTC INFO [module] my message    main.go:L19:main
}

➡️ Source code file

Create a logger from a logger

This should be the preferred way to create additional loggers with different settings, since it favors dependency injection.

For example, we create logger loggerB from loggerA which inherits the settings from loggerA and changes the component setting.

package main

import (
    "github.com/qdm12/log"
)

func main() {
    loggerA := log.New(log.SetComponent("A"))
    loggerB := loggerA.New(log.SetComponent("B"))
    loggerA.Info("my message")
    // 2022-03-29T07:35:08Z INFO [A] my message
    loggerB.Info("my message")
    // 2022-03-29T07:35:08Z INFO [B] my message
}

Note this is a thread safe operation, and thread safety on the writers is also maintained.

➡️ Source code file

Create global loggers

You can create multiple loggers with the global constructor log.New(), and writers will be thread safe to write to. For example the following won't write to the buffer at the same time:

package main

import (
    "bytes"
    "time"

    "github.com/qdm12/log"
)

func main() {
    writer := bytes.NewBuffer(nil)

    timer := time.NewTimer(time.Second)

    const parallelism = 2
    for i := 0; i < parallelism; i++ {
        go func() {
            logger := log.New(log.SetWriters(writer))
            for {
                select {
                case <-timer.C:
                    return
                default:
                    logger.Info("my message")
                }
            }
        }()
    }
}

You can try it with CGO_ENABLED=1 go run -race ./examples/global to ensure there is no data race.

➡️ Source code file

Detailed features

The following features are available:

  • Multiple options available
    • Set the level DEBUG, INFO, WARN, ERROR
    • Set time format, for example time.RFC3339
    • Set or add one or more io.Writer
    • Set a component string
  • Create child loggers inheriting configuration
  • Thread safe per io.Writer for multiple loggers
  • Printf-like methods: Debugf, Infof, Warnf, Errorf
  • Automatic coloring of levels depending on tty
  • Safety to use
    • Full unit test coverage
    • End-to-end race tests
    • Used in the following projects:

Limitations

Using a lot of writers

This logging library is thread safe for each writer. To achieve, it uses a global map from writer address to mutex pointer.

⚠️ This however means that this map will not shrink at any time. If you want to use this logging library with thousands of different writers, you should not use it as it is, please create an issue.

Contributing

See Contributing

License

This repository is under an MIT license

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrLevelNotRecognized = errors.New("level is not recognized")
)

Functions

This section is empty.

Types

type ChildConstructor

type ChildConstructor interface {
	New(options ...Option) *Logger
}

ChildConstructor is the interface to create child loggers.

type Level

type Level uint8

Level is the level of the logger.

const (
	// LevelError is the error level.
	LevelError Level = iota
	// LevelWarn is the warn level.
	LevelWarn
	// LevelInfo is the info level.
	LevelInfo
	// LevelDebug is the debug level.
	LevelDebug
)

func ParseLevel

func ParseLevel(s string) (level Level, err error)

ParseLevel parses a string into a level, and returns an error if it fails.

func (Level) ColoredString

func (level Level) ColoredString() (s string)

ColoredString returns the corresponding colored string for the level.

func (Level) String

func (level Level) String() (s string)

type LeveledLogger

type LeveledLogger interface {
	Debug(s string)
	Info(s string)
	Warn(s string)
	Error(s string)
	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
}

LeveledLogger is the interface to log at different levels.

type Logger

type Logger struct {
	// contains filtered or unexported fields
}

Logger is the logger implementation structure. It is thread safe to use.

func New

func New(options ...Option) *Logger

New creates a new logger, with thread safety each of its writers and other loggers. You can pass options to configure the logger.

func (*Logger) Debug

func (l *Logger) Debug(s string)

Debug logs with the debug level.

func (*Logger) Debugf

func (l *Logger) Debugf(format string, args ...interface{})

Debugf formats and logs at the debug level.

func (*Logger) Error

func (l *Logger) Error(s string)

Error logs with the error level.

func (*Logger) Errorf

func (l *Logger) Errorf(format string, args ...interface{})

Errorf formats and logs at the error level.

func (*Logger) Info

func (l *Logger) Info(s string)

Info logs with the info level.

func (*Logger) Infof

func (l *Logger) Infof(format string, args ...interface{})

Infof formats and logs at the info level.

func (*Logger) New

func (l *Logger) New(options ...Option) *Logger

New creates a child logger inheriting from the settings of the current logger. Options can be passed to modify the settings of the new child logger to be created.

func (*Logger) Patch

func (l *Logger) Patch(options ...Option)

Patch patches the existing settings with any option given. This is thread safe but does not propagates to child loggers.

func (*Logger) Warn

func (l *Logger) Warn(s string)

Warn logs with the warn level.

func (*Logger) Warnf

func (l *Logger) Warnf(format string, args ...interface{})

Warnf formats and logs at the warn level.

type LoggerInterface

type LoggerInterface interface {
	LeveledLogger
	LoggerPatcher
	ChildConstructor
}

type LoggerPatcher

type LoggerPatcher interface {
	Patch(options ...Option)
}

LoggerPatcher is the interface to update the current logger.

type Option

type Option func(s *settings)

Option is the type to specify settings modifier for the logger operation.

func AddWriters

func AddWriters(writers ...io.Writer) Option

AddWriters adds the writers given to the existing writers for the logger. The writers defaults to a single writer of os.Stdout.

func SetCallerFile

func SetCallerFile(enabled bool) Option

SetCallerFile enables or disables logging the caller file. The default is disabled.

func SetCallerFunc

func SetCallerFunc(enabled bool) Option

SetCallerFunc enables or disables logging the caller function. The default is disabled.

func SetCallerLine

func SetCallerLine(enabled bool) Option

SetCallerLine enables or disables logging the caller line number. The default is disabled.

func SetComponent

func SetComponent(component string) Option

SetComponent sets the component for the logger which will be logged on every log operation. Set it to the empty string so no component is logged. The default is the empty string component.

func SetLevel

func SetLevel(level Level) Option

SetLevel sets the level for the logger. The level defaults to the lowest level, error.

func SetTimeFormat

func SetTimeFormat(timeFormat string) Option

SetTimeFormat set the time format for the logger. You can set it to an empty string in order to not log the time. The time format defaults to time.RFC3339.

func SetWriters

func SetWriters(writers ...io.Writer) Option

SetWriters sets the writers for the logger. The writers defaults to a single writer of os.Stdout.

Directories

Path Synopsis
examples
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL