logger

package module
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2018 License: MIT Imports: 12 Imported by: 4

README

Go-Logger v1.0

pipeline status coverage report

A logging library for Go.

My view on application logging

  • Should not be where your CPU spends most of the time.
  • Should be done to STDERR/STDOUT. Log rotation, logging to log dispatchers or centralized log aggregators, etc should be the job of operations not development.
  • Should not be confused with auditing, although it can be rudementarily used for it.
  • Should not cause application failures, even if nothing is being logged due to an error in the logger.
  • Should be simple to use in development and powerful enough to be used in production without convoluted and complex configurations. Id est, it should permit structured logging while keeping a simple interface.

Logging scopes and package usage.

In an opinionated view of logging, one can consider a logger to have 4 hierarchical levels

  • Application level is from where all loggers should be created.
  • Component level is associated with only a part of the application. This is typically a domain package, library, "class", etc.
  • Instance level should be associated with a data structure and respective methods, in the OOP world that would be a class instance. These loggers should be derived from the component level logger.
  • Function level is specific to a certain function, with parts of the input or state included in the fields and/or tags.

Fields or Data?

Fields should represent data relevant to filtering or selecting log entries. Data, on the other hand, is only relevant to the entry itself and has little value in terms of finding the log entry.

Field examples: a user's ID, action, application component. Data examples: a user's email or name

Possible Future Features

TODO

Quick Usage

Download the package

If you are using Dep (recommended) you can simply add the package to your code and run dep ensure or install it in your project using

dep ensure -add gitlab.com/vredens/go-logger

Or install it globally using plain old go get

go get -u gitlab.com/vredens/go-logger
import logger "gitlab.com/vredens/go-logger"

// create a package level logger
var log = logger.SpawnSimple(
	logger.WithFields(map[string]interface{}{"component": "mypackage"}),
	logger.WithTags("user", "account"),
)

func main() {
	// log with our package level logger
	log.Write("this is a message and we use the tag info instead of a log level", logger.Tags{"bootstrap", "info"})

	// logging with extra data
	log.Dump("A message with structured data", nil, logger.KV{"id": 10, "age": 50, "name": "john smith"})

	// create a new logger with some fields
	userLog := log.SpawnSimple(logger.WithFields(logger.KV{"user_type": "me", "user_id": 1234}))

	// logging with the new logger
	userLog.Dump("here's a log with some extra data", logger.Tags{"moardata"}, logger.KV{"kiss": "is simple"})

	// change the logging format and min log level
	logger.Reconfigure(logger.WithLevel(logger.DEBUG), logger.WithFormat(logger.FormatJSON))

	// Log a debug message
	userLog.Dbg("this will show up now", nil, nil)
}
Using it in your code (Logger, the typical interface)
import logger "gitlab.com/vredens/go-logger"

// create a package level logger
var log = logger.Spawn(
	logger.WithFields(map[string]interface{}{"component": "mypackage"}),
	logger.WithTags("user", "account"),
)

func main() {
	// logging with the default global logger
	logger.Debugf("This is a debug of %s", "hello world")

	// log with our package level logger
	log.Info("this is a message")

	// logging with extra data
	log.WarnData("A message with structured data", logger.KV{"id": 10, "age": 50, "name": "john smith"})

	// create a new small scope logger with some fields
	userLog := log.WithFields(logger.KV{"user_type": "me", "user_id": 1234})

	// logging with the new logger
	userLog.WithData(logger.KV{"kiss": "is simple"}).Debug("here's a log with some extra data")

	// change the logging format and min log level
	logger.Reconfigure(logger.WithLevel(logger.DEBUG), logger.WithFormat(logger.FormatJSON))

	// Log an error message with extra tags and fields
	userLog.With(logger.Tags{"critical"}, logger.KV{"ctx_id":666}).Error("the devil is around here!")
}

Documentation

Overview

Example
// logging with the default global logger
Debugf("This is a debug of %s", "hello world")

