logfunk

package module
v1.1.1 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2023 License: MIT Imports: 12 Imported by: 2

README

logfunk

Package logfunk provides a concise, pluggable API for structured logging.

logfunk uses custom type arguments to set additional logging options:

  • optional spew output (struct decomposition) through %#+v
  • optional json output (exported fields only) through %j
  • adaptable output
  • severity levels
  • structured logging
  • call-site logging
  • stackable logging context

Basic use

package main

import "git.pixeltamer.net/gopub/logfunk"

func main() {
	log := logfunk.MakeF(nil) // create a log func on os.Stdout/os.Stderr
	log("Hello World!")       // print a line
}

Output:

20210109.203008.622866 Info  : Hello World!

Stacked Log Functions

Log functions can be created on top of existing log functions. Child log functions inherit the parameters of their parent. New parameters on the child function override those of the parent, except for logfunk.Module, which gets appended for context.

package main

import "git.pixeltamer.net/gopub/logfunk"

func main() {
	log:=logfunk.MakeF(nil,logfunk.Module("Example")) // create a log func on os.Stdout/os.Stderr
	log("In main") // print a line
	sub1(log)
}

func sub1(l logfunk.F) {
	log:=logfunk.MakeF(l,logfunk.Module("Sub1"))
	log(logfunk.Warn,"In sub1")
	sub2(log)
}

func sub2(l logfunk.F) {
	log:=logfunk.MakeF(l,logfunk.Module("Sub2"))
	log(logfunk.Error,"In sub2")
}

Output:

20210109.203512.943886 Info  Example: In main
20210109.203512.943908 Warn  Example.Sub1: In sub1
20210109.203512.943915 Error Example.Sub1.Sub2: In sub2

Log Level

package main

import "git.pixeltamer.net/gopub/logfunk"

func main() {
	log := logfunk.MakeF(nil, // create a log func on os.Stdout/os.Stderr,
		logfunk.Module("Example"),      // with module name "Example",
		logfunk.MinLevel(logfunk.Warn), // minimum Level Warn
		logfunk.ShortTime)              // and short time stamps
	log(logfunk.Info, "Info")   // print a Info line, ignored due to MinLevel
	log(logfunk.Warn, "Warn")   // print a Warn line
	log(logfunk.Error, "Error") // print a Error line
}

Output:

203908.059 Warn  Example: Warn
203908.059 Error Example: Error

Attributes

package main

import "git.pixeltamer.net/gopub/logfunk"

func main() {
	log := logfunk.MakeF(nil)                        // create a log func on os.Stdout/os.Stderr
	log(logfunk.KV("SomeValue", 42), "Hello World!") // print a line
}

Output:

20210109.204145.943847 Info  : Hello World! [SomeValue="42"]

Advanced Formatting

package main

import "git.pixeltamer.net/gopub/logfunk"

func main() {
	log := logfunk.MakeF(nil) // create a log func on os.Stdout/os.Stderr
	v := struct {
		A int
		B []string
	}{
		A: 27,
		B: []string{"1", "a", "Z"},
	}
	log(logfunk.KV("SomeStruct", v), "Line 1") // complex values are %v-printed
	log("Line 2:\n%#+v", v)                    // optional spew deconstruction
	log("Line 3:\n%j", v)                      // optional json deconstruction
}

Output:

20210124.111714.039069 Info  : Line 1 [SomeStruct="{27 [1 a Z]}"]
20210124.111714.039076 Info  : Line 2:
20210124.111714.039076 Info  : (struct { A int; B []string }){A:(int)27 B:([]string)[1 a Z]}
20210124.111714.039089 Info  : Line 3:
20210124.111714.039089 Info  : {
20210124.111714.039089 Info  :   "A": 27,
20210124.111714.039089 Info  :   "B": [
20210124.111714.039089 Info  :     "1",
20210124.111714.039089 Info  :     "a",
20210124.111714.039089 Info  :     "Z"
20210124.111714.039089 Info  :   ]
20210124.111714.039089 Info  : }

Note that line breaks are separated into individual log entries for consistent indentation.

Parameter Placement

