ktlogging

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Aug 21, 2023 License: Apache-2.0 Imports: 10 Imported by: 5

README

lib-logging-golang

A wrapper around (currently! can change!) the popular go.uber.org/zap logging library and on top of that brings

  • configurability from yaml/json config (Python style)
  • hierarchical logging
  • bringing fmt.Printf() style .Info("log message with %v", value) logging signature - which will be only evaluated into a string if log event is not filtered out
  • concept of "global labels" - set of key-value papirs which are always logged with every log event
  • builder style to add custom labels (zap.Fields) to particular log events

Get and install

go get github.com/keytiles/lib-logging-golang

Usage

Here is a simple example (you also find this as a running code in the example folder!)

import (
    ...
	"github.com/keytiles/lib-logging-golang"
	...
)


func main() {

	// === init the logging

	cfgErr := ktlogging.InitFromConfig("./log-config.yaml")
	if cfgErr != nil {
		panic(fmt.Sprintf("Oops! it looks configuring logging failed :-( error was: %v", cfgErr))
	}

	// === global labels

	ktlogging.SetGlobalLabels(buildGlobalLabels())

	// manipulating the GlobalLabels later is also possible
	globalLabels := ktlogging.GetGlobalLabels()
	globalLabels = append(globalLabels, ktlogging.FloatLabel("myVersion", 5.2))
	ktlogging.SetGlobalLabels(globalLabels)

	// === and now let's use the initialized logging!

	// most simple usage
	ktlogging.With("root").Info("very simple info message")

	// message constructued with parameters (will be really evaluated into a string if log event is not filtered out)
	ktlogging.With("root").Info("just an info level message - sent at %v", time.Now())

	// message with only one custom label
	ktlogging.With("root").WithLabel(ktlogging.StringLabel("myKey", "myValue")).Info("just an info level message - sent at %v", time.Now())

	// message with multiple labels
	ktlogging.With("root").WithLabels([]ktlogging.Label{ktlogging.IntLabel("myIntKey", 5), ktlogging.BoolLabel("myBoolKey", true)}).Info("just an info level message - sent at %v", time.Now())

	// and combined also works - multiple labels and one custom
	ktlogging.With("root").WithLabel(ktlogging.StringLabel("myKey", "myValue")).WithLabels([]ktlogging.Label{ktlogging.IntLabel("myIntKey", 5), ktlogging.BoolLabel("myBoolKey", true)}).Info("just an info level message - sent at %v", time.Now())

	// hierarchical logging - we only have "controller" configured (log-config.yaml) so this one will fall back in runtime
	ktlogging.With("controller.something").Info("not visible as logger level is 'warn'")
	ktlogging.With("controller.something").Warn("visible controller log")

	// get a Logger once - and then just use it in all subsequent logs
	// this way you can create package-private Logger instances e.g.
	logger := ktlogging.GetLogger("main")
	logger.Info("with logger instance")
	labels := []ktlogging.Label{ktlogging.StringLabel("key", "value")}
	logger.WithLabels(labels).Info("one more message tagged with 'key=value'")
}

// builds and returns labels we want to add to all log events (this is just an example!!)
func buildGlobalLabels() []ktlogging.Label {
	var globalLabels = []ktlogging.Label{}
	appName := os.Getenv("CONTAINER_NAME")
	appVer := os.Getenv("CONTAINER_VERSION")
	host := os.Getenv("HOSTNAME")

	if appName == "" {
		appName = "?"
	}
	globalLabels = append(globalLabels, ktlogging.StringLabel("appName", appName))
	if appVer == "" {
		appVer = "?"
	}
	globalLabels = append(globalLabels, ktlogging.StringLabel("appVer", appVer))
	if host == "" {
		host = "?"
	}
	globalLabels = append(globalLabels, ktlogging.StringLabel("host", host))

	return globalLabels
}

Config file

We are using the Python style log config as that is simple yet effective at the same time.

Take a look into /example/log-config.yaml file!

This basically consists of two sections:

  • loggers - is a map of Logger instances you want to create.
    So each Logger is named (by the key) and you can assign a specific log level (error|warning|info|debug) and list of handlers (see below) to where this Logger will forward to each log events passed the level filtering
  • handlers - is a map of configured outputs. Each Handler is a named (by the key) entity and can represent outputting to STDOUT (console), file or other. For Handlers you can control the encoding format can be 'json' or 'console'

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func InitFromConfig

func InitFromConfig(cfgPath string) error

Initializing the logging from the .yaml or .json config file available on the given path

func SetGlobalLabels

func SetGlobalLabels(labels []Label)

you can change the GlobalLabels with this - the key-value pairs attached to all log events

Types

type ConfigModel

type ConfigModel struct {
	Loggers  map[string]LoggerConfigModel  `json:"loggers" yaml:"loggers"`
	Handlers map[string]HandlerConfigModel `json:"handlers" yaml:"handlers"`
}

