logur

package module
v0.17.0 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2020 License: MIT Imports: 9 Imported by: 92

README

Logur

Mentioned in Awesome Go

GitHub Workflow Status Codecov Go Report Card Go Version go.dev reference

Logur is an opinionated collection of logging best practices.

Table of Contents

Preface

Logur is an opinionated logging library targeted at producing (application) logs. It does not try to solve every problem around logging, only a few considered important by the developers, thus it's highly opinionated.

The main focus of the library:

  • provide a unified interface that does not require developers to import external dependencies
  • encourage leveled and structured logging
  • provide tools for easy integration of other logging libraries and components

Logur does not care about log output, you can use whatever library/formatting/forwarder you want (ie. use an existing logging library with one of the adapters).

Despite the opinionated nature, Logur encourages you to create custom logging interfaces for your needs and only use Logur as an integration layer/tool. Use the features you need/want and just omit the rest.

As mentioned above, Logur aims to cover only 95% of the use cases, so Logur might not be for you. Read on for more details.

Features

Installation

Logur uses Go Modules introduced in Go 1.11, so the recommended way is using go get:

$ go get logur.dev/logur

Usage

An opinionated library should come with some best practices for usage and so does this one.

TL;DR: See example usage and best practices in github.com/sagikazarmark/modern-go-application. Also, check out the example package in this repository.

Create a custom interface

Interfaces should be defined by the consumer, so the Logger interface in this library should not be used directly. A custom interface should be defined instead:

type MyLogger interface {
	Trace(msg string, fields ...map[string]interface{})
	Debug(msg string, fields ...map[string]interface{})
	Info(msg string, fields ...map[string]interface{})
	Warn(msg string, fields ...map[string]interface{})
	Error(msg string, fields ...map[string]interface{})
}

In a lucky scenario all Logur loggers are compatible with the above interface, so you can just use them in your code:

func main() {
    logger := logur.NewNoopLogger()

    myFunc(logger)
}

func myFunc(logger MyLogger) {
	logger.Debug("myFunc ran")
	// OR
	logger.Debug("myFunc ran", map[string]interface{}{"key": "value"})
}

In case you need to populate the logger with some common context, the interface becomes a bit more complicated:

type MyLogger interface {
	Trace(msg string, fields ...map[string]interface{})
	Debug(msg string, fields ...map[string]interface{})
	// ...
	WithFields(fields map[string]interface{}) MyLogger
}

As you can see MyLogger holds a reference to itself, which makes it incompatible with the Logur implementations. The solution in this case is implementing a custom adapter:

type myLogger struct {
	logger logur.Logger
}

func (l *myLogger) Debug(msg string, fields ...map[string]interface{}) { l.logger.Debug(msg, fields...) }
// ...
func (l *myLogger) WithFields(fields map[string]interface{}) MyLogger {
	return myLogger{logur.WithFields(l.logger, fields)}
}

Now you can easily use Logur provided loggers inside your code:

func main() {
    logger := &myLogger{logur.NewNoopLogger()}

    myFunc(logger)
}

func myFunc(logger MyLogger) {
	logger.WithFields(map[string]interface{}{"key": "value"}).Debug("myFunc ran", nil)
}

Wrap helper functions with custom ones

In many cases it is unavoidable to maintain a simple integration layer between third-party libraries and your application. Logur is no exception. In the previous section you saw how the main interface works with adapters, but that's not all Logur provides. It comes with a set of other tools (eg. a standard library logger compatible io.Writer) to make logging easier. It might be tempting to just use them in your application, but writing an integration layer is recommended, even around functions.

The following example creates a simple standard library logger for using as an HTTP server error log:

func newStandardErrorLogger() *log.Logger {
	return logur.NewStandardLogger(logur.NewNoopLogger(), logur.ErrorLevel, "", 0)
}

func main() {
	server := &http.Server{
		Handler: nil,
		ErrorLog: newStandardErrorLogger(),
	}
}

FAQ

Why not just X logger?

To be honest: mostly because I don't care. Logging libraries proliferated in the Go ecosystem in the past few years. Each tries to convince you it's the most performant or the easiest to use. But the fact is your application doesn't care which you use. In fact, it's happier if it doesn't know anything about it at all. Logging libraries (just like every third-party library) are external dependencies. If you wire them into your application, it will be tied to the chosen libraries forever. That's why using a custom interface is a highly recommended practice.