// create a new logger
var log = SpawnSimple(WithFields(map[string]interface{}{"component": "mypackage"}), WithTags("user", "account"))

// log something
log.Write("this is a message and we use the tag info instead of a log level", Tags{"bootstrap", "info"})

// log with extra data
log.Dump("A message with structured data", nil, KV{"id": 10, "age": 50, "name": "john smith"})

// create a new logger from another logger
userLog := log.SpawnSimple(WithFields(KV{"user_type": "me", "user_id": 1234}))

// logging with the new logger
userLog.Dump("here's a log with some extra data", Tags{"moardata"}, KV{"kiss": "is simple"})

// change the logging format and min log level
Reconfigure(
	WithLevel(DEBUG),
	WithFormat(FormatJSON),
)

// do a debug log
userLog.Dbg("this will show up now", nil, nil)
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Debug

func Debug(msg string)

Debug ...

func DebugData added in v1.0.0

func DebugData(msg string, data map[string]interface{})

DebugData ...

func Debugf

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

Debugf ...

func Error

func Error(msg string)

Error ...

func ErrorData added in v1.0.0

func ErrorData(msg string, data map[string]interface{})

ErrorData ...

func Errorf

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

Errorf ...

func F added in v1.0.0

func F(format string, args ...interface{}) string

F is a wrapper for fmt.Sprintf, its use is not recommended. If you do use it, you are labeling yourself lazy.

func GetCallerInfo added in v1.0.0

func GetCallerInfo(depth int, fullPath bool) string

GetCallerInfo is a helper for returning a string with "filename:line" of the call depth provided. Use this to add to a log field.

func Info

func Info(msg string)

Info ...

func InfoData added in v1.0.0

func InfoData(msg string, data map[string]interface{})

InfoData ...

func Infof

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

Infof ...

func Log added in v1.0.0

func Log(msg string, tags []string)

Log ...

func Logd added in v1.1.0

func Logd(msg string, tags []string, fields map[string]interface{})

Logd ...

func Print

func Print(args ...interface{})

Print for compatibility with Go's official log package.

func Printf

func Printf(format string, args ...interface{})

Printf for compatibility with Go's official log package.

func Println added in v1.0.0

func Println(args ...interface{})

Println for compatibility with Go's official log package.

func Reconfigure added in v1.0.0

func Reconfigure(opts ...WriterOption)

Reconfigure ...

func Stringify added in v1.0.0

func Stringify(v interface{}, quoted bool) string

Stringify attempts to convert any interface to a string. If the interface implements the fmt.Stringer interface then it returns the result of String().

func Warn

func Warn(msg string)

Warn ...

func WarnData added in v1.0.0

func WarnData(msg string, data map[string]interface{})

WarnData ...

func Warnf

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

Warnf ...

func Write added in v1.0.0

func Write(msg string)

Write ...

func WriteData added in v1.0.0

func WriteData(msg string, data map[string]interface{})

WriteData ...

Types

type Compatible added in v1.0.0

type Compatible interface {
	SpawnCompatible(...Option) Compatible
	Print(...interface{})
	Println(...interface{})
	Printf(string, ...interface{})
}

Compatible is a compatibility interface for the standard logger for dropin replacement of the standard logger.

func SpawnCompatible added in v1.0.0

func SpawnCompatible(opts ...Option) Compatible

SpawnCompatible creates a new logger which implements the Compatible interface.

func SpawnCompatibleMute added in v1.2.0

func SpawnCompatibleMute() Compatible

SpawnCompatibleMute creates a new logger which implements the Compatible interface but blocks all logging. This is simply a helper in order to inject loggers into components to keep them quiet.

type ConfigurableLogger added in v1.0.0

type ConfigurableLogger interface {
	Reconfigure(...Option)
	AddFields(map[string]interface{})
	AddTags(...string)
	AddData(KV)
}

ConfigurableLogger interface defines the interface for a logger which can be reconfigured.

type Entry added in v1.2.0