for json/yaml config file parsing - this is root level object

type HandlerConfigModel

type HandlerConfigModel struct {
	Level       string   `json:"level" yaml:"level"`
	Encoding    string   `json:"encoding" yaml:"encoding"`
	OutputPaths []string `json:"outputPaths" yaml:"outputPaths"`
}

for json/yaml config file parsing - this is the entries in /handlers path

type Label

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

A Label can carry a certain key-value pair. Regarding the value the atomic JSON data types are supported: string, bool, numeric values. Complex structures like array/object are not as we do not want to bring this complexity as a key-value into central persistence layers (like Elastic Search or similar). You can marshal complex structures into a JSON string before logging and just log the string representation

func BoolLabel

func BoolLabel(key string, val bool) Label

constructs a Boolean label with the given key and value.

func FloatLabel

func FloatLabel(key string, val float64) Label

constructs a Float label with the given key and value.

func GetGlobalLabels

func GetGlobalLabels() []Label

returns the current GlobalLabels - key-value pairs attached to all log events

func IntLabel

func IntLabel(key string, val int64) Label

constructs an Integer label with the given key and value.

func StringLabel

func StringLabel(key string, val string) Label

constructs a String label with the given key and value.

type LabelType

type LabelType uint8

A LabelType indicates the data type the Label carries

const (
	// UnknownType is the default Label type. Attempting to add it to an encoder will panic.
	UnknownType LabelType = iota
	// BoolType indicates that the Label carries a bool.
	BoolType
	// FloatType indicates that the Label carries a float64.
	FloatType
	// IntType indicates that the Label carries an int64.
	IntType
	// StringType indicates that the Label carries a string.
	StringType
)

type LogEvent

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

func (LogEvent) Debug

func (le LogEvent) Debug(message string, messageParams ...any)

func (LogEvent) Error

func (le LogEvent) Error(message string, messageParams ...any)

func (LogEvent) Info

func (le LogEvent) Info(message string, messageParams ...any)

func (LogEvent) Warn

func (le LogEvent) Warn(message string, messageParams ...any)

func (LogEvent) WithLabel

func (le LogEvent) WithLabel(label Label) LogEvent

func (LogEvent) WithLabels

func (le LogEvent) WithLabels(labels []Label) LogEvent

type LogLevel

type LogLevel uint8
const (
	ErrorLevel   LogLevel = 0
	WarningLevel LogLevel = 1
	InfoLevel    LogLevel = 2
	DebugLevel   LogLevel = 3
)

type Logger

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

func GetLogger

func GetLogger(loggerName string) *Logger

returns a Logger with the given name - if does not exist then a new instance is created with this name and registered note: Loggers are hierarchical

func With

func With(loggerName string) *Logger

just a shortcut to the GetLogger method - for builder style readability stuff

func (Logger) Debug

func (l Logger) Debug(message string, messageParams ...any)

wrapper around .Log() method - fired with Debug level

func (Logger) Error

func (l Logger) Error(message string, messageParams ...any)

wrapper around .Log() method - fired with Error level

func (Logger) GetHandlers

func (l Logger) GetHandlers() map[string]*zap.Logger

returns the attached Handlers

func (Logger) GetLevel

func (l Logger) GetLevel() LogLevel

returns the level

func (Logger) GetName

func (l Logger) GetName() string

returns the name of the Logger - this can not change after instantiation

func (Logger) Info

func (l Logger) Info(message string, messageParams ...any)

wrapper around .Log() method - fired with Info level

func (*Logger) Log

func (l *Logger) Log(level LogLevel, message string, messageParams ...any)

logs the given message resolved with (optional) messageParams (Printf() style) on the given log level in case the the message is filtered out due to configured log level then the message string is not built at all

func (Logger) Warn

func (l Logger) Warn(message string, messageParams ...any)

wrapper around .Log() method - fired with Warning level

func (*Logger) WithLabel

func (l *Logger) WithLabel(label Label) LogEvent

Decorates the upcoming LogEvent (when you invoke .info(), .error() etc method the LogEvent is fired) with the given label. If you have multiple labels to add consider using .WithLabels() method instead. Please note: the label will be just used in the upcoming LogEvent and after that forgotten!

func (*Logger) WithLabels

func (l *Logger) WithLabels(labels []Label) LogEvent

Decorates the upcoming LogEvent (when you invoke .info(), .error() etc method the LogEvent is fired) with the given labels. Please note: the labels will be just used in the upcoming LogEvent and after that forgotten!

type LoggerConfigModel

type LoggerConfigModel struct {
	Name         string   `json:"name" yaml:"name"`
	Level        string   `json:"level" yaml:"level"`
	HandlerNames []string `json:"handlers" yaml:"handlers"`
}

for json/yaml config file parsing - this is the entries in /loggers path

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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