Let's consider the following logger interface:

type Logger interface {
	Trace(msg string, fields ...map[string]interface{})
	Debug(msg string, fields ...map[string]interface{})
	Info(msg string, fields ...map[string]interface{})
	Warn(msg string, fields ...map[string]interface{})
	Error(msg string, fields ...map[string]interface{})
}

You can easily create an interface like this and implement an adapter for the logging library of your choice without wiring it into your application which makes the actual library a less important detail.

Why not Go kit logger?

Go-kit deserves it's own entry because for quite some time I was really fond of the its logger interface and it was the closest thing to become an official Go logging solution. I still think it is great, because the interface is very simple, yet it's incredibly powerful. But this simplicity is why I ultimately stopped using it as my primary logger (or I should say: stopped knowing that I actually use it).

Just a short recap of the interface itself:

type Logger interface {
	Log(keyvals ...interface{}) error
}

It's really simple and easy to use in any application. Following Go's guidelines of using interfaces, one can easily copy this interface and just use it to decouple the code from Go kit itself.

The problem with this interface appears when you try to do "advanced stuff" (like structured logging or adding a level to a log event):

import (
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
)

// ...

logger := log.With(logger, "key", "value")
level.Info(logger).Log("msg", "message")

As you can see doing any kind of structured or leveled logging requires to import Go kit packages after all, which takes us back to Why not just X logger?.

In short: Using Go kit directly - no matter how awesome its interface is - suffers from the same problem as using any other logging library.

One could implement all those functions for a custom interface based on Go kit, but it probably isn't worth the hassle. Defining a more verbose, custom interface is a lot easier to work with. That being said, Go kit logger can very well serve as a perfect base for an implementation of that interface.

The proposal linked above contains many examples why the authors ended up with an interface like this. Go check it out, you might just have the same use cases which could make the Go kit interface a better fit than the one in this library.

Why not logger.With(keyvals ...interface{})?

There is an increasing tendency of logging libraries implementing the following interface:

type Logger interface {
	// ...
	With(keyvals ...interface{})
}

The arguments behind this interface are being simple and convenient, not as verbose as a map of fields. There are also usual arguments against the alternative solutions, (eg. a map[string]interface{} endorsed by this library) like not being able to order fields, being forced to import a concrete type, like logur.Fields or (quite often) performance questions.

Ultimately, this is not completely independent from personal taste, so one will always prefer one or the other. (You can read more in the above linked Go kit proposal).

Let's take a look at these arguments one by one:

1. Simplicity and verbosity

This is something that's hard to argue with, but also a little bit subjective. Here is a comparison of a single line context logging:

logger = log.With(logger, "key", "value", "key2", "value")
logger = logur.WithFields(logger, map[string]interface{}{"key": "value", "key2": "value"})

Obviously the second one is more verbose, takes a bit more efforts to write, but it is rather a question of habits.

Let's take a look at a multiline example as well:

logger = log.With(logger,
	"key", "value",
	"key2", "value",
)

logger = logur.WithFields(logger, map[string]interface{}{
	"key": "value",
	"key2": "value",
})

The difference is less visible in this case and harder to argue that one is better than the other.

Also, defining a custom type is relatively easy which makes the difference even smaller:

logger = log.With(logger,
	"key", "value",
	"key2", "value",
)

type LogFields map[string]interface{}

logger = logur.WithFields(logger, LogFields{
	"key": "value",
	"key2": "value",
})

2. Ordering fields

This is one of the less known arguments against maps in the context of logging, you can read about it in the Go kit proposal.

Since maps are unordered in Go, fields added to a log line might not always look like the same on the output. Variadic (slice) arguments do not suffer from this issue. However, most implementations convert slices internally to maps, so if ordering matters, most logging libraries won't work anyway.

Also, this library is not a one size fits all proposal and doesn't try to solve 100% of the problems (unlike the official logger proposal), but rather aim for the most common use cases which doesn't include ordering of fields.

3. Performance

Comparing the performance of different solutions is not easy and depends heavily on the interface.

