simplelogr

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Oct 2, 2021 License: MIT Imports: 12 Imported by: 2

README

Simple Logr

This little library intended to be a small, customisable component for use with the logr Go library.

Features

  • Simple but configurable. Won't be very efficient, but easy to chop and change it to do what you want.
  • Integrates well with custom error types like github.com/pkg/errors, able to extract stack traces and add them to log messages.

Design

It is broken down into two layers:

  • The Logger which implements the logr.LogSink interface and is responsible for generating log Entry objects.
  • LogSink implementations which are responsible for emitting log Entry objects, to wherever they please, formatted however they like.

There are two provided log sinks:

  • DevelopmentLogSink - intended for local development convenience, with optionally coloured output
  • JSONLogSink - structured JSON logging, intended for production

This library hopes to be made of many composable pieces, such that any component that doesn't suit your requirements can be omitted and replaced. To that end, it uses caller-provided functions where applicable to allow for considerable flexibility before you are forced to resort writing a new LogSink.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	DefaultMessageKey         = "msg"
	DefaultNameKey            = "name"
	DefaultTimestampKey       = "ts"
	DefaultTimestampFormat    = time.RFC3339Nano
	DefaultNameSeparator      = "."
	DefaultTraceVerbosity     = 2
	DefaultDebugVerbosity     = 1
	DefaultSeverityKey        = "severity"
	DefaultErrorKey           = "error"
	DefaultStackTraceKey      = "stacktrace"
	DefaultSeverity           = "INFO"
	DefaultErrorSeverity      = "ERROR"
	DefaultEntrySuffix        = "\n"
	DefaultSpaceSeparator     = " "
	DefaultSeverityThresholds = []SeverityThreshold{
		{Level: DefaultTraceVerbosity, Severity: "TRACE"},
		{Level: DefaultDebugVerbosity, Severity: "DEBUG"},
	}
	DefaultPrimaryColour   = color.New(color.FgHiWhite)
	DefaultSecondaryColour = color.New(color.FgWhite)
	DefaultSeverityColours = map[string]*color.Color{
		"ERROR": color.New(color.FgHiRed),
		"INFO":  color.New(color.FgHiWhite),
		"DEBUG": color.New(color.FgHiBlue),
		"TRACE": color.New(color.FgMagenta),
	}
)

Functions

func DefaultErrorHandler

func DefaultErrorHandler(err error)

DefaultErrorHandler simply emits logging errors to stderr

func DefaultNameEncoder

func DefaultNameEncoder(separator string) func(names []string) string

DefaultNameEncoder assembles a list of logger names by joining them using the provided separator.

func DefaultSeverityEncoder

func DefaultSeverityEncoder(defaultSeverity string, errSeverity string, thresholds []SeverityThreshold) func(verbosity int, err error) string

DefaultSeverityEncoder uses the provided defaults and thresholds to convert verbosity levels into a severity name. - Errors take precedence, using the provided error severity name. - The thresholds are then tested, to identify any specific severities that should be used based on the verbosity level. - Finally a default severity is used.

func DefaultTimestampEncoder

func DefaultTimestampEncoder(format string) func(t time.Time) string

DefaultTimestampEncoder creates a timestamp encoder using the given formatting string

Types

type ColourMode

type ColourMode int

ColourMode controls whether the DevelopmentLogSink emits coloured output or not

const (
	// ColourModeAuto will use the color package's built-in auto-detection to guess whether to use coloured output
	ColourModeAuto ColourMode = iota
	// ColourModeForceOff forces coloured output to be disabled, use this if you're seeing garbled escape characters
	// in the output
	ColourModeForceOff
	// ColourModeForceOn forces coloured output to be produced, use this if you're using an integrated terminal in
	// your development IDE and aren't getting coloured output
	ColourModeForceOn
)

type DevelopmentLogSink

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

DevelopmentLogSink emits unstructured, optionally coloured, text representations of log Entry objects - intended for ease of reading in terminals during local development

func NewDevelopmentLogSink

func NewDevelopmentLogSink(opts DevelopmentLogSinkOptions) *DevelopmentLogSink