type Entry interface {
	// With method spawns a new Entry from the current one adding the provided tags and fields.
	With(tags []string, fields map[string]interface{}) Entry
	// WithTags updates  a new Entry logger with the provided tags.
	WithTags(tags ...string) Entry
	// WithData returns a new Entry logger with the provided data.
	WithData(data map[string]interface{}) Entry
	// WithFields returns a new Entry logger with the provided fields.
	WithFields(fields map[string]interface{}) Entry

	Debug(msg string)
	Info(msg string)
	Warn(msg string)
	Error(msg string)

	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
}

Entry is a special logger aimed at function/line scoped logging.

type Fields added in v1.0.0

type Fields = map[string]interface{}

Fields is a type alias for map[string]interface{}. @deprecated use KV instead.

type Format added in v1.0.0

type Format uint8

Format is a constant defining the log format.

const (
	// FormatText is used for setting the log formatter as a human readable log line in the style of syslog and similar.
	FormatText Format = iota
	// FormatJSON is used for setting the log formatter to JSON where each line is a single JSON object representing the log entry.
	FormatJSON
)

type KV added in v1.2.0

type KV = map[string]interface{}

KV is a type alias for map[string]interface{}.

type Level

type Level uint8

Level for defining log level integer values for granular filtering.

const (

	// RAW log level should be used only when dumping large log entries or entire structures, use in development only.
	RAW Level
	// DEBUG log level should be used for development only and potentially as on/off in particular situations for gathering more information during tricky debugging situations.
	DEBUG
	// INFO is anything relevant for the log analysis/consumer. For example, informing that a database connection was established, a message was received, etc. This should be used for log analysis, metrics and basic profiling of bottlenecks.
	INFO
	// WARN log level should be used in situations where many entries of this type should trigger an allert in your centralized logging system. It only makes sense if you plan to use such a system architecture.
	WARN
	// ERROR log level should be used in all error situations. Careful with what you consider an error. Typically if you are handling the situation or returning the error to the caller, you should not log it as an ERROR.
	ERROR
	// OFF log level should be used only by SetLevel method to disable logging.
	OFF
)

type Logger

type Logger interface {
	Spawn(...Option) Logger
	With(tags []string, fields map[string]interface{}) Entry
	WithTags(tags ...string) Entry
	WithFields(fields map[string]interface{}) Entry
	WithData(data map[string]interface{}) Entry

	Debug(msg string)
	Info(msg string)
	Warn(msg string)
	Error(msg string)

	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Errorf(format string, args ...interface{})

	// DebugData ...
	// @deprecated use WithData().Debug() instead
	DebugData(msg string, data map[string]interface{})
	// InfoData ...
	// @deprecated use WithData().Info() instead
	InfoData(msg string, data map[string]interface{})
	// WarnData ...
	// @deprecated use WithData().Warn() instead
	WarnData(msg string, data map[string]interface{})
	// ErrorData ...
	// @deprecated use WithData().Error() instead
	ErrorData(msg string, data map[string]interface{})
}

Logger is a typical logger interface.

func Spawn added in v1.0.0

func Spawn(opts ...Option) Logger

Spawn creates a new Logger directly from the log writer.

func SpawnMute added in v1.2.0

func SpawnMute() Logger

SpawnMute creates a new logger which implements the Logger interface but blocks all logging. This is simply a helper in order to inject loggers into components to keep them quiet.

type Option added in v1.0.0

type Option func(ConfigurableLogger)

Option ...

func WithData added in v1.2.0

func WithData(data map[string]interface{}) Option

WithData ...

func WithFields added in v1.0.0

func WithFields(fields map[string]interface{}) Option

WithFields ...

func WithTags added in v1.0.0

func WithTags(tags ...string) Option

WithTags ...

type Simple added in v1.0.0