For example, Uber's Zap comes with a rich interface (thus requires you to couple your code to Zap), but also promises zero-allocation in certain scenarios, making it an extremely fast logging library. If being very fast is a requirement for you, even at the expense tight coupling, then Zap is a great choice.

More generic interfaces often use ... well interface{} for structured context, but interface allocations are much cheaper now.

The performance debate these days is often between two approaches:

  • variadic slices (...interface{})
  • maps (map[string]interface{})

Specifically, how the provided context can be merged with an existing, internal context of the logger. Admittedly, appending to a slice is much cheaper than merging a map, so if performance is crucial, using an interface with variadic slices will always be slightly faster. But that difference in performance is negligible in most of the cases, so you won't even notice it, unless you start logging with hundreds of structured context fields (which will have other problems anyway).

There is a problem with Logur adapters though: since the interface uses maps for structured context, libraries like Zap that use variadic slices does not perform too well because of the map -> slice conversion. In most of the cases this should still be acceptable, but you should be aware of this fact when choosing an adapter.

Partly because of this, I plan to add a KVLogger interface that uses variadic slices for structured context. Obviously, map based libraries will suffer from the same performance penalty, but then the choice of the interface will be up to the developer.

Comparing the slice and the map solution, there are also some arguments against using a variadic slice:

1. Odd number of arguments

The variadic slice interface implementation has to deal with the case when an odd number of arguments are passed to the function. While the Go kit proposal argues that this is extremely hard mistake to make, the risk is still there that the logs will lack some information.

2. Converting the slice to key value pairs

In order to display the context as key-value pairs the logging implementations has to convert the key parameters to string in most of the cases (while the value parameter can be handled by the marshaling protocol). This adds an extra step to outputting the logs (an extra loop going through all the parameters). While there is no scientific evidence proving one to be slower than the other (yet), it seems to be an unnecessary complication at first.

Why no *f (format) functions?

A previous version of this interface contained a set of functions that allowed messages to be formatted with arguments:

type Logger interface {
	// ...
	Tracef(format string, args ...interface{})
	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
}

The reason why they were originally included in the interface is that most logging libraries implement these methods, but experience showed that they are not used frequently. Also, nowadays structured logging is a better practice than formatting log messages with structured data, thus these methods were removed from the core interface.

Why no *ln functions?

Another common group of logging functions originally included in the interface is *ln function group:

type Logger interface {
	// ...
	Traceln(args ...interface{})
	Debugln(args ...interface{})
	Infoln(args ...interface{})
	Warnln(args ...interface{})
	Errorln(args ...interface{})
}

Usually separate log events are represented on separate lines anyway, so the added value is not newlines in this case, but the different semantics between fmt.Print and fmt.Println. See this example illustrating the difference.

Common logging libraries include these functions, but experience showed they are not used frequently, so they got removed.

Inspiration

This package is heavily inspired by a set of logging libraries:

License

The MIT License (MIT). Please see License File for more information.

Documentation

Overview

Package logur is an opinionated collection of logging best practices.

Check the readme for detailed documentation: https://github.com/logur/logur/blob/master/README.md

Also, check the example package for detailed examples: https://godoc.org/logur.dev/logur/examples

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func LogEventsEqual deprecated

func LogEventsEqual(expected LogEvent, actual LogEvent) error

LogEventsEqual asserts that two LogEvents are identical and returns an error with detailed information if not.

Deprecated: use LogEvents.AssertEquals.

func NewErrorStandardLogger

func NewErrorStandardLogger(logger Logger, prefix string, flag int) *log.Logger

NewErrorStandardLogger returns a new standard library logger for error level logging (eg. for HTTP servers).

func NewLevelWriter

func NewLevelWriter(logger Logger, level Level) *io.PipeWriter

NewLevelWriter creates a new writer from a Logger for a specific level of log events.

func NewStandardLogger

func NewStandardLogger(logger Logger, level Level, prefix string, flag int) *log.Logger

NewStandardLogger returns a new standard library logger.

func NewWriter

func NewWriter(logger Logger) *io.PipeWriter

NewWriter creates a new writer from a Logger with a default Info level.

Types

type ContextExtractor added in v0.16.0

type ContextExtractor func(ctx context.Context) map[string]interface{}

ContextExtractor extracts a map of details from a context.

func ContextExtractors added in v0.16.0

