logiface

package module
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Mar 31, 2023 License: MIT Imports: 8 Imported by: 4

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrDisabled is a sentinel value that can be returned by a Modifier to
	// disable logging of the event, or by a Writer to indicate that the event
	// was not written.
	//
	// It may also return from Logger.Log.
	ErrDisabled = errors.New(`logger disabled`)
)
View Source
var (
	// L exposes New and it's Option functions (e.g. WithWriter) as
	// methods, using the generic Event type.
	//
	// It's provided as a convenience.
	L = LoggerFactory[Event]{}
)
View Source
var (
	// OsExit is a variable that can be overridden to change the behavior of
	// fatal errors. It is set to [os.Exit] by default.
	OsExit = os.Exit
)

Functions

func ArgFields

func ArgFields[E any, R interface {
	Enabled() bool
	Field(key string, val any) R
}](r R, f func(key E) (string, bool), l ...E) R

ArgFields is a helper function that calls Builder.Field or Context.Field, for every element of a (varargs) slice. If provided, f will be used to ensure that each key is a string, otherwise, if not provided, each key will be converted to a string, using fmt.Sprint. Passing an odd number of keys will set the last value to any(nil).

WARNING: The behavior of the Context.Field and Builder.Field methods may change without notice, to facilitate the addition of new field types.

Example
// l is an instance of logiface.Logger
l := mockL.New(
	mockL.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
	mockL.WithWriter(&mockSimpleWriter{Writer: os.Stdout}),
	mockL.WithLevel(LevelDebug),
)

// supports logiface.Builder
ArgFields(l.Notice(), nil, "a", "A", "b", "B").Log(``)

// supports logiface.Context
ArgFields(l.Clone(), nil, "a", "A", "b", "B").Logger().Alert().
	Log(``)

// supports fluent chaining
ArgFields(l.Crit().
	Str(`a`, `A1`).
	Str(`b`, `B`), nil, "a", "A2", "c", "C1", "d", "D", "c", "C2", "e", "E").
	Str(`c`, `C3`).
	Str(`f`, `F`).
	Log(``)

// supports conversion function
ArgFields(l.Debug(), func(key any) (string, bool) {
	if k, ok := key.(string); ok {
		return k + "_converted", true
	}
	return "", false
}, "a", "A", "b", "B", 123, "C").
	Log(``)

// passing an odd number of keys sets the last value to any(nil)
ArgFields(l.Info(), nil, "a", "A", "b").Log(``)
Output:

[notice] a=A b=B
[alert] a=A b=B
[crit] a=A1 b=B a=A2 c=C1 d=D c=C2 e=E c=C3 f=F
[debug] a_converted=A b_converted=B
[info] a=A b=<nil>

func MapFields

func MapFields[K ~string, V any, R interface {
	Enabled() bool
	Field(key string, val any) R
}](r R, m map[K]V) R

MapFields is a helper function that calls Builder.Field or Context.Field, for every element of a map, which must have keys with an underlying type of string. The field order is not stable, as it iterates on the map, without sorting the keys.

WARNING: The behavior of the Context.Field and Builder.Field methods may change without notice, to facilitate the addition of new field types.

Example
// note that the order of keys is not stable (sorted only to make the test pass)
w, out := sortedLineWriterSplitOnSpace(os.Stdout)
defer func() {
	_ = w.Close()
	<-out
}()

// l is an instance of logiface.Logger
l := newSimpleLogger(w, false)

// supports logiface.Builder
MapFields(l.Notice(), map[string]interface{}{
	`a`: `A`,
	`b`: `B`,
}).Log(``)

// supports logiface.Context
MapFields(l.Clone(), map[string]interface{}{
	`a`: `A`,
	`b`: `B`,
}).Logger().Alert().
	Log(``)

// supports fluent chaining
MapFields(l.Crit().
	Str(`a`, `A1`).
	Str(`b`, `B`), map[string]interface{}{
	`a`: `A2`,
	`c`: `C1`,
	`d`: `D`}).
	Str(`c`, `C2`).
	Str(`e`, `E`).
	Log(``)

// supports any map with string as the underlying key type
type Stringish string
type Mappy map[Stringish]int
m := Mappy{
	`a`: 1,
	`b`: 2,
}
MapFields(l.Build(99), m).Log(``)

_ = w.Close()
if err := <-out; err != nil {
	panic(err)
}
Output:

[notice] a=A b=B
[alert] a=A b=B
[crit] a=A1 a=A2 b=B c=C1 c=C2 d=D e=E
[99] a=1 b=2

Types

type ArrayBuilder added in v0.4.0

type ArrayBuilder[E Event, P Parent[E]] refPoolItem
Example (DefaultFieldFormats)

Demonstrates the default array field formats, if the array support is defaulted.

// note that this will print one top-level field per line
logger := newSimpleLoggerPrintTypes(os.Stdout, true)

logger.Info().
	Array().Field(time.Second*1).Dur(time.Second*3).Dur(time.Second/8).Field(time.Duration(float64(time.Hour)*3.51459)).As(`durs`).End().
	Array().Str(`str val`).As(`str`).End().
	Array().Bool(true).Bool(false).As(`bools`).End().
	Array().Any(map[int]float64{1: 1.0, 2: 1.0 / 2.0, 3: 1.0 / 3.0}).As(`map`).End().
	Array().Err(errors.New(`some error`)).As(`err`).End().
	Array().Int(123).As(`int`).End().
	Array().Uint64(123).As(`uint64`).End().
	Array().Int64(123).As(`int64`).End().
	Array().Float32(1.0/3.0).As(`float32`).End().
	Array().Float64(1.0/3.0).As(`float64`).End().
	Array().Time(time.Unix(0, 0).UTC()).As(`time`).End().
	Array().Base64([]byte(`valasrdijasdu8jasidjasd`), nil).As(`base64`).End().
	Log(``)
Output:

[info]
durs=[(string)1s (string)3s (string)0.125s (string)12652.524s]
str=[(string)str val]
bools=[(bool)true (bool)false]
map=[(map[int]float64)map[1:1 2:0.5 3:0.3333333333333333]]
err=[(*errors.errorString)some error]
int=[(int)123]
uint64=[(string)123]
int64=[(string)123]
float32=[(float32)0.33333334]
float64=[(float64)0.3333333333333333]
time=[(string)1970-01-01T00:00:00Z]
base64=[(string)dmFsYXNyZGlqYXNkdThqYXNpZGphc2Q=]

func Array added in v0.4.0

func Array[E Event, P Parent[E]](p P) (arr *ArrayBuilder[E, P])

Array starts building a new array, as a field of a given Context, Builder or ArrayBuilder.

In Go, generic methods are not allowed to introduce cyclic dependencies on generic types, and cannot introduce further generic types.

Example (NestedArrays)
package main

import (
	"os"
)

var (
	// compile time assertions

	_ Parent[Event]         = (*Context[Event])(nil)
	_ Parent[Event]         = (*Builder[Event])(nil)
	_ Parent[Event]         = (*ArrayBuilder[Event, *Builder[Event]])(nil)
	_ Parent[Event]         = (*ArrayBuilder[Event, *ArrayBuilder[Event, *Builder[Event]]])(nil)
	_ arrayBuilderInterface = (*ArrayBuilder[Event, *Builder[Event]])(nil)
)

func main() {
	// note: outputs one field per line
	type E = *mockSimpleEvent
	var logger *Logger[E] = newSimpleLogger(os.Stdout, true)

	subLogger := Array[E](Array[E](Array[E](Array[E](Array[E](logger.Clone()).Field(1).Field(true)).Field(2).Field(false).Add()).Field(3)).Field(4)).
		Field(5).
		Add().
		Add().
		Add().
		As(`arr_1`).
		Field(`a`, `A`).
		Logger()

	Array[E](Array[E](Array[E](Array[E](Array[E](subLogger.Notice()).Field(1).Field(true)).Field(2).Field(false).Add()).Field(3)).Field(4)).
		Field(5).
		Add().
		Add().
		Add().
		As(`arr_2`).
		Field(`b`, `B`).
		Log(`msg 1`)

}
Output:

[notice]
arr_1=[1 true [2 false] [3 [4 [5]]]]
a=A
arr_2=[1 true [2 false] [3 [4 [5]]]]
b=B
msg=msg 1

func (*ArrayBuilder[E, P]) Add added in v0.4.0

func (x *ArrayBuilder[E, P]) Add() (p P)

Add is an alias for ArrayBuilder.As(""), and is provided for convenience, to improve clarity when adding an array to an array (a case where the key must be an empty string).

WARNING: References to the receiver must not be retained.

func (*ArrayBuilder[E, P]) Any added in v0.4.0

func (x *ArrayBuilder[E, P]) Any(val any) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Array added in v0.4.0

func (x *ArrayBuilder[E, P]) Array() *ArrayBuilder[E, P]

Array attempts to initialize a sub-array, which will succeed only if the parent is Chain, otherwise performing Logger.DPanic (returning nil if in a production configuration).

func (*ArrayBuilder[E, P]) As added in v0.4.0

func (x *ArrayBuilder[E, P]) As(key string) (p P)

As writes the array to the parent, using the provided key (if relevant), and returns the parent.

While you may use this to add an array to an array, providing a non-empty key with an array as a parent will result in a Logger.DPanic. In such cases, prefer ArrayBuilder.Add.

WARNING: References to the receiver must not be retained.

func (*ArrayBuilder[E, P]) Base64 added in v0.4.0

func (x *ArrayBuilder[E, P]) Base64(b []byte, enc *base64.Encoding) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Bool added in v0.4.0

func (x *ArrayBuilder[E, P]) Bool(val bool) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Call added in v0.4.0

func (x *ArrayBuilder[E, P]) Call(fn func(b *ArrayBuilder[E, P])) *ArrayBuilder[E, P]

Call is provided as a convenience, to facilitate code which uses the receiver explicitly, without breaking out of the fluent-style API. The provided fn will not be called if not ArrayBuilder.Enabled.

func (*ArrayBuilder[E, P]) Dur added in v0.4.0

func (x *ArrayBuilder[E, P]) Dur(val time.Duration) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Enabled added in v0.4.0

func (x *ArrayBuilder[E, P]) Enabled() bool

Enabled returns whether the parent is enabled.

func (*ArrayBuilder[E, P]) Err added in v0.4.0

func (x *ArrayBuilder[E, P]) Err(val error) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Field added in v0.4.0

func (x *ArrayBuilder[E, P]) Field(val any) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Float32 added in v0.4.0

func (x *ArrayBuilder[E, P]) Float32(val float32) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Float64 added in v0.4.0

