logger

package
v0.21.0 Latest Latest
Warning

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

Go to latest
Published: Apr 25, 2024 License: Apache-2.0 Imports: 11 Imported by: 0

README

OpenMFP Logger

The OpenMFP logger is a structured type safe logger that operates on top of Zerolog. It can create JSON formatted logs but also tagged logs for console output.

Initialization

Create a logger instance with the New function and pass it to functions and structs that need it. Please avoid using a global variable logger. Instead create an instance or a component logger that inherits from an existing logger.

// DefaultConfig() returns a config with defaults set
logConfig := logger.DefaultConfig()

// set config values
logConfig.Name = "my-service"
logConfig.Level = "debug"

// ceate logger
log, err := logger.New(logConfig)
if err != nil {
	fmt.Println("failed to create logger: %s", err)
    os.Exit(1)
}

Configuration

You can use DefaultConfig() to create a configuration with preset defaults that can be changed. But it is also possible to initialize the Config{} struct directly. Please make sure to set an output (default is os.Stdout).

type Config struct {
	Name   string
	Level  string
	NoJSON bool
	Output io.Writer
}
Field Description
Name Defines a name field that is appended to every log entry.
Level Sets the minimal level for printing log messages. Can be a string of debug, info, error
NoJSON Turns off JSON output. This is useful for local debugging as it is more human read-able.
Output Output for log messages. Must be an io.Writer. Default is io.Stdout

For testing it is possible to pass a &bytes.Buffer{} as Output to collect logs in a buffer and not print it on stdout.

Usage

The logger uses a chained syntax for creating log entrys. You start with the level you want to log in, then optional fields that further describe the context of an error and finally the message itself.

This will create a log entry with level fatal, sets the error as a field in the log output and prints the message "init failed":

log.Fatal().Err(err).Msg("Init failed")

Fatal is a special level that logs and exits the program.

The following example creates a log entry of type info with several structured fields:

log.Info().Int("count", count).Int("total", number).Str("tenant", tenantID).Msg("Init users")

You can add as many fields as needed. There are functions for all Go types including interface{}. These fields are logged as JSON fields and can be used in Kibana to select messages.

There is a special field function Err(error) for handling errors. Please use this to log errors like this:

log.Error().Err(err).Msg("Failed to load data")

Fields are optionally and can be omitted, the Msg call instead is obligatory:

log.Debug().Msg("Service started")

Never forget to call Msg() otherwise no log entry is created! There is also a Msgf(format, values...) function but try to use fields if possible and create a static log message as it makes creating dashboards in Kibana easier.

Child Logger and Component Logger

There is a helper method log.ChildLogger(key string, value string) that returns a new logger with an added field key with the value value. This can be used to create child loggers that inherit from a given main logger but always include this pre-set field.

This can be handy if a logger is used several times in a function and should for instance always contain the name of the function.

The helper method log.ComponentLogger(component string) is a special version of a child logger that returns a new logger with an added field component. The idea behind this is to create a logger for a component like a specific part of an application and give this field a common name that can be used for in Kibana.

Logr Instance

The helper method log.Logr() returns a log instance of an existing OpenMFP Logger that fulfills the logr.Logger interface from go-logr. This is a common interface that is used in many external packages for instance in the Kubernetes controller runtime.

The returned logger inherits settings from the existing OpenMFP Logger.

Default Logger

The package defines a global default logger as logger.StdLogger. Please only use it when really needed, e.g. in case of refactoring old code. Please always create a new logger instance with New() and pass it to structs and functions. This makes testing easier and is in general best practice.

OpenMFP Logger from Zerolog

Because the OpenMFP logger internally embeds Zerolog it is compatible with new versions of Zerolog. Nevertheless, because of this embeding, some functions return Zerolog instances. It is very easy to return a new OpenMFP logger from a Zerolog instance using this helper function:

log := NewFromZerolog(zerologger)
HTTP Middleware

The logger comes with a HTTP middleware that injects the logger into a context and a helper function to load it from a given context. The middleware is compatible with any Go stdlib compatible router (e.g. http.Mux or Chi).

// create log as logger instance and inject it
router.Use(logger.StoreLoggerMiddleware(log))

// get it from a request context
func(w http.ResponseWriter, r *http.Request) {
    log := LoadFromContext(r.Context())
}

If no logger can be found in the context, LoadFromContext() returns logger.StdLogger.

Documentation

Index

Constants

View Source
const RequestIdLoggerKey = "rid"

Variables

View Source
var ErrInvalidKeyValPair = errors.New("invalid key value pair")
View Source
var StdLogger, _ = New(DefaultConfig())

StdLogger is a global default logger, please use with care and prefer creating your own instance

Functions

func SetLoggerInContext

func SetLoggerInContext(ctx context.Context, log *Logger) context.Context

Types

type Config

type Config struct {
	Name   string
	Level  string
	NoJSON bool
	Output io.Writer
}

Config defines the logger configuration

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a logger configuration with defaults set

func (*Config) SetDefaults

func (c *Config) SetDefaults()

SetDefaults set config default values

type Level

type Level zerolog.Level

type Logger

type Logger struct {
	zerolog.Logger
}

Logger is a wrapper around a Zerolog logger instance

func LoadLoggerFromContext

func LoadLoggerFromContext(ctx context.Context) *Logger

LoadFromContext returns the Logger from a given context

func New

func New(config Config) (*Logger, error)

New returns a new Logger instance for a given service name and log level

func NewFromZerolog

func NewFromZerolog(logger zerolog.Logger) *Logger

NewFromZerolog returns a new Logger from a Zerolog instance

func NewRequestLoggerFromZerolog

func NewRequestLoggerFromZerolog(ctx context.Context, logger zerolog.Logger) *Logger

NewFromZerolog returns a new Logger from a Zerolog instance and adds the Request id to the logger Context

func (*Logger) ChildLogger

func (l *Logger) ChildLogger(key string, value string) *Logger

SubLogger returns a new child logger that inherits all settings but adds a new string key field

func (*Logger) ChildLoggerWithAttributes added in v0.16.0

func (l *Logger) ChildLoggerWithAttributes(keyVal ...string) (*Logger, error)

SubLogger returns a new child logger that inherits all settings but adds a number of new string key field

func (*Logger) ComponentLogger

func (l *Logger) ComponentLogger(component string) *Logger

ComponentLogger returns a new child logger that inherits all settings but adds a new component field

func (*Logger) Level

func (l *Logger) Level(lvl Level) *Logger

Level wraps the underlying zerolog level func to openmfp logger level

func (*Logger) Logr

func (l *Logger) Logr() logr.Logger

Logr returns a new logger that fulfills the log.Logr interface

func (*Logger) MustChildLoggerWithAttributes added in v0.16.0

func (l *Logger) MustChildLoggerWithAttributes(keyVal ...string) *Logger

MustChildLogger returns a new child logger that inherits all settings but adds a number of new string key field. It panics in case of wrong use.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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