func ContextExtractors(extractors ...ContextExtractor) ContextExtractor

ContextExtractors combines a list of ContextExtractor. The returned extractor aggregates the result of the underlying extractors.

type Fields

type Fields map[string]interface{}

Fields is used to define structured fields which are appended to log events. It can be used as a shorthand for map[string]interface{}.

type KVLogContextFunc added in v0.17.0

type KVLogContextFunc func(ctx context.Context, msg string, keyvals ...interface{})

KVLogContextFunc records a log event.

func KVLevelContextFunc added in v0.17.0

func KVLevelContextFunc(l KVLogger, level Level) KVLogContextFunc

KVLevelContextFunc returns a KVLogContextFunc for a level. If the level is invalid it falls back to Info level.

type KVLogFunc added in v0.17.0

type KVLogFunc func(msg string, keyvals ...interface{})

KVLogFunc records a log event.

func KVLevelFunc added in v0.17.0

func KVLevelFunc(logger KVLogger, level Level) KVLogFunc

KVLevelFunc returns a KVLogFunc for a level. If the level is invalid it falls back to Info level.

type KVLogger added in v0.17.0

type KVLogger interface {
	// Trace logs a Trace event.
	//
	// Even more fine-grained information than Debug events.
	// Loggers not supporting this level should fall back to Debug.
	Trace(msg string, keyvals ...interface{})

	// Debug logs a Debug event.
	//
	// A verbose series of information events.
	// They are useful when debugging the system.
	Debug(msg string, keyvals ...interface{})

	// Info logs an Info event.
	//
	// General information about what's happening inside the system.
	Info(msg string, keyvals ...interface{})

	// Warn logs a Warn(ing) event.
	//
	// Non-critical events that should be looked at.
	Warn(msg string, keyvals ...interface{})

	// Error logs an Error event.
	//
	// Critical events that require immediate attention.
	// Loggers commonly provide Fatal and Panic levels above Error level,
	// but exiting and panicing is out of scope for a logging library.
	Error(msg string, keyvals ...interface{})
}

KVLogger is a unified interface for various logging use cases and practices, including:

  • leveled logging
  • structured logging

Compared to Logger, KVLogger accepts key-value pairs in the form of variadic interface arguments.

type KVLoggerContext added in v0.17.0

type KVLoggerContext interface {
	// TraceContext logs a Trace event.
	//
	// Even more fine-grained information than Debug events.
	// Loggers not supporting this level should fall back to Debug.
	TraceContext(ctx context.Context, msg string, keyvals ...interface{})

	// DebugContext logs a Debug event.
	//
	// A verbose series of information events.
	// They are useful when debugging the system.
	DebugContext(ctx context.Context, msg string, keyvals ...interface{})

	// InfoContext logs an Info event.
	//
	// General information about what's happening inside the system.
	InfoContext(ctx context.Context, msg string, keyvals ...interface{})

	// WarnContext logs a Warn(ing) event.
	//
	// Non-critical events that should be looked at.
	WarnContext(ctx context.Context, msg string, keyvals ...interface{})

	// ErrorContext logs an Error event.
	//
	// Critical events that require immediate attention.
	// Loggers commonly provide Fatal and Panic levels above Error level,
	// but exiting and panicing is out of scope for a logging library.
	ErrorContext(ctx context.Context, msg string, keyvals ...interface{})
}

KVLoggerContext is an optional interface that MAY be implemented by a KVLogger. It is similar to KVLogger, but it receives a context as the first parameter. An implementation MAY extract information from the context and annotate the log context with it.

KVLoggerContext MAY honor the deadline carried by the context, but that's not a hard requirement.

type KVLoggerFacade added in v0.17.0

type KVLoggerFacade interface {
	KVLogger
	KVLoggerContext
}

KVLoggerFacade is a combination of KVLogger and KVLoggerContext. It's sole purpose is to make the API of the package concise by exposing a common interface type for returned loggers. It's not supposed to be used by consumers of this package.

It goes directly against the "Use interfaces, return structs" idiom of Go, but at the current phase of the package the smaller API surface makes more sense.

In the future it might get replaced with concrete types.

func LoggerToKV added in v0.17.0

func LoggerToKV(logger Logger) KVLoggerFacade