func (x *ArrayBuilder[E, P]) Float64(val float64) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Int added in v0.4.0

func (x *ArrayBuilder[E, P]) Int(val int) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Int64 added in v0.4.0

func (x *ArrayBuilder[E, P]) Int64(val int64) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Interface added in v0.4.0

func (x *ArrayBuilder[E, P]) Interface(val any) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Object added in v0.5.0

func (x *ArrayBuilder[E, P]) Object() *ObjectBuilder[E, P]

Object attempts to initialize a sub-object, which will succeed only if the receiver is Chain, otherwise performing Logger.DPanic (returning nil if in a production configuration).

func (*ArrayBuilder[E, P]) Root added in v0.6.0

func (x *ArrayBuilder[E, P]) Root() *Logger[E]

Root returns the root Logger for this instance.

func (*ArrayBuilder[E, P]) Str added in v0.4.0

func (x *ArrayBuilder[E, P]) Str(val string) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Time added in v0.4.0

func (x *ArrayBuilder[E, P]) Time(val time.Time) *ArrayBuilder[E, P]

func (*ArrayBuilder[E, P]) Uint64 added in v0.4.0

func (x *ArrayBuilder[E, P]) Uint64(val uint64) *ArrayBuilder[E, P]

type Builder

type Builder[E Event] struct {
	Event E
	// contains filtered or unexported fields
}

Builder is used to build a log event, see Logger.Build, Logger.Info, etc.

All methods are safe to call on a nil receiver.

See also Context, which implements a common (sub)set of methods, for building structured log events, including Field ("smarter" than Interface), Interface (Event.AddField pass-through), and strongly-typed implementations such as Err and Str, that utilize the other Event.Add* methods (if implemented), with well-defined fallback behavior.

Example (NestedObjectsAndArrays)
type E = *mockSimpleEvent
var logger *Logger[E] = mockL.New(
	mockL.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
	mockL.WithWriter(&mockSimpleWriter{Writer: os.Stdout, MultiLine: true, JSON: true}),
	mockL.WithDPanicLevel(LevelEmergency),
)

logger.Notice().
	Object().
	Field(`a`, 1).
	Field(`b`, true).
	Array().
	Field(2).
	Object().
	Field(`c`, false).
	Add().
	As(`d`).
	CurObject().
	Field(`D`, 3).
	Object().
	Field(`aa1`, 1).
	Array().
	Array().Add().
	Array().Add().
	CurArray().
	Field(`aaa1`).
	As(`aaa`).
	CurObject().
	Field(`aa2`, 2).
	As(`aa`).
	As(`e`).
	Array().
	Field(5).
	Object().
	Field(`f`, 4).
	Add().
	Object().
	Field(`g`, 6).
	Add().
	As(`h`).
	End().
	Field(`j`, `J`).
	Log(`msg 1`)
Output:

[notice]
e={"D":3,"a":1,"aa":{"aa1":1,"aa2":2,"aaa":[[],[],"aaa1"]},"b":true,"d":[2,{"c":false}]}
h=[5,{"f":4},{"g":6}]
j="J"
msg="msg 1"

func (*Builder[E]) Any

func (x *Builder[E]) Any(key string, val any) *Builder[E]

Any is an alias for Builder.Interface.

func (*Builder[E]) Array added in v0.4.0

func (x *Builder[E]) Array() *ArrayBuilder[E, *Chain[E, *Builder[E]]]
Example (NestedArrays)
// note: outputs one field per line
type E = *mockSimpleEvent
var logger *Logger[E] = newSimpleLogger(os.Stdout, true)

logger.Notice().
	Array().
	Field(1).
	Field(true).
	Array().
	Field(2).
	Field(false).
	Add().
	Array().
	Field(3).
	Array().
	Field(4).
	Array().
	Field(5).
	Add().
	Add().
	Add().
	As(`arr`).
	End().
	Field(`b`, `B`).
	Log(`msg 1`)
Output:

[notice]
arr=[1 true [2 false] [3 [4 [5]]]]
b=B
msg=msg 1

func (*Builder[E]) Base64

func (x *Builder[E]) Base64(key string, b []byte, enc *base64.Encoding) *Builder[E]

Base64 adds a []byte as a structured log field, using [Event.AddBase64Bytes] if available, otherwise falling back to directly encoding the []byte as a base64 string. The fallback behavior is intended to be the core behavior, with the [Event.AddBase64Bytes] method being an optimization.

If enc is nil or base64.StdEncoding, the behavior is the same as the JSON encoding of Protobuf's bytes scalar. See also [https://protobuf.dev/programming-guides/proto3/#json].

func (*Builder[E]) Bool added in v0.3.0

func (x *Builder[E]) Bool(key string, val bool) *Builder[E]

Bool adds a bool as a structured log field, using Event.AddBool if available, otherwise falling back to Event.AddField.

func (*Builder[E]) Call

func (x *Builder[E]) Call(fn func(b *Builder[E])) *Builder[E]

Call is provided as a convenience, to facilitate code which uses the receiver explicitly, without breaking out of the fluent-style API. The provided fn will not be called if not Builder.Enabled.

Example use cases include access of the underlying Event implementation (to utilize functionality not mapped by logiface), or to skip building / formatting certain fields, based on if `b.Event.Level().Enabled()`.

func (*Builder[E]) Dur

func (x *Builder[E]) Dur(key string, d time.Duration) *Builder[E]

Dur adds a time.Duration as a structured log field, using Event.AddDuration if available, otherwise falling back to formatting the time.Duration as a string, formatted as a decimal in seconds (with unit), using the same semantics as the JSON encoding of Protobuf's "well known type", google.protobuf.Duration. In this fallback case, the behavior of Builder.Str is used, to add the field.