logfunk uses specially typed parameters to provide extended functionality. Any such parameters are applied as arguments to the MakeF() function. Additionally, special parameters appearing before the format string argument in log func calls apply to a single call.

package main

import "git.pixeltamer.net/gopub/logfunk"

func main() {
	log := logfunk.MakeF(nil)                  // create a log func on os.Stdout/os.Stderr
	log(logfunk.Warn, "Line 1", logfunk.Error) // only leading parameters are effective
}
20210109.205426.699710 Warn  : Line 1%!(EXTRA *spew.formatState=Error)

Call site logging

Passing the logfunk.ShowCaller flag to MakeF or the log function causes an attribute "Caller" to be set with the name of the calling function and the line number in the source file.

log.Logger Shim

logfunk.NewLogger(logfunk.F) creates a struct that implements all log.Logger methods to enable mixed use.

Custom LogSink

Any implementation of the LogSink interface can act as a target for logging. Additionally, the WriterSink and StdSink functions are provided.

WriterSink creates a LogSink that outputs to a given io.Writer.

StdSink creates a LogSink that outputs to os.Stdout (Spam, Debug and Info levels) and os.Stderr (Warn, Error and Fatal levels).

Reference

Extended log func parameters
 // log severity level
Level
	Spam
	Debug
	Info
	Warn
	Error
	Fatal

 // minimum severity level
MinLevel

type KeyValue struct { // structured attribute, also see logfunk.KV()
	Key   string
	Value string
}

// Flags should be set at the root log function and modify the verboseness.
type Flags uint32
	ShortTime   // use a shorter timestamp format
	LongTime    // use the default long timestamp format (default)
	HideLevel   // do not print the severity level
	ShowLevel   // print the severity level (default)
	HideModule  // do not print the module name
    ShowModule  // print the module name (default)
    HideCaller  // do not print the callers info (default)
	ShowCaller  // print the callers function name and line number
	LineSplit   // split output with \n into multiple lines (default)
	NoLineSplit // do not split multiline output

// Module is a typed string capturing a module name for logging. Stacked Module names are concatenated with dots in the output.
type Module string

// Extractor values are special log arguments that cause context information to be returned from a log function.
type Extractor int
	// ExtractSink has to be followed by a *LogSink argument that gets set to the parent LogSink instance for this log function.
	ExtractSink
	// ExtractDefaults has to be followed by a *[]interface{} argument that gets set to the default parameters for this log function.
	ExtractDefaults
Types
// F is a logging function with some twists. All instances of F should be created through MakeF(). F implements the LogSink interface for stacking.
type F func(args ...interface{})

// The LogSink interface processes LogEntry values and provides default parameters. It is implemented by all logfunk.F returned from logfunk.MakeF()
type LogSink interface {
	LogCommit(le LogEntry)
	LogDefaults() []interface{}
}

// A LogEntry captures all information for a single log line.
type LogEntry struct {
	Time   timestamp.TS
	Level  Level
	Module string
	Text   string
	Flags  Flags
	Attr   map[string]string
}
Functions
// KV creates a KeyValue object from a key name and an arbitrary value. val is taken verbatim if a string, String()ed if it implements fmt.Stringer and otherwises spew'ed
func KV(key string, val interface{}) KeyValue 

// WriterSink creates a LogSink wrapper around a writer with optional defaults
func WriterSink(w io.Writer, defaults ...interface{}) LogSink 

// StdSink creates a LogSink printing to os.StdOut or os.StdErr depending on Level
func StdSink(defaults ...interface{}) LogSink 

// MakeF creates a new log function on a LogSink (which can be another LogFunc or nil) with optional default values
func MakeF(ls LogSink, defaults ...interface{}) F 

// GetSink returns the LogSink that was used to create this LogFunc
func (lf F) GetSink() LogSink

Timestamp Type

logfunk uses git.pixeltamer.net/gopub/timestamp instead of the conventioal time.Time type. The motivation for this is:

  • Always UTC, no timezone shenanigans
  • Compact representation
  • Encodable as javascript-compatible float64 value
  • Stores easily as int64 in databases

Benchmarks

logfunk uses variadic parameters, so some heap allocation is currently unavoidable.