LoggerToKV converts a Logger to a KVLogger.

type Level

type Level uint32

Level represents the same levels as defined in Logger.

const (
	// Even more fine-grained information than Debug events.
	// Loggers not supporting this level should fall back to Debug.
	Trace Level = iota

	// A verbose series of information events.
	// They are useful when debugging the system.
	Debug

	// General information about what's happening inside the system.
	Info

	// Non-critical events that should be looked at.
	Warn

	// Critical events that require immediate attention.
	Error
)

Levels as defined in Logger.

func Levels added in v0.17.0

func Levels() []Level

Levels returns a list of available Level values.

func ParseLevel

func ParseLevel(level string) (Level, bool)

ParseLevel takes a string level and returns the defined log level constant. If the level is not defined, it returns false as the second parameter.

func (Level) String

func (l Level) String() string

String converts a Level to string.

func (*Level) UnmarshalText

func (l *Level) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler.

type LevelEnabler

type LevelEnabler interface {
	// LevelEnabled checks if a level is enabled in a logger.
	LevelEnabled(level Level) bool
}

LevelEnabler checks if a level is enabled in a logger. If the logger cannot reliably decide the correct level this method MUST return true.

type LogContextFunc added in v0.16.0

type LogContextFunc func(ctx context.Context, msg string, fields ...map[string]interface{})

LogContextFunc records a log event.

func LevelContextFunc added in v0.17.0

func LevelContextFunc(l Logger, level Level) LogContextFunc

LevelContextFunc returns a LogContextFunc for a level. If the level is invalid it falls back to Info level.

type LogEvent

type LogEvent struct {
	Line   string
	Level  Level
	Fields map[string]interface{}
}

LogEvent represents a single log event recorded by a test logger.

func (LogEvent) AssertEquals added in v0.16.0

func (e LogEvent) AssertEquals(other LogEvent) error

AssertEquals checks if two LogEvent instances are equal and returns an error if not.

func (LogEvent) Equals added in v0.16.0

func (e LogEvent) Equals(other LogEvent) bool

Equals checks if two LogEvent instances are equal.

type LogFunc

type LogFunc func(msg string, fields ...map[string]interface{})

LogFunc records a log event.

func LevelFunc

func LevelFunc(logger Logger, level Level) LogFunc

LevelFunc returns a LogFunc for a level. If the level is invalid it falls back to Info level.

type Logger

type Logger interface {
	// Trace logs a Trace event.
	//
	// Even more fine-grained information than Debug events.
	// Loggers not supporting this level should fall back to Debug.
	Trace(msg string, fields ...map[string]interface{})

	// Debug logs a Debug event.
	//
	// A verbose series of information events.
	// They are useful when debugging the system.
	Debug(msg string, fields ...map[string]interface{})

	// Info logs an Info event.
	//
	// General information about what's happening inside the system.
	Info(msg string, fields ...map[string]interface{})

	// Warn logs a Warn(ing) event.
	//
	// Non-critical events that should be looked at.
	Warn(msg string, fields ...map[string]interface{})

	// Error logs an Error event.
	//
	// Critical events that require immediate attention.
	// Loggers commonly provide Fatal and Panic levels above Error level,
	// but exiting and panicing is out of scope for a logging library.
	Error(msg string, fields ...map[string]interface{})
}

Logger is a unified interface for various logging use cases and practices, including:

  • leveled logging
  • structured logging

func NewNoopLogger deprecated

func NewNoopLogger() Logger

NewNoopLogger creates a no-op logger that discards all received log events. Useful in examples and as a fallback logger.

Deprecated: use NoopLogger.

type LoggerContext added in v0.16.0

type LoggerContext interface {
	// TraceContext logs a Trace event.
	//
	// Even more fine-grained information than Debug events.
	// Loggers not supporting this level should fall back to Debug.
	TraceContext(ctx context.Context, msg string, fields ...map[string]interface{})

	// DebugContext logs a Debug event.
	//
	// A verbose series of information events.
	// They are useful when debugging the system.
	DebugContext(ctx context.Context, msg string, fields ...map[string]interface{})

	// InfoContext logs an Info event.
	//
	// General information about what's happening inside the system.
	InfoContext(ctx context.Context, msg string, fields ...map[string]interface{})

	// WarnContext logs a Warn(ing) event.
	//
	// Non-critical events that should be looked at.
	WarnContext(ctx context.Context, msg string, fields ...map[string]interface{})

	// ErrorContext logs an Error event.
	//
	// Critical events that require immediate attention.
	// Loggers commonly provide Fatal and Panic levels above Error level,
	// but exiting and panicing is out of scope for a logging library.
	ErrorContext(ctx context.Context, msg string, fields ...map[string]interface{})
}