type Simple interface {
	// Spawn creates a new logger with the provided configuration. Use this to change your default logger's fields and tags.
	SpawnSimple(...Option) Simple
	// Log writes a log line with the provided message and a list of tags. Use nil value for tags if you don't want to add any. Tags are appended to the logger's tags. There is no check for repeated tags.
	// @deprecated.
	Log(message string, tags []string)
	// Logd is similar to Log except it allows passing additional structured data in the form of map[string]interface{}.
	// @deprecated.
	Logd(message string, tags []string, data map[string]interface{})
	// Write writes a new log entry with the provided message and tags. The tags parameter can be nil and no extra tags will be included in the log entry.
	Write(msg string, tags []string)
	// Dump is similar to Write but it also logs extra data. The data parameter can be nil which has the same effect as calling the Write method.
	Dump(msg string, tags []string, data map[string]interface{})
	// Dbg is similar to Dump except it will not print anything if the minimum log level has been set to something higher than DEBUG. Note that the Simple logger itself will ignore any other minimum log level set.
	Dbg(message string, tags []string, data map[string]interface{})
}

Simple interface is the a basic yet powerful interface for a logger. It encourages the use of tags instead of log levels for more control in terms of log filtering and search. It discourages fancy printf, requiring the user to run fmt.Printf or logger.F for a slightly shorter version.

func SpawnSimple added in v1.1.1

func SpawnSimple(opts ...Option) Simple

SpawnSimple returns a new logger which implements the Simple interface.

func SpawnSimpleMute added in v1.2.0

func SpawnSimpleMute() Simple

SpawnSimpleMute creates a new logger which implements the Simple interface but blocks all logging. This is simply a helper in order to inject loggers into components to keep them quiet.

type StdLogger added in v1.0.0

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

StdLogger ...

func (*StdLogger) AddData added in v1.2.0

func (l *StdLogger) AddData(data KV)

AddData ...

func (*StdLogger) AddFields added in v1.0.0

func (l *StdLogger) AddFields(fields map[string]interface{})

AddFields ...

func (*StdLogger) AddTags added in v1.0.0

func (l *StdLogger) AddTags(tags ...string)

AddTags ...

func (*StdLogger) Dbg added in v1.2.0

func (l *StdLogger) Dbg(msg string, tags []string, data map[string]interface{})

Dbg is similar to Dump except it will not print anything if the minimum log level has been set to something higher than DEBUG. Note that the Simple logger itself will ignore any other minimum log level set.

func (*StdLogger) Debug added in v1.0.0

func (l *StdLogger) Debug(msg string)

Debug ...

func (*StdLogger) DebugData added in v1.0.0

func (l *StdLogger) DebugData(msg string, data map[string]interface{})

DebugData ...

func (*StdLogger) Debugf added in v1.0.0

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

Debugf ...

func (*StdLogger) Dump added in v1.2.0

func (l *StdLogger) Dump(msg string, tags []string, data map[string]interface{})

Dump is similar to Write but it also logs extra data. The data parameter can be nil which has the same effect as calling the Write method.

func (*StdLogger) Error added in v1.0.0

func (l *StdLogger) Error(msg string)

Error ...

func (*StdLogger) ErrorData added in v1.0.0

func (l *StdLogger) ErrorData(msg string, data map[string]interface{})

ErrorData ...

func (*StdLogger) Errorf added in v1.0.0

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

Errorf ...

func (*StdLogger) Info added in v1.0.0

func (l *StdLogger) Info(msg string)

Info ...

func (*StdLogger) InfoData added in v1.0.0

func (l *StdLogger) InfoData(msg string, data map[string]interface{})

InfoData ...

func (*StdLogger) Infof added in v1.0.0

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

Infof ...

func (*StdLogger) Log added in v1.0.0

func (l *StdLogger) Log(msg string, tags []string)

Log ...

func (*StdLogger) Logd added in v1.1.0

func (l *StdLogger) Logd(msg string, tags []string, data map[string]interface{})

Logd ...

func (*StdLogger) Print added in v1.0.0

func (l *StdLogger) Print(args ...interface{})