See also [https://github.com/protocolbuffers/protobuf/blob/4f6ef7e4d88a74dfcd82b36ef46844b22b9e54b1/src/google/protobuf/duration.proto].

func (*Builder[E]) Enabled

func (x *Builder[E]) Enabled() bool

Enabled indicates that this Builder was initialized by a Logger, using a writable Level, given the logger's configuration.

func (*Builder[E]) Err

func (x *Builder[E]) Err(err error) *Builder[E]

Err adds an error as a structured log field, the key for which will either be determined by the Event.AddError method, or will be "err" if not implemented.

func (*Builder[E]) Field

func (x *Builder[E]) Field(key string, val any) *Builder[E]

Field adds a field to the log event, making an effort to choose the most appropriate handler for the value.

WARNING: The behavior of this method may change without notice, to facilitate the addition of new field types.

Use the Interface method if you want a direct pass-through to the Event.AddField implementation.

func (*Builder[E]) Float32

func (x *Builder[E]) Float32(key string, val float32) *Builder[E]

Float32 adds a float32 as a structured log field, using Event.AddFloat32 if available, otherwise falling back to Event.AddField.

func (*Builder[E]) Float64 added in v0.3.0

func (x *Builder[E]) Float64(key string, val float64) *Builder[E]

Float64 adds a float64 as a structured log field, using Event.AddFloat64 if available, otherwise falling back to Event.AddField.

func (*Builder[E]) Int

func (x *Builder[E]) Int(key string, val int) *Builder[E]

Int adds an int as a structured log field, using Event.AddInt if available, otherwise falling back to Event.AddField.

func (*Builder[E]) Int64 added in v0.3.0

func (x *Builder[E]) Int64(key string, val int64) *Builder[E]

Int64 adds an int64 as a structured log field, using Event.AddInt64 if available, otherwise falling back to encoding val as a decimal string, in the same manner as Protobuf's JSON encoding.

For the fallback, the behavior of Builder.Str is used, to add the field.

func (*Builder[E]) Interface

func (x *Builder[E]) Interface(key string, val any) *Builder[E]

Interface adds a structured log field, which will pass through to Event.AddField.

func (*Builder[E]) Log

func (x *Builder[E]) Log(msg string)

Log logs an event, with the given message, using the provided level and modifier, if the relevant conditions are met (e.g. configured log level).

The field for the message will either be determined by the implementation, if Event.AddMessage is implemented, or the default field name "msg" will be used.

This method calls Builder.Release. This method is not implemented by Context.

func (*Builder[E]) LogFunc

func (x *Builder[E]) LogFunc(fn func() string)

LogFunc logs an event, with the message returned by the given function, using the provided level and modifier, if the relevant conditions are met (e.g. configured log level).

The field for the message will either be determined by the implementation, if Event.AddMessage is implemented, or the default field name "msg" will be used.

Note that the function will not be called if, for example, the given log level is not enabled.

This method calls Builder.Release. This method is not implemented by Context.

func (*Builder[E]) Logf

func (x *Builder[E]) Logf(format string, args ...any)

Logf logs an event, with the given message, using the provided level and modifier, if the relevant conditions are met (e.g. configured log level).

The field for the message will either be determined by the implementation, if Event.AddMessage is implemented, or the default field name "msg" will be used.

This method calls Builder.Release. This method is not implemented by Context.

func (*Builder[E]) Modifier added in v0.6.0

func (x *Builder[E]) Modifier(val Modifier[E]) *Builder[E]

Modifier calls val.Modify, if the receiver is enabled, and val is non-nil. If the modifier returns ErrDisabled, the return value will be nil, and the receiver will be released. If the modifier returns any other non-nil error, Logger.DPanic will be called.

func (*Builder[E]) Object added in v0.5.0

func (x *Builder[E]) Object() *ObjectBuilder[E, *Chain[E, *Builder[E]]]
Example (NestedObjects)
type E = *mockSimpleEvent
var logger *Logger[E] = mockL.New(
	mockL.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
	mockL.WithWriter(&mockSimpleWriter{Writer: os.Stdout, MultiLine: true, JSON: true}),
)

logger.Notice().
	Object().
	Field(`a`, 1).
	Field(`b`, true).
	Object().
	Field(`c`, 2).
	Field(`d`, false).
	As(`e`).
	Object().
	Field(`f`, 3).
	Object().
	Field(`g`, 4).
	Object().
	Field(`h`, 5).
	As(`i`).
	As(`j`).
	As(`k`).
	As(`l`).
	End().
	Field(`m`, `B`).
	Log(`msg 1`)
Output:

[notice]
l={"a":1,"b":true,"e":{"c":2,"d":false},"k":{"f":3,"j":{"g":4,"i":{"h":5}}}}
m="B"
msg="msg 1"

func (*Builder[E]) Release added in v0.2.0

func (x *Builder[E]) Release()

Release returns the Builder to the pool, calling any user-defined EventReleaser to reset or release [Builder.Event] (e.g. if the concrete event implementation also uses a pool).

In most cases, it should not be necessary to call this directly. This method is exported to allow for more advanced use cases, such as when the Builder is used to build an event that is not logged, or when the Builder is used to build an event that is logged by a different logger implementation.

This method is called by other "terminal" methods, such as Builder.Log. This method is not implemented by Context.

func (*Builder[E]) Root added in v0.6.0

func (x *Builder[E]) Root() *Logger[E]

Root returns the root Logger for this instance.

func (*Builder[E]) Str

func (x *Builder[E]) Str(key string, val string) *Builder[E]

Str adds a string as a structured log field, using Event.AddString if available, otherwise falling back to Event.AddField.

func (*Builder[E]) Time

func (x *Builder[E]) Time(key string, t time.Time) *Builder[E]

Time adds a time.Time as a structured log field, using Event.AddTime if available, otherwise falling back to formatting the time.Time as a string in the RFC 3339 format, using the same semantics as the JSON encoding of Protobuf's "well known type", google.protobuf.Timestamp. In this fallback case, the behavior of Builder.Str is used, to add the field.

See also [https://github.com/protocolbuffers/protobuf/blob/4f6ef7e4d88a74dfcd82b36ef46844b22b9e54b1/src/google/protobuf/timestamp.proto].

func (*Builder[E]) Uint64 added in v0.3.0

func (x *Builder[E]) Uint64(key string, val uint64) *Builder[E]

Uint64 adds an uint64 as a structured log field, using Event.AddUint64 if available, otherwise falling back to encoding val as a decimal string, in the same manner as Protobuf's JSON encoding.

For the fallback, the behavior of Builder.Str is used, to add the field.

type Chain added in v0.4.0

type Chain[E Event, P comparable] refPoolItem

Chain wraps a Parent implementation in order to support nested data structures.

func (*Chain[E, P]) Add added in v0.4.0

func (x *Chain[E, P]) Add() *Chain[E, P]

func (*Chain[E, P]) Array added in v0.4.0

func (x *Chain[E, P]) Array() *ArrayBuilder[E, *Chain[E, P]]

func (*Chain[E, P]) As added in v0.4.0

func (x *Chain[E, P]) As(key string) *Chain[E, P]

func (*Chain[E, P]) CurArray added in v0.5.0

func (x *Chain[E, P]) CurArray() *ArrayBuilder[E, *Chain[E, P]]

CurArray returns the current array, calls Logger.DPanic if the current value is not an array, and returns nil if in a production configuration.

Allows adding fields on the same level as nested object(s) and/or array(s).

func (*Chain[E, P]) CurObject added in v0.5.0

func (x *Chain[E, P]) CurObject() *ObjectBuilder[E, *Chain[E, P]]

CurObject returns the current object, calls Logger.DPanic if the current value is not an array, and returns nil if in a production configuration.

Allows adding fields on the same level as nested object(s) and/or array(s).

func (*Chain[E, P]) Enabled added in v0.4.0

func (x *Chain[E, P]) Enabled() bool

func (*Chain[E, P]) End added in v0.4.0

func (x *Chain[E, P]) End() (p P)

End jumps out of chain, returning the parent, and returning the receiver to the pool.

func (*Chain[E, P]) Object added in v0.5.0

func (x *Chain[E, P]) Object() *ObjectBuilder[E, *Chain[E, P]]

func (*Chain[E, P]) Root added in v0.6.0

func (x *Chain[E, P]) Root() *Logger[E]

Root returns the root Logger for this instance.

type Context

type Context[E Event] struct {
	Modifiers ModifierSlice[E]
	// contains filtered or unexported fields
}

Context is used to build a sub-logger, see Logger.Clone.

All methods are safe to call on a nil receiver.

See also Builder, which implements a common (sub)set of methods, for building structured log events, including Field ("smarter" than Interface), Interface (Event.AddField pass-through), and strongly-typed implementations that utilize the other Event.Add* methods (if implemented), with well-defined fallback behavior.

Example (NestedObjectsAndArrays)
type E = *mockSimpleEvent
var logger *Logger[E] = mockL.New(
	mockL.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
	mockL.WithWriter(&mockSimpleWriter{Writer: os.Stdout, MultiLine: true, JSON: true}),
	mockL.WithDPanicLevel(LevelEmergency),
)

logger.Clone().
	Object().
	Field(`a`, 1).
	Field(`b`, true).
	Array().
	Field(2).
	Object().
	Field(`c`, false).
	Add().
	As(`d`).
	CurObject().
	Field(`D`, 3).
	Object().
	Field(`aa1`, 1).
	Array().
	Array().Add().
	Array().Add().
	CurArray().
	Field(`aaa1`).
	As(`aaa`).
	CurObject().
	Field(`aa2`, 2).
	As(`aa`).
	As(`e`).
	Array().
	Field(5).
	Object().
	Field(`f`, 4).
	Add().
	Object().
	Field(`g`, 6).
	Add().
	As(`h`).
	End().
	Field(`j`, `J`).
	Logger().
	Notice().
	Log(`msg 1`)
Output:

[notice]
e={"D":3,"a":1,"aa":{"aa1":1,"aa2":2,"aaa":[[],[],"aaa1"]},"b":true,"d":[2,{"c":false}]}
h=[5,{"f":4},{"g":6}]
j="J"
msg="msg 1"

func (*Context[E]) Any

func (x *Context[E]) Any(key string, val any) *Context[E]

Any is an alias for Context.Interface.

func (*Context[E]) Array added in v0.4.0

func (x *Context[E]) Array() *ArrayBuilder[E, *Chain[E, *Context[E]]]
Example (NestedArrays)
// note: outputs one field per line
type E = *mockSimpleEvent
var logger *Logger[E] = newSimpleLogger(os.Stdout, true)

logger.Clone().
	Array().
	Field(1).
	Field(true).
	Array().
	Field(2).
	Field(false).
	Add().
	Array().
	Field(3).
	Array().
	Field(4).
	Array().
	Field(5).
	Add().
	Add().
	Add().
	As(`arr`).
	End().
	Field(`b`, `B`).
	Logger().
	Notice().
	Log(`msg 1`)
Output:

[notice]
arr=[1 true [2 false] [3 [4 [5]]]]
b=B
msg=msg 1

func (*Context[E]) Base64

func (x *Context[E]) Base64(key string, b []byte, enc *base64.Encoding) *Context[E]

Base64 adds a []byte as a structured log field, using [Event.AddBase64Bytes] if available, otherwise falling back to directly encoding the []byte as a base64 string. The fallback behavior is intended to be the core behavior, with the [Event.AddBase64Bytes] method being an optimization.

If enc is nil or base64.StdEncoding, the behavior is the same as the JSON encoding of Protobuf's bytes scalar. See also [https://protobuf.dev/programming-guides/proto3/#json].

func (*Context[E]) Bool added in v0.3.0

func (x *Context[E]) Bool(key string, val bool) *Context[E]

Bool adds a bool as a structured log field, using Event.AddBool if available, otherwise falling back to Event.AddField.

func (*Context[E]) Call added in v0.4.0

func (x *Context[E]) Call(fn func(b *Context[E])) *Context[E]

Call is provided as a convenience, to facilitate code which uses the receiver explicitly, without breaking out of the fluent-style API. The provided fn will not be called if not Context.Enabled.

Example (ArrayField)
type E = *mockSimpleEvent
var logger *Logger[E] = newSimpleLogger(os.Stdout, false)

// while not a necessary part of the Array API, this pattern makes things easier to manage
subLogger := logger.Clone().
	Call(func(b *Context[E]) { Array[E](b).Field(1).Field(2).Field(3).As(`arr_field`) }).
	Str(`str_field`, `str_value`).
	Logger()

subLogger.Info().Log(`log msg`)
Output:

[info] arr_field=[1 2 3] str_field=str_value msg=log msg

func (*Context[E]) Dur

func (x *Context[E]) Dur(key string, d time.Duration) *Context[E]

Dur adds a time.Duration as a structured log field, using Event.AddDuration if available, otherwise falling back to formatting the time.Duration as a string, formatted as a decimal in seconds (with unit), using the same semantics as the JSON encoding of Protobuf's "well known type", google.protobuf.Duration. In this fallback case, the behavior of Context.Str is used, to add the field.

See also [https://github.com/protocolbuffers/protobuf/blob/4f6ef7e4d88a74dfcd82b36ef46844b22b9e54b1/src/google/protobuf/duration.proto].

func (*Context[E]) Enabled

func (x *Context[E]) Enabled() bool

Enabled indicates that this Context was initialized from a writable Logger, via Logger.Clone.

func (*Context[E]) Err

func (x *Context[E]) Err(err error) *Context[E]

Err adds an error as a structured log field, the key for which will either be determined by the Event.AddError method, or will be "err" if not implemented.

func (*Context[E]) Field

func (x *Context[E]) Field(key string, val any) *Context[E]

Field adds a field to the log context, making an effort to choose the most appropriate handler for the value.

WARNING: The behavior of this method may change without notice, to facilitate the addition of new field types.

Use the Interface method if you want a direct pass-through to the Event.AddField implementation.

func (*Context[E]) Float32

func (x *Context[E]) Float32(key string, val float32) *Context[E]

Float32 adds a float32 as a structured log field, using Event.AddFloat32 if available, otherwise falling back to Event.AddField.

func (*Context[E]) Float64 added in v0.3.0

func (x *Context[E]) Float64(key string, val float64) *Context[E]

Float64 adds a float64 as a structured log field, using Event.AddFloat64 if available, otherwise falling back to Event.AddField.

func (*Context[E]) Int

func (x *Context[E]) Int(key string, val int) *Context[E]

Int adds an int as a structured log field, using Event.AddInt if available, otherwise falling back to Event.AddField.

func (*Context[E]) Int64 added in v0.3.0

func (x *Context[E]) Int64(key string, val int64) *Context[E]

Int64 adds an int64 as a structured log field, using Event.AddInt64 if available, otherwise falling back to encoding val as a decimal string, in the same manner as Protobuf's JSON encoding.

For the fallback, the behavior of Context.Str is used, to add the field.

func (*Context[E]) Interface

func (x *Context[E]) Interface(key string, val any) *Context[E]

Interface adds a structured log field, which will pass through to Event.AddField.

func (*Context[E]) Logger

func (x *Context[E]) Logger() *Logger[E]

Logger returns the underlying (sub)logger, or nil.

Note that the returned logger will apply all parent modifiers, including [Context.Modifiers]. This method is intended to be used to get the actual sub-logger, after building the context that sub-logger is to apply.

This method is not implemented by Builder.

func (*Context[E]) Modifier added in v0.6.0

func (x *Context[E]) Modifier(val Modifier[E]) *Context[E]

Modifier appends val to the receiver, if the receiver is enabled, and val is non-nil.

func (*Context[E]) Object added in v0.5.0

func (x *Context[E]) Object() *ObjectBuilder[E, *Chain[E, *Context[E]]]
Example (NestedObjects)
type E = *mockSimpleEvent
var logger *Logger[E] = mockL.New(
	mockL.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
	mockL.WithWriter(&mockSimpleWriter{Writer: os.Stdout, MultiLine: true, JSON: true}),
)

logger.Clone().
	Object().
	Field(`a`, 1).
	Field(`b`, true).
	Object().
	Field(`c`, 2).
	Field(`d`, false).
	As(`e`).
	Object().
	Field(`f`, 3).
	Object().
	Field(`g`, 4).
	Object().
	Field(`h`, 5).
	As(`i`).
	As(`j`).
	As(`k`).
	As(`l`).
	End().
	Field(`m`, `B`).
	Logger().
	Notice().
	Log(`msg 1`)
Output:

[notice]
l={"a":1,"b":true,"e":{"c":2,"d":false},"k":{"f":3,"j":{"g":4,"i":{"h":5}}}}
m="B"
msg="msg 1"

func (*Context[E]) Root added in v0.6.0

func (x *Context[E]) Root() *Logger[E]

Root returns the root Logger for this instance.

func (*Context[E]) Str

func (x *Context[E]) Str(key string, val string) *Context[E]

Str adds a string as a structured log field, using Event.AddString if available, otherwise falling back to Event.AddField.

func (*Context[E]) Time

func (x *Context[E]) Time(key string, t time.Time) *Context[E]

Time adds a time.Time as a structured log field, using Event.AddTime if available, otherwise falling back to formatting the time.Time as a string in the RFC 3339 format, using the same semantics as the JSON encoding of Protobuf's "well known type", google.protobuf.Timestamp. In this fallback case, the behavior of Context.Str is used, to add the field.

See also [https://github.com/protocolbuffers/protobuf/blob/4f6ef7e4d88a74dfcd82b36ef46844b22b9e54b1/src/google/protobuf/timestamp.proto].

func (*Context[E]) Uint64 added in v0.3.0

func (x *Context[E]) Uint64(key string, val uint64) *Context[E]

Uint64 adds an uint64 as a structured log field, using Event.AddUint64 if available, otherwise falling back to encoding val as a decimal string, in the same manner as Protobuf's JSON encoding.

For the fallback, the behavior of Context.Str is used, to add the field.

type Event

type Event interface {

	// Level returns the level of the event.
	// It must be the same as originally provided to the factory.
	Level() Level
	// AddField adds a field to the event, for structured logging.
	// How fields are handled is implementation specific.
	AddField(key string, val any)

	// AddMessage sets the log message for the event, returning false if unimplemented.
	// The field or output structure of the log message is implementation specific.
	AddMessage(msg string) bool
	// AddError adds an error to the event, returning false if unimplemented.
	// The field or output structure of the log message is implementation specific.
	AddError(err error) bool
	// AddString adds a field of type string. It's an optional optimisation.
	AddString(key string, val string) bool
	// AddInt adds a field of type int. It's an optional optimisation.
	AddInt(key string, val int) bool
	// AddFloat32 adds a field of type float32. It's an optional optimisation.
	AddFloat32(key string, val float32) bool
	// AddTime adds a field of type time.Time. It's an optional optimisation.
	AddTime(key string, val time.Time) bool
	// AddDuration adds a field of type time.Duration. It's an optional optimisation.
	AddDuration(key string, val time.Duration) bool
	// AddBase64Bytes adds bytes as a field, to be base64 encoded.
	// The enc param will always be non-nil, and is the encoding to use.
	// This abstraction is provided to allow implementations to use the
	// most appropriate method, of the enc param.
	// It's an optional optimisation.
	AddBase64Bytes(key string, val []byte, enc *base64.Encoding) bool
	// AddBool adds a field of type bool. It's an optional optimisation.
	AddBool(key string, val bool) bool
	// AddFloat64 adds a field of type float64. It's an optional optimisation.
	AddFloat64(key string, val float64) bool
	// AddInt64 adds a field of type int64. It's an optional optimisation.
	AddInt64(key string, val int64) bool
	// AddUint64 adds a field of type uint64. It's an optional optimisation.
	AddUint64(key string, val uint64) bool
	// contains filtered or unexported methods
}

Event models the integration with the logging framework.

The methods Level and AddField are mandatory.

Implementations must have a zero value that doesn't panic when calling Level, in which instance it must return LevelDisabled.

All implementations must embed UnimplementedEvent, as it provides support for optional methods (and facilitates additional optional methods being added, without breaking changes).

Adding a new log field type

In general, types of log fields are added via the implementation of new methods, which should be present in all of Builder, Context, and Event, though the Event method will differ.

The method name and arguments, for Builder and Context, are typically styled after the equivalent provided by zerolog, though they need not be. The arguments for Event are typically identical, returning a bool (to indicate support), with the method name being somewhat arbitrary, but ideally descriptive and consistent, e.g. Add<full type name>. The Event interface isn't used directly, by end users, making brevity unimportant.

These are common development tasks, when a new field type is added:

  1. Add the new field type method to the Event interface (e.g. AddDuration)
  2. Add the new field type method to the UnimplementedEvent struct (return false)
  3. Add the calling/fallback behavior as a new unexported method of the internal modifierMethods struct (e.g. dur)
  4. Update the (internal) modifierMethods.Field method, with type case(s) using 3., for the new field type
  5. Add a new (internal) method to the modifierMethods struct, using 3., named per Builder and Context (e.g. Dur)
  6. Add to each of Builder and Context a method named the same as and using 5. (e.g. Dur)
  7. Add the Event method to mockComplexEvent in mock_test.go
  8. Run make in the root of the git repository, fix any issues
  9. Add appropriate Field and specific method calls (e.g. Dur) to fluentCallerTemplate in mock_test.go (note: update the T generic interface)
  10. Fix all test cases that fail
  11. Update the testsuite module to include the new field type (e.g. throw it on eventTemplate1 in templates.go)
  12. Run make in the root of the git repository, everything should still pass
  13. Implement new field type in all relevant implementation modules (e.g. logiface/zerolog)
  14. Fix any issues with the test harness implementations, which may require adding additional functionality to logiface/testsuite, see also normalizeEvent
  15. Consider adding or updating benchmarks, e.g. the comparison (vs direct use) benchmarks in logiface/zerolog
  16. Add the field to fieldBuilderObjectInterface in method_test.go
  17. Add the field to fieldBuilderArrayInterface, unless not applicable
  18. Implement necessary methods and make necessary changes to add the methods to the peripheral implementations, including ObjectBuilder, ArrayBuilder, and JSONSupport

type EventFactory

type EventFactory[E Event] interface {
	NewEvent(level Level) E
}

EventFactory initializes a new Event, for Logger instances.

As Builder instances are pooled, implementations may need to implement EventReleaser as a way to clear references to objects that should be garbage collected.

Note that it may be desirable to use a pool of events, to reduce unnecessary allocations. In this case, EventReleaser should be implemented, to return the event to the pool.

type EventFactoryFunc

type EventFactoryFunc[E Event] func(level Level) E

EventFactoryFunc implements EventFactory.

func NewEventFactoryFunc

func NewEventFactoryFunc[E Event](f func(level Level) E) EventFactoryFunc[E]

NewEventFactoryFunc is an alias provided as a convenience, to make it easier to cast a function to an EventFactoryFunc.

It's equivalent to EventFactoryFunc[E](f), which is more verbose, as it cannot infer the type.

See also LoggerFactory.NewEventFactoryFunc.

func (EventFactoryFunc[E]) NewEvent

func (x EventFactoryFunc[E]) NewEvent(level Level) E

type EventReleaser

type EventReleaser[E Event] interface {
	ReleaseEvent(event E)
}

EventReleaser is an optional implementation that may be used to either "reset" or "release" concrete implementations of Event.

Use this interface to, for example, clear references to which should be garbage collected, or return references to pool(s).

type EventReleaserFunc

type EventReleaserFunc[E Event] func(event E)

EventReleaserFunc implements EventReleaser.

func NewEventReleaserFunc

func NewEventReleaserFunc[E Event](f func(event E)) EventReleaserFunc[E]

NewEventReleaserFunc is an alias provided as a convenience, to make it easier to cast a function to an EventReleaserFunc.

It's equivalent to EventReleaserFunc[E](f), which is more verbose, as it cannot infer the type.

See also LoggerFactory.NewEventFactoryFunc.

func (EventReleaserFunc[E]) ReleaseEvent

func (x EventReleaserFunc[E]) ReleaseEvent(event E)

type JSONSupport added in v0.5.0

type JSONSupport[E Event, O any, A any] interface {
	NewObject() O
	AddObject(evt E, key string, obj O)
	SetField(obj O, key string, val any) O
	CanSetObject() bool
	SetObject(obj O, key string, val O) O
	CanSetArray() bool
	SetArray(obj O, key string, val A) O
	CanSetString() bool
	SetString(obj O, key string, val string) O
	CanSetBool() bool
	SetBool(obj O, key string, val bool) O
	CanSetBase64Bytes() bool
	SetBase64Bytes(obj O, key string, b []byte, enc *base64.Encoding) O
	CanSetDuration() bool
	SetDuration(obj O, key string, d time.Duration) O
	CanSetError() bool
	SetError(obj O, err error) O
	CanSetInt() bool
	SetInt(obj O, key string, val int) O
	CanSetFloat32() bool
	SetFloat32(obj O, key string, val float32) O
	CanSetTime() bool
	SetTime(obj O, key string, t time.Time) O
	CanSetFloat64() bool
	SetFloat64(obj O, key string, val float64) O
	CanSetInt64() bool
	SetInt64(obj O, key string, val int64) O
	CanSetUint64() bool
	SetUint64(obj O, key string, val uint64) O

	NewArray() A
	AddArray(evt E, key string, arr A)
	AppendField(arr A, val any) A
	CanAppendObject() bool
	AppendObject(arr A, val O) A
	CanAppendArray() bool
	AppendArray(arr A, val A) A
	CanAppendString() bool
	AppendString(arr A, val string) A
	CanAppendBool() bool
	AppendBool(arr A, val bool) A
	CanAppendBase64Bytes() bool
	AppendBase64Bytes(arr A, b []byte, enc *base64.Encoding) A
	CanAppendDuration() bool
	AppendDuration(arr A, d time.Duration) A
	CanAppendError() bool
	AppendError(arr A, err error) A
	CanAppendInt() bool
	AppendInt(arr A, val int) A
	CanAppendFloat32() bool
	AppendFloat32(arr A, val float32) A
	CanAppendTime() bool
	AppendTime(arr A, t time.Time) A
	CanAppendFloat64() bool
	AppendFloat64(arr A, val float64) A
	CanAppendInt64() bool
	AppendInt64(arr A, val int64) A
	CanAppendUint64() bool
	AppendUint64(arr A, val uint64) A
	// contains filtered or unexported methods
}

type Level

type Level int8

Level models the severity level of a log message.

Valid Level values include all the syslog log levels, as defined in RFC 5424, with the addition of a "trace" level (LevelTrace), which is expected to use abnormal output mechanisms (e.g. a separate log file). Negative values are treated as disabled, see also LevelDisabled.

Also supported are "custom levels" which are positive integer values, from 9 to 127, inclusive. Custom levels are handled differently than regular levels, in that they are not affected by the log level set on the Logger.

Syslog severity levels

Value	Severity	Keyword	Deprecated keywords	Description	Condition
0	Emergency	emerg	panic[9]	System is unusable	A panic condition.[10]
1	Alert	alert		Action must be taken immediately	A condition that should be corrected immediately, such as a corrupted system database.[10]
2	Critical	crit		Critical conditions	Hard device errors.[10]
3	Error	err	error[9]	Error conditions
4	Warning	warning	warn[9]	Warning conditions
5	Notice	notice		Normal but significant conditions	Conditions that are not error conditions, but that may require special handling.[10]
6	Informational	info		Informational messages	Confirmation that the program is working as expected.
7	Debug	debug		Debug-level messages	Messages that contain information normally of use only when debugging a program.[10]

[9] https://linux.die.net/man/5/syslog.conf
[10] https://pubs.opengroup.org/onlinepubs/009695399/functions/syslog.html

Mapping levels to logger implementations

Regarding mapping, to log levels in other systems, the recommended approach is:

  • LevelEmergency => PANIC
  • LevelAlert => FATAL
  • LevelCritical => ERROR
  • LevelError => ERROR
  • LevelWarning => WARN
  • LevelNotice => WARN
  • LevelInformational => INFO
  • LevelDebug => DEBUG
  • LevelTrace => TRACE (or disabled)
const (
	// LevelDisabled is a special value that disables logging.
	LevelDisabled Level = iota - 1

	// LevelEmergency is a syslog level.
	// Indicates that the system is unusable, a panic condition.
	//
	// This log level should be used with caution, as it tends to be mapped to
	// "panic", which, in at least several logger implementations, will call
	// panic(). See also the recommended mappings, documented under Level.
	//
	// See also [Logger.Panic].
	LevelEmergency

	// LevelAlert is a syslog level.
	// Indicates that action must be taken immediately, or a condition that
	// should be corrected immediately, such as a corrupted system database.
	//
	// This log level should be used with caution, as it tends to be mapped to
	// "fatal", which, in at least several logger implementations, will call
	// os.Exit(1). See also the recommended mappings, documented under Level.
	//
	// See also [Logger.Fatal].
	LevelAlert

	// LevelCritical is a syslog level.
	// Indicates critical conditions, such as hard device errors.
	LevelCritical

	// LevelError is a syslog level.
	// Indicates error conditions.
	LevelError

	// LevelWarning is a syslog level.
	// Indicates warning conditions.
	LevelWarning

	// LevelNotice is a syslog level.
	// Indicates normal but significant conditions, which may require special
	// handling or attention, such as startup messages.
	LevelNotice

	// LevelInformational is a syslog level.
	// Indicates informational messages, which confirm that the program is
	// working as expected.
	LevelInformational

	// LevelDebug is a syslog level.
	// Indicates a message contains information normally of use only when
	// debugging a program.
	LevelDebug

	// LevelTrace is not a syslog level, and is intended to be used only when
	// running using abnormal output mechanisms (e.g. a dedicated log file, as
	// part of a debugging session).
	// It is expected to be more verbose than LevelDebug, but serves a similar
	// purpose.
	LevelTrace
)

func (Level) Custom

func (x Level) Custom() bool

Custom returns true if the Level is a custom level (greater than LevelTrace).

Example
p := func(level Level) {
	fmt.Printf("%q (%d): %v\n", level, level, level.Custom())
}
p(math.MinInt8)
p(-2)
p(LevelDisabled)
p(LevelEmergency)
p(LevelAlert)
p(LevelCritical)
p(LevelError)
p(LevelWarning)
p(LevelNotice)
p(LevelInformational)
p(LevelDebug)
p(LevelTrace)
p(9)
p(math.MaxInt8)
Output:

"-128" (-128): false
"-2" (-2): false
"disabled" (-1): false
"emerg" (0): false
"alert" (1): false
"crit" (2): false
"err" (3): false
"warning" (4): false
"notice" (5): false
"info" (6): false
"debug" (7): false
"trace" (8): false
"9" (9): true
"127" (127): true

func (Level) Enabled

func (x Level) Enabled() bool

Enabled returns true if the Level is enabled (greater than or equal to 0).

Example
p := func(level Level) {
	fmt.Printf("%q (%d): %v\n", level, level, level.Enabled())
}
p(math.MinInt8)
p(-2)
p(LevelDisabled)
p(LevelEmergency)
p(LevelAlert)
p(LevelCritical)
p(LevelError)
p(LevelWarning)
p(LevelNotice)
p(LevelInformational)
p(LevelDebug)
p(LevelTrace)
p(9)
p(math.MaxInt8)
Output:

"-128" (-128): false
"-2" (-2): false
"disabled" (-1): false
"emerg" (0): true
"alert" (1): true
"crit" (2): true
"err" (3): true
"warning" (4): true
"notice" (5): true
"info" (6): true
"debug" (7): true
"trace" (8): true
"9" (9): true
"127" (127): true

func (Level) String

func (x Level) String() string

String implements fmt.Stringer, note that it uses the short keyword (for the actual syslog levels).

func (Level) Syslog

func (x Level) Syslog() bool

Syslog returns true if the Level is a syslog level.

Example
p := func(level Level) {
	fmt.Printf("%q (%d): %v\n", level, level, level.Syslog())
}
p(math.MinInt8)
p(-2)
p(LevelDisabled)
p(LevelEmergency)
p(LevelAlert)
p(LevelCritical)
p(LevelError)
p(LevelWarning)
p(LevelNotice)
p(LevelInformational)
p(LevelDebug)
p(LevelTrace)
p(9)
p(math.MaxInt8)
Output:

"-128" (-128): false
"-2" (-2): false
"disabled" (-1): false
"emerg" (0): true
"alert" (1): true
"crit" (2): true
"err" (3): true
"warning" (4): true
"notice" (5): true
"info" (6): true
"debug" (7): true
"trace" (8): false
"9" (9): false
"127" (127): false

type Logger

type Logger[E Event] struct {
	// contains filtered or unexported fields
}

Logger is the core logger implementation, and constitutes the core functionality, provided by this package.

func New

func New[E Event](options ...Option[E]) (logger *Logger[E])

New constructs a new Logger instance.

Configure the logger using either the With* prefixed functions (or methods of LoggerFactory, e.g. accessible via the L global), or via composite options, implemented in external packages, e.g. logger integrations.

See also LoggerFactory.New and L (an instance of LoggerFactory[Event]{}).

func (*Logger[E]) Alert

func (x *Logger[E]) Alert() *Builder[E]

Alert is an alias for Logger.Build(LevelAlert).

func (*Logger[E]) Build

func (x *Logger[E]) Build(level Level) *Builder[E]

Build returns a new Builder for the given level, note that it may return nil (e.g. if the level is disabled).

See also the methods Info, Debug, etc.

func (*Logger[E]) Clone

func (x *Logger[E]) Clone() *Context[E]

Clone returns a new Context, which is a mechanism to configure a sub-logger, which will be available via Context.Logger, note that it may return nil.

func (*Logger[E]) Crit

func (x *Logger[E]) Crit() *Builder[E]

Crit is an alias for Logger.Build(LevelCritical).

func (*Logger[E]) DPanic added in v0.4.0

func (x *Logger[E]) DPanic() *Builder[E]

DPanic is a virtual log level, and stands for "panic in development". It is intended to be used for errors that "shouldn't happen", but, if they occur in production, shouldn't (necessarily) trigger an actual panic.

If configured with LevelEmergency, it will behave like Logger.Panic, otherwise it will behave like Logger.Build(dpanicLevel).

It's default level is LevelCritical, intended for production use. See also WithDPanicLevel.

This method was inspired by [zap](https://github.com/uber-go/zap/blob/85c4932ce3ea76b6babe3e0a3d79da10ef295b8d/FAQ.md#whats-dpanic).

Example
opts := mockL.WithOptions(
	mockL.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
	mockL.WithWriter(&mockSimpleWriter{Writer: os.Stdout}),
)

New(opts).DPanic().Log(`DPanic uses LevelCritical by default`)

func() {
	defer func() { fmt.Printf("recover: %v\n", recover()) }()
	New(opts, mockL.WithDPanicLevel(LevelEmergency)).DPanic().Log(`if set to LevelEmergency DPanic behaves per Panic`)
}()

func() {
	defer func() { fmt.Printf("recover: %v\n", recover()) }()
	fmt.Println(`like Panic, DPanic at LevelEmergency will pre-emptively panic if the logger is disabled`)
	New(opts, mockL.WithLevel(LevelDisabled), mockL.WithDPanicLevel(LevelEmergency)).DPanic()
}()

fmt.Println(`note that if the DPanic level is not LevelEmergency it is possible that neither log or panic will occur`)
logger := New(opts, mockL.WithLevel(LevelDisabled))
logger.DPanic().Log(`does nothing as the logger is disabled and the DPanic level is not LevelEmergency`)
logger = nil
logger.DPanic().Log(`does nothing for the same reasons as above`)
Output:

[crit] msg=DPanic uses LevelCritical by default
[emerg] msg=if set to LevelEmergency DPanic behaves per Panic
recover: if set to LevelEmergency DPanic behaves per Panic
like Panic, DPanic at LevelEmergency will pre-emptively panic if the logger is disabled
recover: logiface: panic requested but logger is disabled
note that if the DPanic level is not LevelEmergency it is possible that neither log or panic will occur

func (*Logger[E]) Debug

func (x *Logger[E]) Debug() *Builder[E]

Debug is an alias for Logger.Build(LevelDebug).

func (*Logger[E]) Emerg

func (x *Logger[E]) Emerg() *Builder[E]

Emerg is an alias for Logger.Build(LevelEmergency).

func (*Logger[E]) Enabled added in v0.6.0

func (x *Logger[E]) Enabled() bool

Enabled returns true if the logger can write.

func (*Logger[E]) Err

func (x *Logger[E]) Err() *Builder[E]

Err is an alias for Logger.Build(LevelError).

func (*Logger[E]) Fatal added in v0.4.0

func (x *Logger[E]) Fatal() (b *Builder[E])

Fatal constructs a Builder that behaves like Logger.Alert, with the additional behaviour that it will call os.Exit(1) after the event has been written.

The recommended behavior is to map LevelAlert to a "fatal level", and most log libraries seem to have their own implementation, so they may trigger the actual exit.

WARNING: An exit will occur immediately if that level is disabled.

See also OsExit.

Example
{
	old := OsExit
	defer func() { OsExit = old }()
}
OsExit = func(code int) {
	fmt.Printf("exited with code: %d\n", code)
}

l := newSimpleLogger(os.Stdout, false)

l.Fatal().Log(`will exit after logging`)

fmt.Println(`will pre-emptively exit if the logger or that log level is disabled`)
l = nil
if l.Fatal() != nil {
	panic(`strange...`)
}
Output:

[alert] msg=will exit after logging
exited with code: 1
will pre-emptively exit if the logger or that log level is disabled
exited with code: 1

func (*Logger[E]) Info

func (x *Logger[E]) Info() *Builder[E]

Info is an alias for Logger.Build(LevelInformational).

func (*Logger[E]) Level added in v0.3.0

func (x *Logger[E]) Level() Level

Level returns the logger's Level, note that it will be LevelDisabled if it isn't writeable, or if the provided level was any disabled value.

func (*Logger[E]) Log

func (x *Logger[E]) Log(level Level, modifier Modifier[E]) error

Log directly performs a Log operation, without the "fluent builder" pattern.

Example

An example of how to use the non-fluent Log method.

l := newSimpleLogger(os.Stdout, false).Logger()

if err := l.Log(LevelDisabled, nil); err != ErrDisabled {
	panic(err)
} else {
	fmt.Printf("disabled level wont log: %v\n", err)
}

// note: the method under test is intended for external log integrations
// (this isn't a real use case)
with := func(fields ...any) ModifierFunc[Event] {
	return func(e Event) error {
		if len(fields)%2 != 0 {
			return fmt.Errorf("invalid number of fields: %d", len(fields))
		}
		for i := 0; i < len(fields); i += 2 {
			e.AddField(fmt.Sprint(fields[i]), fields[i+1])
		}
		return nil
	}
}

fmt.Print(`single modifier provided in the call: `)
if err := l.Log(LevelNotice, with(
	`a`, `A`,
	`b`, `B`,
)); err != nil {
	panic(err)
}

fmt.Print(`cloned logger modifier + modifier in the call: `)
if err := l.Clone().Str(`a`, `A1`).Logger().Log(LevelNotice, with(`a`, `A2`)); err != nil {
	panic(err)
}

fmt.Print(`just cloned logger modifier: `)
if err := l.Clone().Str(`a`, `A1`).Logger().Log(LevelNotice, nil); err != nil {
	panic(err)
}

fmt.Print(`no logger modifier: `)
if err := l.Log(LevelNotice, nil); err != nil {
	panic(err)
}

fmt.Printf("modifier error: %v\n", l.Log(LevelNotice, with(`willerror`)))

fmt.Printf("internal modifier error guards provided modifier: %v\n", New(
	mockL.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
	mockL.WithWriter(&mockSimpleWriter{Writer: os.Stdout}),
	mockL.WithModifier(NewModifierFunc(func(e *mockSimpleEvent) error {
		return fmt.Errorf(`some internal modifier error`)
	})),
).Log(LevelNotice, ModifierFunc[*mockSimpleEvent](func(e *mockSimpleEvent) error {
	panic(`should not be called`)
})))
Output:

disabled level wont log: logger disabled
single modifier provided in the call: [notice] a=A b=B
cloned logger modifier + modifier in the call: [notice] a=A1 a=A2
just cloned logger modifier: [notice] a=A1
no logger modifier: [notice]
modifier error: invalid number of fields: 1
internal modifier error guards provided modifier: some internal modifier error

func (*Logger[E]) Logger

func (x *Logger[E]) Logger() (logger *Logger[Event])

Logger returns a new generified logger.

Use this for greater compatibility, but sacrificing ease of using the underlying library directly.

func (*Logger[E]) Notice

func (x *Logger[E]) Notice() *Builder[E]

Notice is an alias for Logger.Build(LevelNotice).

func (*Logger[E]) Panic added in v0.4.0

func (x *Logger[E]) Panic() (b *Builder[E])

Panic constructs a Builder that behaves like Logger.Emerg, with the additional behaviour that it will panic after the event has been written.

The recommended behavior is to map LevelEmergency to a "panic level", and most log libraries seem to have their own implementation, so they may trigger the actual panic.

WARNING: A panic will occur immediately if that level is disabled.

Example
opts := mockL.WithOptions(
	mockL.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
	mockL.WithWriter(&mockSimpleWriter{Writer: os.Stdout}),
)

func() {
	defer func() { fmt.Printf("recover: %v\n", recover()) }()
	New(opts).Panic().Log(`will panic after logging`)
}()

fmt.Println(`you should set the message though there is a default string that will be used if you don't`)
func() {
	defer func() { fmt.Printf("recover: %v\n", recover()) }()
	New(opts).Panic().Str(`some`, `data`).Log(``)
}()

func() {
	defer func() { fmt.Printf("recover: %v\n", recover()) }()
	fmt.Println(`will pre-emptively panic if the logger is disabled`)
	New(opts, mockL.WithLevel(LevelDisabled), mockL.WithDPanicLevel(LevelEmergency)).DPanic()
}()
Output:

[emerg] msg=will panic after logging
recover: will panic after logging
you should set the message though there is a default string that will be used if you don't
[emerg] some=data
recover: logiface: panic requested
will pre-emptively panic if the logger is disabled
recover: logiface: panic requested but logger is disabled

func (*Logger[E]) Root added in v0.4.0

func (x *Logger[E]) Root() *Logger[E]

Root returns the root Logger for this instance.

func (*Logger[E]) Trace

func (x *Logger[E]) Trace() *Builder[E]

Trace is an alias for Logger.Build(LevelTrace).

func (*Logger[E]) Warning

func (x *Logger[E]) Warning() *Builder[E]

Warning is an alias for Logger.Build(LevelWarning).

type LoggerFactory

type LoggerFactory[E Event] struct{}

LoggerFactory provides aliases for package functions including New, as well as the functions returning Option values. This allows the Event type to be omitted from all but one location.

See also L, an instance of LoggerFactory[Event]{}.

func (LoggerFactory[E]) LevelAlert

func (LoggerFactory[E]) LevelAlert() Level

LevelAlert returns LevelAlert, and is provided as a convenience for implementation packages, so end users don't have to import logiface.

func (LoggerFactory[E]) LevelCritical

func (LoggerFactory[E]) LevelCritical() Level

LevelCritical returns LevelCritical, and is provided as a convenience for implementation packages, so end users don't have to import logiface.

func (LoggerFactory[E]) LevelDebug

func (LoggerFactory[E]) LevelDebug() Level

LevelDebug returns LevelDebug, and is provided as a convenience for implementation packages, so end users don't have to import logiface.

func (LoggerFactory[E]) LevelDisabled

func (LoggerFactory[E]) LevelDisabled() Level

LevelDisabled returns LevelDisabled, and is provided as a convenience for implementation packages, so end users don't have to import logiface.

func (LoggerFactory[E]) LevelEmergency

func (LoggerFactory[E]) LevelEmergency() Level

LevelEmergency returns LevelEmergency, and is provided as a convenience for implementation packages, so end users don't have to import logiface.

func (LoggerFactory[E]) LevelError

func (LoggerFactory[E]) LevelError() Level

LevelError returns LevelError, and is provided as a convenience for implementation packages, so end users don't have to import logiface.

func (LoggerFactory[E]) LevelInformational

func (LoggerFactory[E]) LevelInformational() Level

LevelInformational returns LevelInformational, and is provided as a convenience for implementation packages, so end users don't have to import logiface.

func (LoggerFactory[E]) LevelNotice

func (LoggerFactory[E]) LevelNotice() Level

LevelNotice returns LevelNotice, and is provided as a convenience for implementation packages, so end users don't have to import logiface.

func (LoggerFactory[E]) LevelTrace

func (LoggerFactory[E]) LevelTrace() Level

LevelTrace returns LevelTrace, and is provided as a convenience for implementation packages, so end users don't have to import logiface.

func (LoggerFactory[E]) LevelWarning

func (LoggerFactory[E]) LevelWarning() Level

LevelWarning returns LevelWarning, and is provided as a convenience for implementation packages, so end users don't have to import logiface.

func (LoggerFactory[E]) New

func (LoggerFactory[E]) New(options ...Option[E]) *Logger[E]

New is an alias of the package function of the same name.

See also LoggerFactory.New and L (an instance of LoggerFactory[Event]{}).

func (LoggerFactory[E]) NewEventFactoryFunc

func (LoggerFactory[E]) NewEventFactoryFunc(f func(level Level) E) EventFactoryFunc[E]

NewEventFactoryFunc is an alias provided as a convenience, to make it easier to cast a function to an EventFactoryFunc.

It's equivalent to EventFactoryFunc[E](f), which is more verbose, as it requires specifying the type, which, for this method, comes from the receiver.

See also logiface.NewEventFactoryFunc.

func (LoggerFactory[E]) NewEventReleaserFunc

func (LoggerFactory[E]) NewEventReleaserFunc(f func(event E)) EventReleaserFunc[E]

NewEventReleaserFunc is an alias provided as a convenience, to make it easier to cast a function to an EventReleaserFunc.

It's equivalent to EventReleaserFunc[E](f), which is more verbose, as it requires specifying the type, which, for this method, comes from the receiver.

See also logiface.NewEventReleaserFunc.

func (LoggerFactory[E]) NewModifierFunc

func (LoggerFactory[E]) NewModifierFunc(f func(event E) error) ModifierFunc[E]

NewModifierFunc is an alias provided as a convenience, to make it easier to cast a function to a ModifierFunc.

It's equivalent to ModifierFunc[E](f), which is more verbose, as it requires specifying the type, which, for this method, comes from the receiver.

See also logiface.NewModifierFunc.

func (LoggerFactory[E]) NewModifierSlice

func (LoggerFactory[E]) NewModifierSlice(s ...Modifier[E]) ModifierSlice[E]

NewModifierSlice is an alias provided as a convenience, to make it easier to initialize a ModifierSlice.

See also logiface.NewModifierSlice.

func (LoggerFactory[E]) NewWriterFunc

func (LoggerFactory[E]) NewWriterFunc(f func(event E) error) WriterFunc[E]

NewWriterFunc is an alias provided as a convenience, to make it easier to cast a function to a WriterFunc.

It's equivalent to WriterFunc[E](f), which is more verbose, as it requires specifying the type, which, for this method, comes from the receiver.

See also logiface.NewWriterFunc.

func (LoggerFactory[E]) NewWriterSlice

func (LoggerFactory[E]) NewWriterSlice(s ...Writer[E]) WriterSlice[E]

NewWriterSlice is an alias provided as a convenience, to make it easier to initialize a WriterSlice.

See also logiface.NewWriterSlice.

func (LoggerFactory[E]) WithDPanicLevel added in v0.4.0

func (LoggerFactory[E]) WithDPanicLevel(level Level) Option[E]

WithDPanicLevel is an alias of the package function of the same name.

func (LoggerFactory[E]) WithEventFactory

func (LoggerFactory[E]) WithEventFactory(factory EventFactory[E]) Option[E]

WithEventFactory is an alias of the package function of the same name.

func (LoggerFactory[E]) WithEventReleaser

func (LoggerFactory[E]) WithEventReleaser(releaser EventReleaser[E]) Option[E]

WithEventReleaser is an alias of the package function of the same name.

func (LoggerFactory[E]) WithJSONSupport added in v0.5.0

func (LoggerFactory[E]) WithJSONSupport(impl JSONSupport[E, any, any]) Option[E]

WithJSONSupport configures the implementation the logger uses to back support for nested data structures.

By default, maps of type `map[string]any` and slices of type `[]any` are used.

Depending on your implementation, you may need the WithJSONSupport function, instead.

func (LoggerFactory[E]) WithLevel

func (LoggerFactory[E]) WithLevel(level Level) Option[E]

WithLevel is an alias of the package function of the same name.

func (LoggerFactory[E]) WithModifier

func (LoggerFactory[E]) WithModifier(modifier Modifier[E]) Option[E]

WithModifier is an alias of the package function of the same name.

func (LoggerFactory[E]) WithOptions

func (LoggerFactory[E]) WithOptions(options ...Option[E]) Option[E]

WithOptions is an alias of the package function of the same name.

func (LoggerFactory[E]) WithWriter

func (LoggerFactory[E]) WithWriter(writer Writer[E]) Option[E]

WithWriter is an alias of the package function of the same name.

type Modifier

type Modifier[E Event] interface {
	Modify(event E) error
}

Modifier is used to model the configuration of a log event, e.g. adding fields, including the message.

type ModifierFunc

type ModifierFunc[E Event] func(event E) error

ModifierFunc implements Modifier.

func NewModifierFunc

func NewModifierFunc[E Event](f func(event E) error) ModifierFunc[E]

NewModifierFunc is an alias provided as a convenience, to make it easier to cast a function to a ModifierFunc.

It's equivalent to ModifierFunc[E](f), which is more verbose, as it cannot infer the type.

See also LoggerFactory.NewModifierFunc.

func (ModifierFunc[E]) Modify

func (x ModifierFunc[E]) Modify(event E) error

type ModifierSlice

type ModifierSlice[E Event] []Modifier[E]

ModifierSlice combines Modifier values, calling each in turn, returning the first non-nil error.

func NewModifierSlice

func NewModifierSlice[E Event](s ...Modifier[E]) ModifierSlice[E]

NewModifierSlice is an alias provided as a convenience, to make it easier to initialize a ModifierSlice.

See also LoggerFactory.NewModifierSlice.

func (ModifierSlice[E]) Modify

func (x ModifierSlice[E]) Modify(event E) (err error)

type ObjectBuilder added in v0.5.0

type ObjectBuilder[E Event, P Parent[E]] refPoolItem
Example (DefaultFieldFormats)

Demonstrates the default object field formats, if the object support is defaulted.

type E = *mockSimpleEvent
var logger *Logger[E] = mockL.New(
	mockL.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
	mockL.WithWriter(&mockSimpleWriter{Writer: os.Stdout, MultiLine: true, JSON: true}),
)

logger.Info().
	Object().Field(`a`, time.Second*1).Dur(`b`, time.Second*3).Dur(`c`, time.Second/8).Field(`d`, time.Duration(float64(time.Hour)*3.51459)).As(`durs`).End().
	Object().Str(`e`, `str val`).As(`str`).End().
	Object().Bool(`f`, true).Bool(`F`, false).As(`bools`).End().
	Object().Any(`g`, map[int]float64{1: 1.0, 2: 1.0 / 2.0, 3: 1.0 / 3.0}).As(`map`).End().
	Object().Err(errors.New(`some error`)).As(`err`).End().
	Object().Int(`h`, 123).As(`int`).End().
	Object().Uint64(`i`, 123).As(`uint64`).End().
	Object().Int64(`j`, 123).As(`int64`).End().
	Object().Float32(`k`, 1.0/3.0).As(`float32`).End().
	Object().Float64(`l`, 1.0/3.0).As(`float64`).End().
	Object().Time(`m`, time.Unix(0, 0).UTC()).As(`time`).End().
	Object().Base64(`n`, []byte(`valasrdijasdu8jasidjasd`), nil).As(`base64`).End().
	Log(``)
Output:

[info]
durs={"a":"1s","b":"3s","c":"0.125s","d":"12652.524s"}
str={"e":"str val"}
bools={"F":false,"f":true}
map={"g":{"1":1,"2":0.5,"3":0.3333333333333333}}
err={"err":{}}
int={"h":123}
uint64={"i":"123"}
int64={"j":"123"}
float32={"k":0.33333334}
float64={"l":0.3333333333333333}
time={"m":"1970-01-01T00:00:00Z"}
base64={"n":"dmFsYXNyZGlqYXNkdThqYXNpZGphc2Q="}

func Object added in v0.5.0

func Object[E Event, P Parent[E]](p P) (obj *ObjectBuilder[E, P])
Example (NestedObjects)
package main

import (
	"os"
)

var (
	// compile time assertions

	_ objectBuilderInterface = (*ObjectBuilder[Event, *Builder[Event]])(nil)
)

func main() {
	type E = *mockSimpleEvent
	var logger *Logger[E] = mockL.New(
		mockL.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
		mockL.WithWriter(&mockSimpleWriter{Writer: os.Stdout, MultiLine: true, JSON: true}),
	)

	subLogger := Object[E](Object[E](Object[E](Object[E](Object[E](logger.Clone()).Field(`a`, 1).Field(`b`, true)).Field(`c`, 2).Field(`d`, false).As(`e`)).Field(`f`, 3)).Field(`g`, 4)).
		Field(`h`, 5).
		As(`i`).
		As(`j`).
		As(`k`).
		As(`arr_1`).
		Field(`l`, `A`).
		Logger()

	Object[E](Object[E](Object[E](Object[E](Object[E](subLogger.Notice()).Field(`m`, 1).Field(`n`, true)).Field(`o`, 2).Field(`p`, false).As(`q`)).Field(`r`, 3)).Field(`s`, 4)).
		Field(`t`, 5).
		As(`u`).
		As(`v`).
		As(`w`).
		As(`arr_2`).
		Field(`x`, `B`).
		Log(`msg 1`)

}
Output:

[notice]
arr_1={"a":1,"b":true,"e":{"c":2,"d":false},"k":{"f":3,"j":{"g":4,"i":{"h":5}}}}
l="A"
arr_2={"m":1,"n":true,"q":{"o":2,"p":false},"w":{"r":3,"v":{"s":4,"u":{"t":5}}}}
x="B"
msg="msg 1"

func (*ObjectBuilder[E, P]) Add added in v0.5.0

func (x *ObjectBuilder[E, P]) Add() (p P)

Add is an alias for ObjectBuilder.As(""), and is provided for convenience, to improve clarity when adding an object to an array (a case where the key must be an empty string).

WARNING: References to the receiver must not be retained.

func (*ObjectBuilder[E, P]) Any added in v0.5.0

func (x *ObjectBuilder[E, P]) Any(key string, val any) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Array added in v0.5.0

func (x *ObjectBuilder[E, P]) Array() *ArrayBuilder[E, P]

Array attempts to initialize a sub-array, which will succeed only if the parent is Chain, otherwise performing Logger.DPanic (returning nil if in a production configuration).

func (*ObjectBuilder[E, P]) As added in v0.5.0

func (x *ObjectBuilder[E, P]) As(key string) (p P)

As writes the object to the parent, using the provided key (if relevant), and returns the parent.

While you may use this to add an object to an array, providing a non-empty key with an array as a parent will result in a Logger.DPanic. In such cases, prefer ObjectBuilder.Add.

WARNING: References to the receiver must not be retained.

func (*ObjectBuilder[E, P]) Base64 added in v0.5.0

func (x *ObjectBuilder[E, P]) Base64(key string, b []byte, enc *base64.Encoding) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Bool added in v0.5.0

func (x *ObjectBuilder[E, P]) Bool(key string, val bool) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Call added in v0.5.0

func (x *ObjectBuilder[E, P]) Call(fn func(b *ObjectBuilder[E, P])) *ObjectBuilder[E, P]

Call is provided as a convenience, to facilitate code which uses the receiver explicitly, without breaking out of the fluent-style API. The provided fn will not be called if not ObjectBuilder.Enabled.

func (*ObjectBuilder[E, P]) Dur added in v0.5.0

func (x *ObjectBuilder[E, P]) Dur(key string, val time.Duration) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Enabled added in v0.5.0

func (x *ObjectBuilder[E, P]) Enabled() bool

Enabled returns whether the parent is enabled.

func (*ObjectBuilder[E, P]) Err added in v0.5.0

func (x *ObjectBuilder[E, P]) Err(val error) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Field added in v0.5.0

func (x *ObjectBuilder[E, P]) Field(key string, val any) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Float32 added in v0.5.0

func (x *ObjectBuilder[E, P]) Float32(key string, val float32) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Float64 added in v0.5.0

func (x *ObjectBuilder[E, P]) Float64(key string, val float64) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Int added in v0.5.0

func (x *ObjectBuilder[E, P]) Int(key string, val int) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Int64 added in v0.5.0

func (x *ObjectBuilder[E, P]) Int64(key string, val int64) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Interface added in v0.5.0

func (x *ObjectBuilder[E, P]) Interface(key string, val any) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Object added in v0.5.0

func (x *ObjectBuilder[E, P]) Object() *ObjectBuilder[E, P]

Object attempts to initialize a sub-object, which will succeed only if the parent is Chain, otherwise performing Logger.DPanic (returning nil if in a production configuration).

func (*ObjectBuilder[E, P]) Root added in v0.6.0

func (x *ObjectBuilder[E, P]) Root() *Logger[E]

Root returns the root Logger for this instance.

func (*ObjectBuilder[E, P]) Str added in v0.5.0

func (x *ObjectBuilder[E, P]) Str(key string, val string) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Time added in v0.5.0

func (x *ObjectBuilder[E, P]) Time(key string, val time.Time) *ObjectBuilder[E, P]

func (*ObjectBuilder[E, P]) Uint64 added in v0.5.0

func (x *ObjectBuilder[E, P]) Uint64(key string, val uint64) *ObjectBuilder[E, P]

type Option

type Option[E Event] func(c *loggerConfig[E])

Option is a configuration option for constructing Logger instances, using the New function, or it's alias(es), e.g. LoggerFactory.New.

func WithDPanicLevel added in v0.4.0

func WithDPanicLevel[E Event](level Level) Option[E]

WithDPanicLevel configures the level that the Logger.DPanic method will alias to, defaulting to LevelCritical.

See also LoggerFactory.WithDPanicLevel and L (an instance of LoggerFactory[Event]{}).

func WithEventFactory

func WithEventFactory[E Event](factory EventFactory[E]) Option[E]

WithEventFactory configures the logger's EventFactory.

See also LoggerFactory.WithEventFactory and L (an instance of LoggerFactory[Event]{}).

func WithEventReleaser

func WithEventReleaser[E Event](releaser EventReleaser[E]) Option[E]

WithEventReleaser configures the logger's EventReleaser.

See also LoggerFactory.WithEventReleaser and L (an instance of LoggerFactory[Event]{}).

func WithJSONSupport added in v0.5.0

func WithJSONSupport[E Event, O any, A any](impl JSONSupport[E, O, A]) Option[E]

WithJSONSupport configures the implementation the logger uses to back support for nested data structures.

By default, slices of type `[]any` are used.

See also LoggerFactory.WithJSONSupport.

func WithLevel

func WithLevel[E Event](level Level) Option[E]

WithLevel configures the logger's Level.

Level will be used to filter events that are mapped to a syslog-defined level. Events with a custom level will always be logged.

See also LoggerFactory.WithLevel and L (an instance of LoggerFactory[Event]{}).

func WithModifier

func WithModifier[E Event](modifier Modifier[E]) Option[E]

WithModifier configures the logger's Modifier, appending it to an internal ModifierSlice.

See also LoggerFactory.WithModifier and L (an instance of LoggerFactory[Event]{}).

func WithOptions

func WithOptions[E Event](options ...Option[E]) Option[E]

WithOptions combines multiple Option values into one.

See also LoggerFactory.WithOptions and L (an instance of LoggerFactory[Event]{}).

func WithWriter

func WithWriter[E Event](writer Writer[E]) Option[E]

WithWriter configures the logger's Writer, prepending it to an internal WriterSlice.

See also LoggerFactory.WithWriter and L (an instance of LoggerFactory[Event]{}).

type Parent added in v0.4.0

type Parent[E Event] interface {
	Enabled() bool
	Root() *Logger[E]
	// contains filtered or unexported methods
}

Parent models one of the fluent-style builder implementations, including Builder, Context, ArrayBuilder, and others.

type UnimplementedEvent

type UnimplementedEvent struct{}

UnimplementedEvent must be embedded in every Event implementation. It provides implementation of methods that are optional.

func (UnimplementedEvent) AddBase64Bytes

func (UnimplementedEvent) AddBase64Bytes(string, []byte, *base64.Encoding) bool

func (UnimplementedEvent) AddBool added in v0.3.0

func (UnimplementedEvent) AddBool(string, bool) bool

func (UnimplementedEvent) AddDuration

func (UnimplementedEvent) AddDuration(string, time.Duration) bool

func (UnimplementedEvent) AddError

func (UnimplementedEvent) AddError(error) bool

func (UnimplementedEvent) AddFloat32

func (UnimplementedEvent) AddFloat32(string, float32) bool

func (UnimplementedEvent) AddFloat64 added in v0.3.0

func (UnimplementedEvent) AddFloat64(string, float64) bool

func (UnimplementedEvent) AddInt

func (UnimplementedEvent) AddInt(string, int) bool

func (UnimplementedEvent) AddInt64 added in v0.3.0

func (UnimplementedEvent) AddInt64(string, int64) bool

func (UnimplementedEvent) AddMessage

func (UnimplementedEvent) AddMessage(string) bool

func (UnimplementedEvent) AddString

func (UnimplementedEvent) AddString(string, string) bool

func (UnimplementedEvent) AddTime

func (UnimplementedEvent) AddUint64 added in v0.3.0

func (UnimplementedEvent) AddUint64(string, uint64) bool

type UnimplementedJSONSupport added in v0.5.0

type UnimplementedJSONSupport[E Event, O any, A any] struct{}

func (UnimplementedJSONSupport[E, O, A]) AppendArray added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendArray(arr A, val A) A

func (UnimplementedJSONSupport[E, O, A]) AppendBase64Bytes added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendBase64Bytes(arr A, b []byte, enc *base64.Encoding) A

func (UnimplementedJSONSupport[E, O, A]) AppendBool added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendBool(arr A, val bool) A

func (UnimplementedJSONSupport[E, O, A]) AppendDuration added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendDuration(arr A, d time.Duration) A

func (UnimplementedJSONSupport[E, O, A]) AppendError added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendError(arr A, err error) A

func (UnimplementedJSONSupport[E, O, A]) AppendFloat32 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendFloat32(arr A, val float32) A

func (UnimplementedJSONSupport[E, O, A]) AppendFloat64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendFloat64(arr A, val float64) A

func (UnimplementedJSONSupport[E, O, A]) AppendInt added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendInt(arr A, val int) A

func (UnimplementedJSONSupport[E, O, A]) AppendInt64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendInt64(arr A, val int64) A

func (UnimplementedJSONSupport[E, O, A]) AppendObject added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendObject(arr A, val O) A

func (UnimplementedJSONSupport[E, O, A]) AppendString added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendString(arr A, val string) A

func (UnimplementedJSONSupport[E, O, A]) AppendTime added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendTime(arr A, t time.Time) A

func (UnimplementedJSONSupport[E, O, A]) AppendUint64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) AppendUint64(arr A, val uint64) A

func (UnimplementedJSONSupport[E, O, A]) CanAppendArray added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendArray() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendBase64Bytes added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendBase64Bytes() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendBool added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendBool() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendDuration added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendDuration() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendError added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendError() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendFloat32 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendFloat32() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendFloat64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendFloat64() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendInt added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendInt() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendInt64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendInt64() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendObject added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendObject() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendString added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendString() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendTime added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendTime() bool

func (UnimplementedJSONSupport[E, O, A]) CanAppendUint64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanAppendUint64() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetArray added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetArray() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetBase64Bytes added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetBase64Bytes() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetBool added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetBool() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetDuration added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetDuration() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetError added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetError() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetFloat32 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetFloat32() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetFloat64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetFloat64() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetInt added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetInt() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetInt64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetInt64() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetObject added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetObject() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetString added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetString() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetTime added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetTime() bool

func (UnimplementedJSONSupport[E, O, A]) CanSetUint64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) CanSetUint64() bool

func (UnimplementedJSONSupport[E, O, A]) SetArray added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetArray(obj O, key string, val A) O

func (UnimplementedJSONSupport[E, O, A]) SetBase64Bytes added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetBase64Bytes(obj O, key string, b []byte, enc *base64.Encoding) O

func (UnimplementedJSONSupport[E, O, A]) SetBool added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetBool(obj O, key string, val bool) O

func (UnimplementedJSONSupport[E, O, A]) SetDuration added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetDuration(obj O, key string, d time.Duration) O

func (UnimplementedJSONSupport[E, O, A]) SetError added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetError(obj O, err error) O

func (UnimplementedJSONSupport[E, O, A]) SetFloat32 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetFloat32(obj O, key string, val float32) O

func (UnimplementedJSONSupport[E, O, A]) SetFloat64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetFloat64(obj O, key string, val float64) O

func (UnimplementedJSONSupport[E, O, A]) SetInt added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetInt(obj O, key string, val int) O

func (UnimplementedJSONSupport[E, O, A]) SetInt64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetInt64(obj O, key string, val int64) O

func (UnimplementedJSONSupport[E, O, A]) SetObject added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetObject(obj O, key string, val O) O

func (UnimplementedJSONSupport[E, O, A]) SetString added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetString(obj O, key string, val string) O

func (UnimplementedJSONSupport[E, O, A]) SetTime added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetTime(obj O, key string, t time.Time) O

func (UnimplementedJSONSupport[E, O, A]) SetUint64 added in v0.5.0

func (UnimplementedJSONSupport[E, O, A]) SetUint64(obj O, key string, val uint64) O

type Writer

type Writer[E Event] interface {
	Write(event E) error
}

Writer writes out / finalizes an event.

Event MUST NOT be retained or modified after the call.

type WriterFunc

type WriterFunc[E Event] func(event E) error

WriterFunc implements Writer.

func NewWriterFunc

func NewWriterFunc[E Event](f func(event E) error) WriterFunc[E]

NewWriterFunc is an alias provided as a convenience, to make it easier to cast a function to a WriterFunc.

It's equivalent to WriterFunc[E](f), which is more verbose, as it cannot infer the type.

See also LoggerFactory.NewWriterFunc.

func (WriterFunc[E]) Write

func (x WriterFunc[E]) Write(event E) error

type WriterSlice

type WriterSlice[E Event] []Writer[E]

WriterSlice combines writers, returning success on the first writer that succeeds, returning the first error that isn't ErrDisabled, or ErrDisabled if every writer returns ErrDisabled (or if empty).

WARNING: ErrDisabled must be returned directly (not wrapped).

func NewWriterSlice

func NewWriterSlice[E Event](s ...Writer[E]) WriterSlice[E]

NewWriterSlice is an alias provided as a convenience, to make it easier to initialize a WriterSlice.

See also LoggerFactory.NewWriterSlice.

func (WriterSlice[E]) Write

func (x WriterSlice[E]) Write(event E) (err error)

Directories

Path Synopsis
logrus module
stumpy module
testsuite module
zerolog module

Jump to

Keyboard shortcuts

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