LoggerContext is an optional interface that MAY be implemented by a Logger. It is similar to Logger, but it receives a context as the first parameter. An implementation MAY extract information from the context and annotate the log context with it.

LoggerContext MAY honor the deadline carried by the context, but that's not a hard requirement.

type LoggerFacade added in v0.16.0

type LoggerFacade interface {
	Logger
	LoggerContext
}

LoggerFacade is a combination of Logger and LoggerContext. It's sole purpose is to make the API of the package concise by exposing a common interface type for returned loggers. It's not supposed to be used by consumers of this package.

It goes directly against the "Use interfaces, return structs" idiom of Go, but at the current phase of the package the smaller API surface makes more sense.

In the future it might get replaced with concrete types.

func WithContextExtractor added in v0.16.0

func WithContextExtractor(logger Logger, extractor ContextExtractor) LoggerFacade

WithContextExtractor returns a logger that extracts details from the provided context (if any) and annotates the log event with them.

func WithField added in v0.15.1

func WithField(logger Logger, key string, value interface{}) LoggerFacade

WithField is a shortcut for WithFields(logger, map[string]interface{}{key: value}).

func WithFields

func WithFields(logger Logger, fields map[string]interface{}) LoggerFacade

WithFields returns a new logger instance that attaches the given fields to every subsequent log call.

type MessageLogger

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

MessageLogger simplifies the Logger interface by removing the second context parameter. Useful when there is no need for contextual logging.

func NewMessageLogger

func NewMessageLogger(logger Logger) *MessageLogger

NewMessageLogger returns a new MessageLogger instance.

func (*MessageLogger) Debug

func (l *MessageLogger) Debug(msg string)

Debug logs a Debug level event.

func (*MessageLogger) Error

func (l *MessageLogger) Error(msg string)

Error logs a Error level event.

func (*MessageLogger) Info

func (l *MessageLogger) Info(msg string)

Info logs a Info level event.

func (*MessageLogger) Trace

func (l *MessageLogger) Trace(msg string)

Trace logs a Trace level event.

func (*MessageLogger) Warn

func (l *MessageLogger) Warn(msg string)

Warn logs a Warn level event.

type NoopKVLogger added in v0.17.0

type NoopKVLogger struct{}

NoopKVLogger is a no-op logger that discards all received log events.

It implements both KVLogger and KVLoggerContext interfaces.

func (NoopKVLogger) Debug added in v0.17.0

func (NoopKVLogger) Debug(_ string, _ ...interface{})

func (NoopKVLogger) DebugContext added in v0.17.0

func (NoopKVLogger) DebugContext(_ context.Context, _ string, _ ...interface{})

func (NoopKVLogger) Error added in v0.17.0

func (NoopKVLogger) Error(_ string, _ ...interface{})

func (NoopKVLogger) ErrorContext added in v0.17.0

func (NoopKVLogger) ErrorContext(_ context.Context, _ string, _ ...interface{})

func (NoopKVLogger) Info added in v0.17.0

func (NoopKVLogger) Info(_ string, _ ...interface{})

func (NoopKVLogger) InfoContext added in v0.17.0

func (NoopKVLogger) InfoContext(_ context.Context, _ string, _ ...interface{})

func (NoopKVLogger) Trace added in v0.17.0

func (NoopKVLogger) Trace(_ string, _ ...interface{})

func (NoopKVLogger) TraceContext added in v0.17.0

func (NoopKVLogger) TraceContext(_ context.Context, _ string, _ ...interface{})

func (NoopKVLogger) Warn added in v0.17.0

func (NoopKVLogger) Warn(_ string, _ ...interface{})

func (NoopKVLogger) WarnContext added in v0.17.0

func (NoopKVLogger) WarnContext(_ context.Context, _ string, _ ...interface{})