Print ...

func (*StdLogger) Printf added in v1.0.0

func (l *StdLogger) Printf(format string, args ...interface{})

Printf ...

func (*StdLogger) Println added in v1.0.0

func (l *StdLogger) Println(args ...interface{})

Println ...

func (*StdLogger) Reconfigure added in v1.0.0

func (l *StdLogger) Reconfigure(opts ...Option)

Reconfigure ...

func (*StdLogger) Spawn added in v1.0.0

func (l *StdLogger) Spawn(opts ...Option) Logger

Spawn creates a new instance of a Logger using the parent Logger as origin.

func (*StdLogger) SpawnCompatible added in v1.0.0

func (l *StdLogger) SpawnCompatible(opts ...Option) Compatible

SpawnCompatible creates a new instance of a Logger using the parent Logger as origin.

func (*StdLogger) SpawnSimple added in v1.1.0

func (l *StdLogger) SpawnSimple(opts ...Option) Simple

SpawnSimple creates a new instance of a Logger using the parent Logger as origin.

func (*StdLogger) Warn added in v1.0.0

func (l *StdLogger) Warn(msg string)

Warn ...

func (*StdLogger) WarnData added in v1.0.0

func (l *StdLogger) WarnData(msg string, data map[string]interface{})

WarnData ...

func (*StdLogger) Warnf added in v1.0.0

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

Warnf ...

func (*StdLogger) With added in v1.2.0

func (l *StdLogger) With(tags []string, fields map[string]interface{}) Entry

With returns a new instance of an Entry logger with the provided tags and fields.

func (*StdLogger) WithData added in v1.2.0

func (l *StdLogger) WithData(data map[string]interface{}) Entry

WithData creates a new instance of an Entry logger with the provided data.

func (*StdLogger) WithFields added in v1.2.0

func (l *StdLogger) WithFields(fields map[string]interface{}) Entry

WithFields creates a new instance of an Entry logger with the provided fields.

func (*StdLogger) WithTags added in v1.2.0

func (l *StdLogger) WithTags(tags ...string) Entry

WithTags creates a new instance of an Entry logger with the provided tags.

func (*StdLogger) Write added in v1.2.0

func (l *StdLogger) Write(msg string, tags []string)

Write writes a new log entry with the provided message and tags. The tags parameter can be nil and no extra tags will be included in the log entry.

type Tags added in v1.0.0

type Tags = []string

Tags is a type alias for []string

type Writer added in v1.0.0

type Writer interface {
	Spawn(...Option) Logger
	SpawnSimple(...Option) Simple
	SpawnCompatible(...Option) Compatible
	Reconfigure(...WriterOption)
	Write(msg string)
	WriteData(msg string, data map[string]interface{})
}

Writer ...

func NewWriter added in v1.0.0

func NewWriter(opts ...WriterOption) Writer

NewWriter creates a new log Writer.

type WriterOption added in v1.0.0

type WriterOption func(*writer)

WriterOption are options for all loggers implementing the Basic logger interface.

func WithFormat added in v1.0.0

func WithFormat(format Format) WriterOption

WithFormat ...

func WithImmutableFields added in v1.0.0

func WithImmutableFields(fields map[string]interface{}) WriterOption

WithImmutableFields option, a writer has the provided fields replace its list of fields. A writer's fields can not be changed or overriden by a logger and at Spawn time are copied to the spawn.

func WithImmutableTags added in v1.0.0

func WithImmutableTags(tags ...string) WriterOption

WithImmutableTags option, a writer has the tags provided replace its list of tags. A writer's tags can not be changed or overriden by a logger and at Spawn time all tags are copied to the spawn.

func WithLevel added in v1.0.0

func WithLevel(level Level) WriterOption

WithLevel ...

func WithOutput added in v1.0.0

func WithOutput(w io.Writer) WriterOption

WithOutput allows setting the output writer for the logger.

Jump to

Keyboard shortcuts

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