formatr

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2023 License: Apache-2.0 Imports: 11 Imported by: 0

README

formatr

formatr is a log formatter derived from (and compatible with) go-logr/funcr which adds klog-like output formatting.

license

Apache v2, like go-logr

origin

imported from https://github.com/go-logr/logr.git @ 2ea8628b184c8ed00c5698d7798d30e49deb454d

Documentation

Overview

Package formatr implements formatting of structured log messages and optionally captures the call site and timestamp.

The simplest way to use it is via its implementation of a github.com/go-logr/logr.LogSink with output through an arbitrary "write" function. See New and NewJSON for details.

Custom LogSinks

For users who need more control, a formatr.Formatter can be embedded inside your own custom LogSink implementation. This is useful when the LogSink needs to implement additional methods, for example.

Formatting

This will respect logr.Marshaler, fmt.Stringer, and error interfaces for values which are being logged. When rendering a struct, formatr will use Go's standard JSON tags (all except "string").

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Caller

type Caller struct {
	// File is the basename of the file for this call site.
	File string `json:"file"`
	// Line is the line number in the file for this call site.
	Line int `json:"line"`
	// Func is the function name for this call site, or empty if
	// Options.LogCallerFunc is not enabled.
	Func string `json:"function,omitempty"`
}

Caller represents the original call site for a log line, after considering logr.Logger.WithCallDepth and logr.Logger.WithCallStackHelper. The File and Line fields will always be provided, while the Func field is optional. Users can set the render hook fields in Options to examine logged key-value pairs, one of which will be {"caller", Caller} if the Options.LogCaller field is enabled for the given MessageClass.

type Formatter

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

Formatter is an opaque struct which can be embedded in a LogSink implementation. It should be constructed with NewFormatter. Some of its methods directly implement logr.LogSink.

Example
package main

import (
	"fmt"
	"strings"

	"github.com/go-logr/logr"

	"github.com/ffromani/formatr"
)

// NewStdoutLogger returns a logr.Logger that prints to stdout.
// It demonstrates how to implement a custom With* function which
// controls whether INFO or ERROR are printed in front of the log
// message.
func NewStdoutLogger() logr.Logger {
	l := &stdoutlogger{
		Formatter: formatr.NewFormatter(formatr.Options{}),
	}
	return logr.New(l)
}

type stdoutlogger struct {
	formatr.Formatter
	logMsgType bool
}

func (l stdoutlogger) WithName(name string) logr.LogSink {
	l.Formatter.AddName(name)
	return &l
}

func (l stdoutlogger) WithValues(kvList ...any) logr.LogSink {
	l.Formatter.AddValues(kvList)
	return &l
}

func (l stdoutlogger) WithCallDepth(depth int) logr.LogSink {
	l.Formatter.AddCallDepth(depth)
	return &l
}

func (l stdoutlogger) Info(level int, msg string, kvList ...any) {
	prefix, args := l.FormatInfo(level, msg, kvList)
	l.write("INFO", prefix, args)
}

func (l stdoutlogger) Error(err error, msg string, kvList ...any) {
	prefix, args := l.FormatError(err, msg, kvList)
	l.write("ERROR", prefix, args)
}

func (l stdoutlogger) write(msgType, prefix, args string) {
	var parts []string
	if l.logMsgType {
		parts = append(parts, msgType)
	}
	if prefix != "" {
		parts = append(parts, prefix)
	}
	parts = append(parts, args)
	fmt.Println(strings.Join(parts, ": "))
}

// WithLogMsgType returns a copy of the logger with new settings for
// logging the message type. It returns the original logger if the
// underlying LogSink is not a stdoutlogger.
func WithLogMsgType(log logr.Logger, logMsgType bool) logr.Logger {
	if l, ok := log.GetSink().(*stdoutlogger); ok {
		clone := *l
		clone.logMsgType = logMsgType
		log = log.WithSink(&clone)
	}
	return log
}

// Assert conformance to the interfaces.
var _ logr.LogSink = &stdoutlogger{}
var _ logr.CallDepthLogSink = &stdoutlogger{}

func main() {
	l := NewStdoutLogger()
	l.Info("no message type")
	WithLogMsgType(l, true).Info("with message type")
}
Output:

"level"=0 "msg"="no message type"
INFO: "level"=0 "msg"="with message type"

func NewFormatter

func NewFormatter(opts Options) Formatter

NewFormatter constructs a Formatter which emits a JSON-like key=value format.

func NewFormatterJSON

func NewFormatterJSON(opts Options) Formatter

NewFormatterJSON constructs a Formatter which emits strict JSON.

func NewFormatterKlog added in v0.2.0