type NoopLogger added in v0.16.0

type NoopLogger struct{}

NoopLogger is a no-op logger that discards all received log events.

It implements both Logger and LoggerContext interfaces.

func (NoopLogger) Debug added in v0.16.0

func (NoopLogger) Debug(_ string, _ ...map[string]interface{})

func (NoopLogger) DebugContext added in v0.16.0

func (NoopLogger) DebugContext(_ context.Context, _ string, _ ...map[string]interface{})

func (NoopLogger) Error added in v0.16.0

func (NoopLogger) Error(_ string, _ ...map[string]interface{})

func (NoopLogger) ErrorContext added in v0.16.0

func (NoopLogger) ErrorContext(_ context.Context, _ string, _ ...map[string]interface{})

func (NoopLogger) Info added in v0.16.0

func (NoopLogger) Info(_ string, _ ...map[string]interface{})

func (NoopLogger) InfoContext added in v0.16.0

func (NoopLogger) InfoContext(_ context.Context, _ string, _ ...map[string]interface{})

func (NoopLogger) Trace added in v0.16.0

func (NoopLogger) Trace(_ string, _ ...map[string]interface{})

func (NoopLogger) TraceContext added in v0.16.0

func (NoopLogger) TraceContext(_ context.Context, _ string, _ ...map[string]interface{})

func (NoopLogger) Warn added in v0.16.0

func (NoopLogger) Warn(_ string, _ ...map[string]interface{})

func (NoopLogger) WarnContext added in v0.16.0

func (NoopLogger) WarnContext(_ context.Context, _ string, _ ...map[string]interface{})

type PrintLogger

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

PrintLogger logs messages with fmt.Print* function semantics.

func NewErrorPrintLogger

func NewErrorPrintLogger(logger Logger) *PrintLogger

NewErrorPrintLogger returns a new PrintLogger that logs everything on error level.

func NewPrintLogger

func NewPrintLogger(logger LogFunc) *PrintLogger

NewPrintLogger returns a new PrintLogger.

func (*PrintLogger) Print

func (l *PrintLogger) Print(v ...interface{})

Print logs a line with fmt.Print semantics.

func (*PrintLogger) Printf

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

Printf logs a line with fmt.Printf semantics.

func (*PrintLogger) Println

func (l *PrintLogger) Println(v ...interface{})

Println logs a line with fmt.Println semantics.

type TestLogger

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

TestLogger is a Logger recording every log event.

Useful when you want to test behavior with an Logger, but not with LoggerContext. In every other cases TestLoggerFacade should be the default choice of test logger.

The TestLogger is safe for concurrent use.

func NewTestLogger deprecated

func NewTestLogger() *TestLogger

NewTestLogger returns a new TestLogger.

Deprecated: use TestLogger.

func (*TestLogger) Count

func (l *TestLogger) Count() int

Count returns the number of events recorded in the logger.

func (*TestLogger) Debug

func (l *TestLogger) Debug(msg string, fields ...map[string]interface{})

Debug records a Debug level event.

func (*TestLogger) Error

func (l *TestLogger) Error(msg string, fields ...map[string]interface{})

Error records an Error level event.

func (*TestLogger) Events

func (l *TestLogger) Events() []LogEvent

Events returns all recorded events in the logger.

func (*TestLogger) Info

func (l *TestLogger) Info(msg string, fields ...map[string]interface{})

Info records an Info level event.

func (*TestLogger) LastEvent

func (l *TestLogger) LastEvent() *LogEvent

LastEvent returns the last recorded event in the logger (if any).

func (*TestLogger) Trace

func (l *TestLogger) Trace(msg string, fields ...map[string]interface{})

Trace records a Trace level event.

func (*TestLogger) Warn

func (l *TestLogger) Warn(msg string, fields ...map[string]interface{})

Warn records a Warn level event.

type TestLoggerContext added in v0.16.0

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

TestLoggerContext is a LoggerContext recording every log event.

Useful when you want to test behavior with an LoggerContext, but not with Logger. In every other cases TestLoggerFacade should be the default choice of test logger.

The TestLoggerContext is safe for concurrent use.

func (*TestLoggerContext) Count added in v0.16.0

func (l *TestLoggerContext) Count() int

Count returns the number of events recorded in the logger.