NewDevelopmentLogSink creates a new DevelopmentLogSink with the provided options

func (DevelopmentLogSink) Log

func (d DevelopmentLogSink) Log(e Entry) error

Log implements LogSink, encoding the given Entry as human-readable text before writing it to the configured io.Writer

type DevelopmentLogSinkOptions

type DevelopmentLogSinkOptions struct {
	// Output configures where to write logs to
	Output io.Writer
	// ColouredOutput determines whether coloured output will be used, if unspecified it will attempt to auto-detect
	// from the environment. This is usually confused by integrated terminals in IDEs, so for coloured output in IDEs
	// you may wish to use ColourModeForceOn
	ColouredOutput ColourMode
	// SeverityColours maps severity names (produced by SeverityEncoder) to colours, used when displaying severity names
	// and when Entry objects contain an Entry.Error
	SeverityColours map[string]*color.Color
	// PrimaryColour is the colour of log messages, logger names, and the values of key-value pairs
	PrimaryColour *color.Color
	// SecondaryColour is the colour of timestamps, and the keys of key-value pairs
	SecondaryColour *color.Color
	// SeverityEncoder identifies the severity name based on the verbosity level and the presence of any errors
	SeverityEncoder func(level int, err error) string
	// NameEncoder collapses the series of Logger names down into one string for logging
	NameEncoder func(names []string) string
	// TimestampEncoder formats timestamps into string representations
	TimestampEncoder func(t time.Time) string
	// ErrorKey determines the key prefix on any error messages, displayed as though "just another key-value pair",
	// but (if colours are enabled) printed using the relevant colour (see SeverityColours)
	ErrorKey string
	// ErrorEncoder  extracts loggable EncodedError information from an error
	ErrorEncoder func(err error) EncodedError
	// EntrySuffix is appended to the end of log entries, typically to add a newline between them
	EntrySuffix string
	// SpaceSeparator is placed between all log elements: timestamp, severity, logger name, message, and key-value pairs
	// It can be useful, for example, to change this to "\t" to increase spacing - which may improve readability
	SpaceSeparator string
}

DevelopmentLogSinkOptions configures the behaviour of a DevelopmentLogSink

func (*DevelopmentLogSinkOptions) AssertDefaults

func (d *DevelopmentLogSinkOptions) AssertDefaults()

AssertDefaults replaces all uninitialised options with reasonable defaults

type EncodedError

type EncodedError struct {
	// Message is the primary message contained in the error, typically the result of error.Error()
	Message string
	// StackTrace is optional stack trace information extracted from the error
	StackTrace string
}

EncodedError contains information extracted from an error to facilitate logging

func DefaultErrorEncoder

func DefaultErrorEncoder(err error) EncodedError

DefaultErrorEncoder uses an error's error.Error() implementation to populate the EncodedError.Message, and has support for github.com/pkg/errors which may have built-in stack traces. If it detects a built-in stack trace it will populate the EncodedError.StackTrace with it.

type Entry

type Entry struct {
	// Level is the verbosity level of this log event, 0 being "least verbose", and larger numbers being more verbose
	Level int
	// Names is the list of names accumulated by chained calls to Logger.WithName
	Names []string
	// Timestamp is the time the log message was captured
	Timestamp time.Time
	// Message is typically a static string associated with the cause of the log event, often a short explanation of
	// what has occurred
	Message string
	// KVs is a sequence of keys and values, stored [key1, value1, key2, value2, ...], populated by both calls to
	// Logger.WithValues and the keysAndValues arguments to Logger.Info and Logger.Error
	KVs []interface{}
	// Error is the error passed to Logger.Error, and may be nil.
	Error error
}

Entry represents a log entry prepared by Logger, ready for a LogSink to emit (typically by writing to stdout/stderr)

type JSONLogSink

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

JSONLogSink emits structured JSON representations of log Entry objects

func NewJSONLogSink

func NewJSONLogSink(options JSONLogSinkOptions) *JSONLogSink