func NewFormatterKlog(opts Options) Formatter

NewFormatterKlog constructs a Formatter which emits a klog-like format.

func (*Formatter) AddCallDepth

func (f *Formatter) AddCallDepth(depth int)

AddCallDepth increases the number of stack-frames to skip when attributing the log line to a file and line.

func (*Formatter) AddName

func (f *Formatter) AddName(name string)

AddName appends the specified name. formatr uses '/' characters to separate name elements. Callers should not pass '/' in the provided name string, but this library does not actually enforce that.

func (*Formatter) AddValues

func (f *Formatter) AddValues(kvList []any)

AddValues adds key-value pairs to the set of saved values to be logged with each log line.

func (Formatter) Enabled

func (f Formatter) Enabled(level int) bool

Enabled checks whether an info message at the given level should be logged.

func (Formatter) FormatError

func (f Formatter) FormatError(err error, msg string, kvList []any) (prefix, argsStr string)

FormatError renders an Error log message into strings. The prefix will be empty when no names were set (via AddNames), or when the output is configured for JSON.

func (Formatter) FormatInfo

func (f Formatter) FormatInfo(level int, msg string, kvList []any) (prefix, argsStr string)

FormatInfo renders an Info log message into strings. The prefix will be empty when no names were set (via AddNames), or when the output is configured for JSON.

func (Formatter) GetDepth

func (f Formatter) GetDepth() int

GetDepth returns the current depth of this Formatter. This is useful for implementations which do their own caller attribution.

func (*Formatter) Init

func (f *Formatter) Init(info logr.RuntimeInfo)

Init configures this Formatter from runtime info, such as the call depth imposed by logr itself. Note that this receiver is a pointer, so depth can be saved.

type MessageClass

type MessageClass int

MessageClass indicates which category or categories of messages to consider.

const (
	// None ignores all message classes.
	None MessageClass = iota
	// All considers all message classes.
	All
	// Info only considers info messages.
	Info
	// Error only considers error messages.
	Error
)

type Options

type Options struct {
	// LogCaller tells formatr to add a "caller" key to some or all log lines.
	// This has some overhead, so some users might not want it.
	LogCaller MessageClass

	// LogCallerFunc tells formatr to also log the calling function name.  This
	// has no effect if caller logging is not enabled (see Options.LogCaller).
	LogCallerFunc bool

	// LogTimestamp tells formatr to add a "ts" key to log lines.  This has some
	// overhead, so some users might not want it.
	LogTimestamp bool

	// TimestampFormat tells formatr how to render timestamps when LogTimestamp
	// is enabled.  If not specified, a default format will be used.  For more
	// details, see docs for Go's time.Layout.
	TimestampFormat string

	// Verbosity tells formatr which V logs to produce.  Higher values enable
	// more logs.  Info logs at or below this level will be written, while logs
	// above this level will be discarded.
	Verbosity int

	// RenderBuiltinsHook allows users to mutate the list of key-value pairs
	// while a log line is being rendered.  The kvList argument follows logr
	// conventions - each pair of slice elements is comprised of a string key
	// and an arbitrary value (verified and sanitized before calling this
	// hook).  The value returned must follow the same conventions.  This hook
	// can be used to audit or modify logged data.  For example, you might want
	// to prefix all of formatr's built-in keys with some string.  This hook is
	// only called for built-in (provided by formatr itself) key-value pairs.
	// Equivalent hooks are offered for key-value pairs saved via
	// logr.Logger.WithValues or Formatter.AddValues (see RenderValuesHook) and
	// for user-provided pairs (see RenderArgsHook).
	RenderBuiltinsHook func(kvList []any) []any

	// RenderValuesHook is the same as RenderBuiltinsHook, except that it is
	// only called for key-value pairs saved via logr.Logger.WithValues.  See
	// RenderBuiltinsHook for more details.
	RenderValuesHook func(kvList []any) []any

	// RenderArgsHook is the same as RenderBuiltinsHook, except that it is only
	// called for key-value pairs passed directly to Info and Error.  See
	// RenderBuiltinsHook for more details.
	RenderArgsHook func(kvList []any) []any

	// MaxLogDepth tells formatr how many levels of nested fields (e.g. a struct
	// that contains a struct, etc.) it may log.  Every time it finds a struct,
	// slice, array, or map the depth is increased by one.  When the maximum is
	// reached, the value will be converted to a string indicating that the max
	// depth has been exceeded.  If this field is not specified, a default
	// value will be used.
	MaxLogDepth int
}

Options carries parameters which influence the way logs are generated.

type PseudoStruct

type PseudoStruct []any

PseudoStruct is a list of key-value pairs that gets logged as a struct.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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