func (*TestLoggerContext) DebugContext added in v0.16.0

func (l *TestLoggerContext) DebugContext(ctx context.Context, msg string, fields ...map[string]interface{})

DebugContext records a Debug level event.

func (*TestLoggerContext) ErrorContext added in v0.16.0

func (l *TestLoggerContext) ErrorContext(ctx context.Context, msg string, fields ...map[string]interface{})

ErrorContext records an Error level event.

func (*TestLoggerContext) Events added in v0.16.0

func (l *TestLoggerContext) Events() []LogEvent

Events returns all recorded events in the logger.

func (*TestLoggerContext) InfoContext added in v0.16.0

func (l *TestLoggerContext) InfoContext(ctx context.Context, msg string, fields ...map[string]interface{})

InfoContext records an Info level event.

func (*TestLoggerContext) LastEvent added in v0.16.0

func (l *TestLoggerContext) LastEvent() *LogEvent

LastEvent returns the last recorded event in the logger (if any).

func (*TestLoggerContext) TraceContext added in v0.16.0

func (l *TestLoggerContext) TraceContext(ctx context.Context, msg string, fields ...map[string]interface{})

TraceContext records a Trace level event.

func (*TestLoggerContext) WarnContext added in v0.16.0

func (l *TestLoggerContext) WarnContext(ctx context.Context, msg string, fields ...map[string]interface{})

WarnContext records a Warn level event.

type TestLoggerFacade added in v0.16.0

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

TestLoggerFacade is a LoggerFacade recording every log event.

The TestLoggerFacade is safe for concurrent use.

func (*TestLoggerFacade) Count added in v0.16.0

func (l *TestLoggerFacade) Count() int

Count returns the number of events recorded in the logger.

func (*TestLoggerFacade) Debug added in v0.16.0

func (l *TestLoggerFacade) Debug(msg string, fields ...map[string]interface{})

Debug records a Debug level event.

func (*TestLoggerFacade) DebugContext added in v0.16.0

func (l *TestLoggerFacade) DebugContext(ctx context.Context, msg string, fields ...map[string]interface{})

DebugContext records a Debug level event.

func (*TestLoggerFacade) Error added in v0.16.0

func (l *TestLoggerFacade) Error(msg string, fields ...map[string]interface{})

Error records an Error level event.

func (*TestLoggerFacade) ErrorContext added in v0.16.0

func (l *TestLoggerFacade) ErrorContext(ctx context.Context, msg string, fields ...map[string]interface{})

ErrorContext records an Error level event.

func (*TestLoggerFacade) Events added in v0.16.0

func (l *TestLoggerFacade) Events() []LogEvent

Events returns all recorded events in the logger.

func (*TestLoggerFacade) Info added in v0.16.0

func (l *TestLoggerFacade) Info(msg string, fields ...map[string]interface{})

Info records an Info level event.

func (*TestLoggerFacade) InfoContext added in v0.16.0

func (l *TestLoggerFacade) InfoContext(ctx context.Context, msg string, fields ...map[string]interface{})

InfoContext records an Info level event.

func (*TestLoggerFacade) LastEvent added in v0.16.0

func (l *TestLoggerFacade) LastEvent() *LogEvent

LastEvent returns the last recorded event in the logger (if any).

func (*TestLoggerFacade) Trace added in v0.16.0

func (l *TestLoggerFacade) Trace(msg string, fields ...map[string]interface{})

Trace records a Trace level event.

func (*TestLoggerFacade) TraceContext added in v0.16.0

func (l *TestLoggerFacade) TraceContext(ctx context.Context, msg string, fields ...map[string]interface{})

TraceContext records a Trace level event.

func (*TestLoggerFacade) Warn added in v0.16.0

func (l *TestLoggerFacade) Warn(msg string, fields ...map[string]interface{})

Warn records a Warn level event.

func (*TestLoggerFacade) WarnContext added in v0.16.0

func (l *TestLoggerFacade) WarnContext(ctx context.Context, msg string, fields ...map[string]interface{})

WarnContext records a Warn level event.

Directories

Path Synopsis
examples module
integration
grpc
Package grpc provides a V2 gRPC logger.
Package grpc provides a V2 gRPC logger.
kit
internal

Jump to

Keyboard shortcuts

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