BenchmarkLogFunk/FixedString-16         	 6309463	       245 ns/op	     112 B/op	       3 allocs/op
BenchmarkLogFunk/FixedLongString-16     	 5667570	       240 ns/op	     112 B/op	       3 allocs/op
BenchmarkLogFunk/Format-16              	 1412878	       772 ns/op	     272 B/op	       8 allocs/op
BenchmarkLogFunk/FormatIgnored-16       	 7940806	       193 ns/op	     128 B/op	       3 allocs/op
BenchmarkLogFunk/FixedAttrib1-16        	 1000000	      1194 ns/op	     656 B/op	      11 allocs/op
BenchmarkLogFunk/FixedAttrib5-16        	 1000000	      1316 ns/op	     848 B/op	      15 allocs/op
BenchmarkLogFunk/FixedAttrib5Ignored-16 	 1288423	      1073 ns/op	     704 B/op	      10 allocs/op

License

MIT License

(c) pixeltamer.net 2021

Documentation

Overview

Package logfunk provides a concise, pluggable API for structured logging.

logfunk uses custom type arguments to set additional logging options.

See README.md for details.

Index

Constants

View Source
const (
	// ExtractSink has to be followed by a *LogSink argument that gets set to the parent LogSink instance for this log function.
	ExtractSink = Extractor(0)
	// ExtractDefaults has to be followed by a *[]interface{} argument that gets set to the default parameters for this log function.
	ExtractDefaults = Extractor(1)
)

Variables

This section is empty.

Functions

func P added in v1.0.9

func P(args ...interface{})

P is a convenience logging function using the StdSink. It is initialized on demand.

func PPrep added in v1.0.9

func PPrep(args ...interface{})

PPrep sets defaults for the logfunk.P convenience function

Types

type Extractor

type Extractor int

Extractor values are special log arguments that cause context information to be returned from a log function.

type F

type F func(args ...interface{})

F is a logging function with some twists. All instances of F should be created through MakeF(). F implements the LogSink interface for stacking.

func MakeF

func MakeF(defaults ...interface{}) F

MakeF creates a new log function on a LogSink (which can be another LogFunc or nil) with optional default values

func (F) GetSink

func (lf F) GetSink() LogSink

GetSink returns the LogSink that was used to create this LogFunc

func (F) LogCommit

func (lf F) LogCommit(le LogEntry)

LogCommit submits a LogEntry into the LogFuncs sink

func (F) LogCommitMulti added in v1.0.13

func (lf F) LogCommitMulti(lel []LogEntry)

LogCommitMulti submits a LogEntry into the LogFuncs sink

func (F) LogDefaults

func (lf F) LogDefaults() []interface{}

LogDefaults retrieves the default values provided to LogMakeFunc originally

func (F) LogLevel added in v1.0.4

func (lf F) LogLevel() Level

LogLevel returns the effective MinLevel on this F

type Flags

type Flags uint32

Flags should be set at the root log function and modify the verboseness.

const (
	ShortTime     Flags = 1 << 0
	LongTime      Flags = 0xffffffff ^ ShortTime
	HideLevel     Flags = 1 << 1
	ShowLevel     Flags = 0xffffffff ^ HideLevel
	HideModule    Flags = 1 << 2
	ShowModule    Flags = 0xffffffff ^ HideModule
	HideCaller    Flags = 0xffffffff ^ ShowCaller
	ShowCaller    Flags = 1 << 3
	LineSplit     Flags = 0xffffffff ^ NoLineSplit
	NoLineSplit   Flags = 1 << 4
	HideTime      Flags = 0xffffffff ^ ShowTime
	ShowTime      Flags = 1 << 5
	RFC5424Format Flags = 1 << 6 // todo
)

Flags

type KeyValue

type KeyValue struct {
	Key   string
	Value string
}

KeyValue captures a named value for structured logging

func KV

func KV(key string, val interface{}) KeyValue

KV creates a KeyValue object from a key name and an arbitrary value. val is taken verbatim if a string, String()ed if it implements fmt.Stringer and otherwises spew'ed

type Level

type Level int