NewJSONLogSink creates a new JSONLogSink with the provided options

func (JSONLogSink) Log

func (j JSONLogSink) Log(e Entry) error

Log implements LogSink, encoding the given Entry as JSON before writing it to the configured io.Writer

type JSONLogSinkOptions

type JSONLogSinkOptions struct {
	// Output configures where to write structured JSON logs to
	Output io.Writer
	// SeverityKey determines the top level JSON object key to store the log severity name in
	SeverityKey string
	// SeverityEncoder identifies the severity name based on the verbosity level and the presence of any errors
	SeverityEncoder func(level int, err error) string
	// NameKey determines the top level JSON object key to store the logger name in
	NameKey string
	// NameEncoder collapses the series of Logger names down into one string for logging
	NameEncoder func(names []string) string
	// MessageKey determines the top level JSON object key to store the log message in
	MessageKey string
	// TimestampKey determines the top level JSON object key to store the timestamp in
	TimestampKey string
	// TimestampEncoder formats timestamps into string representations
	TimestampEncoder func(t time.Time) string
	// ErrorKey determines the top level JSON object key to store any error messages in
	ErrorKey string
	// StackTraceKey determines the top level JSON object key to store any stack trace information in
	StackTraceKey string
	// ErrorEncoder  extracts loggable EncodedError information from an error
	ErrorEncoder func(err error) EncodedError
}

JSONLogSinkOptions configures the behaviour of a JSONLogSink

func (*JSONLogSinkOptions) AssertDefaults

func (j *JSONLogSinkOptions) AssertDefaults()

AssertDefaults replaces all uninitialised options with reasonable defaults

type LogSink

type LogSink interface {
	Log(e Entry) error
}

LogSink is a system that accepts log Entry objects and handles them, typically by encoding them and emitting them to some destination, e.g. encoding into JSON and then emitting to stdout

type Logger

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

Logger implements the logr.LogSink interface

func New

func New(opts Options) *Logger

New creates a new Logger using the provided Options, applying reasonable defaults where options aren't specified

func (Logger) Enabled

func (l Logger) Enabled(level int) bool

Enabled determines whether this logger would emit Info messages at the specified verbosity level

func (Logger) Error

func (l Logger) Error(err error, msg string, keysAndValues ...interface{})

Error emits an log message associated with an error

func (Logger) Info

func (l Logger) Info(level int, msg string, keysAndValues ...interface{})

Info emits an info level log message

func (*Logger) Init

func (l *Logger) Init(info logr.RuntimeInfo)

Init accepts runtime information from the parent logr.Logger

func (Logger) WithName

func (l Logger) WithName(name string) logr.LogSink

WithName produces a new logger with an additional name segment

func (Logger) WithValues

func (l Logger) WithValues(keysAndValues ...interface{}) logr.LogSink

WithValues produces a new logger containing additional key value pairs

type Options

type Options struct {
	Sink         LogSink
	Verbosity    int
	ErrorHandler func(err error)
}

Options controls the configuration of a new Logger, see New

type SeverityThreshold

type SeverityThreshold struct {
	// Level at which the verbosity level must be greater than or equal to in order to satisfy this threshold
	Level int
	// Severity is the the severity level name
	Severity string
}

SeverityThreshold describes a verbosity level at which logs are associated with a given severity level string

type SynchronizedWriter

type SynchronizedWriter struct {
	Underlying io.Writer
	// contains filtered or unexported fields
}

SynchronizedWriter is used for wrapping an io.Writer with a sync.Mutex so that it is thread safe, e.g. when wrapping file handles.

func SynchronizeWritesTo

func SynchronizeWritesTo(w io.Writer) *SynchronizedWriter

SynchronizeWritesTo wraps an io.Writer, producing a new io.Writer that is thread-safe

func (*SynchronizedWriter) Write

func (s *SynchronizedWriter) Write(p []byte) (n int, err error)

Write implements io.Writer, acquiring a mutex to prevent concurrency issues when writing to the underlying io.Writer

Directories

Path Synopsis
examples module

Jump to

Keyboard shortcuts

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