logiface

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Feb 28, 2023 License: MIT Imports: 7 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]{}
)

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
// 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 := simpleLoggerFactory.New(
	simpleLoggerFactory.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
	simpleLoggerFactory.WithWriter(&mockSimpleWriter{Writer: w}),
	simpleLoggerFactory.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").
	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(``)

_ = 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
[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 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.

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]) 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]) 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.

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()`.

This method is not implemented by Context.

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]) 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]) 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]) 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]) 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].

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.

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]) 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]) 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]) 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]) 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]) 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].

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
	// 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

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 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.
	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.
	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[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]) 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]) Err

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

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

func (*Logger[E]) Info

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

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

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(
	simpleLoggerFactory.WithEventFactory(NewEventFactoryFunc(mockSimpleEventFactory)),
	simpleLoggerFactory.WithWriter(&mockSimpleWriter{Writer: os.Stdout}),
	simpleLoggerFactory.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[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]) 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]) 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]) 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 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 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 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 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) 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) AddInt

func (UnimplementedEvent) AddInt(string, int) bool

func (UnimplementedEvent) AddMessage

func (UnimplementedEvent) AddMessage(string) bool

func (UnimplementedEvent) AddString

func (UnimplementedEvent) AddString(string, string) bool

func (UnimplementedEvent) AddTime

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