Level specifies a severity level for a log message. Possible values are Spam, Debug, Info, Warn, Error and Fatal.

const (
	Spam Level = iota
	Debug
	Info
	Warn
	Error
	Fatal
)

Level constants

func (Level) AlString

func (ls Level) AlString() string

AlString returns an aligned string

func (Level) String

func (ls Level) String() string

type LogEntry

type LogEntry struct {
	Time   timestamp.TS
	Level  Level
	Module string
	Text   string
	Flags  Flags
	Attr   map[string]string
}

A LogEntry captures all information for a single log line.

func (*LogEntry) AddCallerAttribute

func (le *LogEntry) AddCallerAttribute()

AddCallerAttribute sets a "Caller" value to the function and the line number in the source file

func (*LogEntry) String

func (le *LogEntry) String() string

String implements the Stringer interface

type LogSink

type LogSink interface {
	LogCommit(le LogEntry)
	LogDefaults() []interface{}
}

The LogSink interface processes LogEntry values and provides default parameters. It is implemented by all logfunk.F returned from logfunk.MakeF()

func FmtSink added in v1.0.11

func FmtSink(defaults ...interface{}) LogSink

FmtSink creates a LogSink printing to fmt.Printf

func SilentSink added in v1.0.6

func SilentSink(defaults ...interface{}) LogSink

SilentSink creates a LogSink that silently ignores all log entries

func StdSink

func StdSink(defaults ...interface{}) LogSink

StdSink creates a LogSink printing to os.StdOut or os.StdErr depending on Level

func WriterSink

func WriterSink(w io.Writer, defaults ...interface{}) LogSink

WriterSink creates a LogSink wrapper around a writer with optional defaults"

type LogSinkExt added in v1.0.13

type LogSinkExt interface {
	LogCommitMulti(le []LogEntry)
}

The LogSinkExt interface processes LogEntry values and provides default parameters. It is implemented by all logfunk.F returned from logfunk.MakeF()

type Logger

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

Logger mimics the log.Logger structure

func NewLogger

func NewLogger(f F) *Logger

NewLogger creates a new log.Logger-compatible Logger wrapping f

func (*Logger) Fatal

func (l *Logger) Fatal(v ...interface{})

Fatal mimics log.Logger

func (*Logger) Fatalf

func (l *Logger) Fatalf(format string, v ...interface{})

Fatalf mimics log.Logger

func (*Logger) Fatalln

func (l *Logger) Fatalln(v ...interface{})

Fatalln mimics log.Logger

func (*Logger) Flags

func (l *Logger) Flags() int

Flags mimics log.Logger

func (*Logger) Output

func (l *Logger) Output(calldepth int, s string) error

Output mimics log.Logger

func (*Logger) Panic

func (l *Logger) Panic(v ...interface{})

Panic mimics log.Logger

func (*Logger) Panicf

func (l *Logger) Panicf(format string, v ...interface{})

Panicf mimics log.Logger

func (*Logger) Panicln

func (l *Logger) Panicln(v ...interface{})

Panicln mimics log.Logger

func (*Logger) Prefix

func (l *Logger) Prefix() string

Prefix mimics log.Logger, returns an empty string

func (*Logger) Print

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

Print mimics log.Logger

func (*Logger) Printf

func (l *Logger) Printf(format string, v ...interface{})

Printf mimics log.Logger

func (*Logger) Println

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

Println mimics log.Logger

func (*Logger) SetFlags

func (l *Logger) SetFlags(flag int)

SetFlags mimics log.Logger, but is a nop

func (*Logger) SetOutput

func (l *Logger) SetOutput(w io.Writer)

SetOutput mimics log.Logger, but is a nop

func (*Logger) SetPrefix

func (l *Logger) SetPrefix(prefix string)

SetPrefix mimics log.Logger, but is a nop

func (*Logger) Writer

func (l *Logger) Writer() io.Writer

Writer mimics log.Logger, but returns os.Stdout

type MinLevel

type MinLevel int

MinLevel specifies the minimum severity level for a log message not to be ignored.

type Module

type Module string

Module is a typed string capturing a module name for logging. Stacked Module names are concatenated with dots in the output.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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