Documentation ¶
Overview ¶
Package types of logger unifies different types of loggers into interfaces Logger. For example it allows to upgrade simple fmt.Printf to be a fully functional Logger. Therefore multiple wrappers are implemented here to provide different functions which could be missing in some loggers.
Package types of logger unifies different types of loggers into interfaces Logger. For example it allows to upgrade simple fmt.Printf to be a fully functional Logger. Therefore multiple wrappers are implemented here to provide different functions which could be missing in some loggers.
Index ¶
- Constants
- type Config
- type Emitter
- type Emitters
- type Entry
- type EntryProperties
- type EntryProperty
- type Flusher
- type GetCallerPC
- type Hook
- type Hooks
- type Level
- type Logger
- type Option
- type OptionGetCallerFunc
- type Options
- type PreHook
- type PreHookResult
- type PreHooks
- func (s PreHooks) ProcessInput(traceIDs belt.TraceIDs, level Level, values ...any) PreHookResult
- func (s PreHooks) ProcessInputFields(traceIDs belt.TraceIDs, level Level, message string, ...) PreHookResult
- func (s PreHooks) ProcessInputf(traceIDs belt.TraceIDs, level Level, format string, args ...any) PreHookResult
Constants ¶
const ( // LevelUndefined is an erroneous value of log-level which just corresponds // to the zero-value. LevelUndefined = Level(iota) // LevelNone means to do not log anything. // // But even if a Logger is setup with this level, messages with levels Panic // and Fatal will still cause panics and os.Exit, just we except this to avoid // sending log messages (some Logger implementations may ignore this rule). LevelNone // LevelFatal means non-recoverable error case. // // If a message sent with this level then os.Exit is invoked in the end of processing the message. // // If a Logger is setup with this level, it will just ignore messages with level higher than Panic, // will silently panic on a Panic message and will loudly exit on a Fatal message. // // Some Logger implementations may ignore the rule about panicking "silently". LevelFatal // LevelPanic means a panic case (basically a recoverable, but critical problem). // // If a message sent with this level then panic() is invoked in the end of processing the message. // // If a Logger is setup with this level, it will ignore messages with level higher than Panic. LevelPanic // LevelError means an error case (not a critical problem, but yet an error). // // A message with this level is just logged if the Logger is setup with level no less that this. LevelError // LevelWarning means an odd/unexpected/wrong/undesired/etc case. Basically this is something // to keep an eye on. For example which could explain odd/erroneous behavior of the application // in future. // // A message with this level is just logged if the Logger is setup with level no less that this. LevelWarning // LevelInfo means an information message, essential enough to notify the end user (who is // not a developer of the application), but about something benign and that does not // says to any wrong behavior of the application. // // A message with this level is just logged if the Logger is setup with level no less that this. // // Recommended as the default level. LevelInfo // LevelDebug means a message non-essential for the end user, but useful for debugging // the application by its developer. // // A message with this level is just logged if the Logger is setup with level no less that this. LevelDebug // LevelTrace is for all other messages. // // For example, sometimes in complex processes/application it sometimes useful // to have an extra layer to put an insane amount put all useless messages, which // may suddenly become very useful for some very difficult debug process. // // A message with this level is just logged if the Logger is setup with level no less that this. LevelTrace // EndOfLevel just defines a maximum level + 1. EndOfLevel )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct { // GetCallerPC defines the line of code which invoked the logging entry, // see the description of "GetCallerPC" . GetCallerFunc GetCallerPC // ImplementationSpecificOptions is a set of Logger-implementation-specific // options. ImplementationSpecificOptions []any }
Config is a resulting configuration of a collection of Options.
type Emitter ¶
type Emitter interface { Flusher // Emit just logs the provided Entry. It does not modify it. // // If it is reasonably possible then the implementation of Emitter // should not panic or os.Exit even if the Level is Fatal or Panic. // Otherwise for example it prevents from logging a problem through other // Emitters if there are multiple of them. Emit(entry *Entry) }
Emitter is a log entry sender. It is not obligated to provide functionality for logging levels, hooks, contextual fields or any other fancy stuff, and it just sends what is was told to.
Note: Some specific Emitter implementations may support filtering of messages based on log level or/and add structured fields internally or do other stuff. But it is expected that even if a Emitter actually supports that kind of functionality, it will still be by default configured in a way like it has no such functionality (thus maximal logging level, no contextual fields and so on). However, if a Emitter is returned from a Logger, then it may (or may not) inherit properties of Logger (like logging level or structured fields). The undefined behavior here is left intentionally to provide more flexibility to Logger implementations to achieve better performance. It is considered than any Emitter managed by a Logger may have any configuration the Logger may consider the optimal one at any moment.
All methods are thread-safe.
type Emitters ¶
type Emitters []Emitter
Emitters is a set of Emitter-s.
Only the last Emitter is allowed to panic or/and os.Exit (on Level-s Fatal and Panic). Do not use a set of Emitters if this rule is not satisfied. Check guarantees these provided by specific a Emitter implementation.
type Entry ¶
type Entry struct { // Timestamp defines the time moment when the entry was issued (for example method `Debugf` was called). Timestamp time.Time // Level is the logging level of the entry. Level Level // Message is an arbitrary string explaining the event, an unstructured message. // It is set by `*f` (e.g. `Debugf`) functions, by argument "message" in // LogFields/TraceFields/etc function or by unstructured values in Log/Trace/Debug/etc functions. Message string // Fields implements ways to read the structured fields to be logged. // // To avoid copying the fields into an intermediate format (which most likely // will be transformed into something else anyway in the Logger implementation) // we provide here an accessor to Fields instead of compiled Fields themselves. Fields field.AbstractFields // TraceIDs is the collection of unique IDs associated with this logging entry. // For example it may be useful to attach an unique ID to each network request, // so that it will be possible to fetch the whole log of processing for any network request. TraceIDs belt.TraceIDs // Properties defines special implementation-specific behavior related to the Entry. // // See description of EntryProperty. Properties EntryProperties // Caller is the Program Counter of the position in the code which initiated the logging // of the entry. // // See also OptionGetCallerFunc and DefaultGetCallerFunc. Caller runtime.PC }
Entry a single log entry to be logged/written.
type EntryProperties ¶
type EntryProperties []EntryProperty
EntryProperties is a collection of EntryProperty-es.
func (EntryProperties) Add ¶
func (s EntryProperties) Add(a ...EntryProperty) EntryProperties
Add returns the concatenation of EntryProperties.
Note! It does not work similar to classical `append` function, instead it nests two slices into a new slice to optimize for CPU and RAM (by avoiding extra memory allocation and copying).
func (EntryProperties) Has ¶
func (s EntryProperties) Has(p EntryProperty) bool
Has returns true if the collection of properties contains a specific EntryProperty. It should be equal by both: type and value.
type EntryProperty ¶
type EntryProperty any
EntryProperty defines special implementation-specific behavior related to a specific Entry.
Any Emitter implementation, Hook or other tool may use it for internal or/and external needs.
For example, a Emitter may support both async and sync logging, and it could be possible to request sync logging through a property.
Another example is: if an error monitor and a logger are hooked to each other then these properties could be used to avoid loops (to mark already processed entries).
type Flusher ¶
type Flusher interface {
// Flush forces to flush all buffers.
Flush()
}
Flusher defines a method to flush all buffers.
type GetCallerPC ¶
GetCallerPC is a function which returns the Program Counter (PC) of the piece of code which invoked logging the entry.
It is called by a Logger to fill the value Entry.Caller.
type Hook ¶
type Hook interface { // ProcessLogEntry is called right before sending the Entry to a Emitter. // // If the returned value is false, then the sending and processing by other hooks // are cancelled. // // It is allowed to modify the entry. ProcessLogEntry(*Entry) bool // Flush gracefully empties any buffers the hook may have. Flush() }
Hook is a pre-processor for log entries. It may for example modify them or cancel them.
type Hooks ¶
type Hooks []Hook
Hooks is a collection of Hook-s.
func (Hooks) ProcessLogEntry ¶
ProcessLogEntry implements Hook.
type Level ¶
type Level int
Level is a severity of a message/Entry.
There are two ways to use Level: 1. To define a severity of a specific message/Entry (when logging). 2. To define a severity of messages/Entries be actually logged (when configuring a Logger).
func ParseLogLevel ¶
ParseLogLevel parses incoming string into a Level and returns LevelUndefined with an error if an unknown logging level was passed.
func (Level) Byte ¶
Byte is similar to String, but returns a single byte, which describes in a human-readable way the logging level.
func (*Level) Set ¶
Set updates the logging level values based on the passed string value. This method just implements flag.Value and pflag.Value.
type Logger ¶
type Logger interface { belt.Tool // Logf logs an unstructured message. Though, of course, all // contextual structured fields will also be logged. // // This method exists mostly for convenience, for people who // has not got used to proper structured logging, yet. // See `LogFields` and `Log`. If one have variables they want to // log, it is better for scalable observability to log them // as structured values, instead of injecting them into a // non-structured string. Logf(level Level, format string, args ...any) // LogFields logs structured fields with a explanation message. // // Anything that implements field.AbstractFields might be used // as a collection of fields to be logged. // // Examples: // // l.LogFields(logger.LevelDebug, "new_request", field.Fields{{Key: "user_id", Value: userID}, {Key: "group_id", Value: groupID}}) // l.LogFields(logger.LevelInfo, "affected entries", field.Field{Key: "mysql_affected", Value: affectedRows}) // l.LogFields(logger.LevelError, "unable to fetch user info", request) // where `request` implements field.AbstractFields // // Sometimes it is inconvenient to manually describe each field, // and for such cases see method `Log`. LogFields(level Level, message string, fields field.AbstractFields) // Log extracts structured fields from provided values, joins // the rest into an unstructured message and logs the result. // // This function provides convenience (relatively to LogFields) // at cost of a bit of performance. // // There are few ways to extract structured fields, which are // applied for each value from `values` (in descending priority order): // 1. If a `value` is an `*Entry` then the Entry is used (with its fields). // This works only if this is the only argument. Otherwise it is // threated as a simple structure (see point #3). // 2. If a `value` implements field.AbstractFields then ForEachField method // is used (so it is become similar to LogFields). // 3. If a `value` is a structure (or a pointer to a structure) then // fields of the structure are interpreted as structured fields // to be logged (see explanation below). // 4. If a `value` is a map then fields a constructed out of this map. // // Structured arguments are processed effectively the same // as they would have through a sequence of WithField/WithFields. // // Everything that does not fit into any of the rules above is just // joined into an unstructured message (and works the same way // as `message` in LogFields). // // How structures are parsed: // Structures are parsed recursively. Each field name of the path in a tree // of structures is added to the resulting field name (for example in "struct{A struct{B int}}" // the field name will be `A.B`). // To enforce another name use tag `log` (for example "struct{A int `log:"anotherName"`}"), // to prevent a field from logging use tag `log:"-"`. // // Examples: // // user, err := getUser() // if err != nil { // l.Log(logger.LevelError, err) // return err // } // l.Log(logger.LevelDebug, "current user", user) // fields of structure "user" will be logged // l.Log(logger.LevelDebug, map[string]any{"user_id": user.ID, "group_id", user.GroupID}) // l.Log(logger.LevelDebug, field.Fields{{Key: "user_id", Value: user.ID}, {Key: "group_id", Value: user.GroupID}}) // l.Log(logger.LevelDebug, "current user ID is ", user.ID, " and group ID is ", user.GroupID) // will result into message "current user ID is 1234 and group ID is 5678". Log(level Level, values ...any) // Emitter returns the Emitter (see the description of interface "Emitter"). Emitter() Emitter // Level returns the current logging level (see description of "Level"). Level() Level // TraceFields is just a shorthand for LogFields(logger.LevelTrace, ...) TraceFields(message string, fields field.AbstractFields) // DebugFields is just a shorthand for LogFields(logger.LevelDebug, ...) DebugFields(message string, fields field.AbstractFields) // InfoFields is just a shorthand for LogFields(logger.LevelInfo, ...) InfoFields(message string, fields field.AbstractFields) // WarnFields is just a shorthand for LogFields(logger.LevelWarn, ...) WarnFields(message string, fields field.AbstractFields) // ErrorFields is just a shorthand for LogFields(logger.LevelError, ...) ErrorFields(message string, fields field.AbstractFields) // PanicFields is just a shorthand for LogFields(logger.LevelPanic, ...) // // Be aware: Panic level also triggers a `panic`. PanicFields(message string, fields field.AbstractFields) // FatalFields is just a shorthand for LogFields(logger.LevelFatal, ...) // // Be aware: Panic level also triggers an `os.Exit`. FatalFields(message string, fields field.AbstractFields) // Trace is just a shorthand for Log(logger.LevelTrace, ...) Trace(values ...any) // Debug is just a shorthand for Log(logger.LevelDebug, ...) Debug(values ...any) // Info is just a shorthand for Log(logger.LevelInfo, ...) Info(values ...any) // Warn is just a shorthand for Log(logger.LevelWarn, ...) Warn(values ...any) // Error is just a shorthand for Log(logger.LevelError, ...) Error(values ...any) // Panic is just a shorthand for Log(logger.LevelPanic, ...) // // Be aware: Panic level also triggers a `panic`. Panic(values ...any) // Fatal is just a shorthand for Log(logger.LevelFatal, ...) // // Be aware: Fatal level also triggers an `os.Exit`. Fatal(values ...any) // Tracef is just a shorthand for Logf(logger.LevelTrace, ...) Tracef(format string, args ...any) // Debugf is just a shorthand for Logf(logger.LevelDebug, ...) Debugf(format string, args ...any) // Infof is just a shorthand for Logf(logger.LevelInfo, ...) Infof(format string, args ...any) // Warnf is just a shorthand for Logf(logger.LevelWarn, ...) Warnf(format string, args ...any) // Errorf is just a shorthand for Logf(logger.LevelError, ...) Errorf(format string, args ...any) // Panicf is just a shorthand for Logf(logger.LevelPanic, ...) // // Be aware: Panic level also triggers a `panic`. Panicf(format string, args ...any) // Fatalf is just a shorthand for Logf(logger.LevelFatal, ...) // // Be aware: Fatal level also triggers an `os.Exit`. Fatalf(format string, args ...any) // WithLevel returns a logger with logger level set to the given argument. // // See also the description of type "Level". WithLevel(Level) Logger // WithPreHooks returns a Logger which includes/appends pre-hooks from the arguments. // // See also description of "PreHook". // // Special case: to reset hooks use `WithPreHooks()` (without any arguments). WithPreHooks(...PreHook) Logger // WithHooks returns a Logger which includes/appends hooks from the arguments. // // See also description of "Hook". // // Special case: to reset hooks use `WithHooks()` (without any arguments). WithHooks(...Hook) Logger // WithField returns the logger with the added field (used for structured logging). WithField(key string, value any, props ...field.Property) Logger // WithFields returns the logger with the added fields (used for structured logging) WithFields(fields field.AbstractFields) Logger // WithMessagePrefix adds a string to all messages logged through the derived logger. WithMessagePrefix(prefix string) Logger // WithEntryProperties adds props to EntryProperties of each emitted Entry. // This could be used only for enabling implementation-specific behavior. WithEntryProperties(props ...EntryProperty) Logger }
Logger is an abstract generic structured logger. It is supposed to be one of the belt.Tools provided by the Belt. And therefore interface supposed to be used by end users of the `logger` package, so it already contains syntax sugar.
All methods are thread-safe.
For an optimized interface with the same functionality use interface CompactLogger.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option is an abstract option which changes the behavior of a Logger.
type OptionGetCallerFunc ¶
type OptionGetCallerFunc GetCallerPC
OptionGetCallerFunc overrides GetCallerPC (see description of "GetCallerPC").
type PreHook ¶
type PreHook interface { // ProcessInput is executed when functions Log, Trace, Debug, Info, Warn, Error, Panic and Fatal are called. // // TraceIDs are provided by Logger/CompactLogger and the rest arguments are just passed-through. ProcessInput(belt.TraceIDs, Level, ...any) PreHookResult // ProcessInputf is executed when functions Logf, Tracef, Debugf, Infof, Warnf, Errorf, Panicf and Fatalf are called. // // TraceIDs are provided by Logger/CompactLogger and the rest arguments are just passed-through. ProcessInputf(belt.TraceIDs, Level, string, ...any) PreHookResult // ProcessInputf is executed when functions LogFields, TraceFields, DebugFields, InfoFields, WarnFields, ErrorFields, PanicFields and FatalFields are called. // // TraceIDs are provided by Logger/CompactLogger and the rest arguments are just passed-through. ProcessInputFields(belt.TraceIDs, Level, string, field.AbstractFields) PreHookResult }
PreHook is executed very early in a Logger, allowing to discard or change an Entry before any essential computations are done.
For example it may be useful for samplers.
type PreHookResult ¶
type PreHookResult struct { // Skip forces a Logger to do not log this Entry. Skip bool // ExtraFields adds additional fields to the Entry. ExtraFields field.AbstractFields // ExtraEntryProperties adds additional Entry.Properties. ExtraEntryProperties EntryProperties }
PreHookResult is a result of computations returned by a PreHook.
type PreHooks ¶
type PreHooks []PreHook
PreHooks is a collection of PreHook-s.
func (PreHooks) ProcessInput ¶
func (s PreHooks) ProcessInput(traceIDs belt.TraceIDs, level Level, values ...any) PreHookResult
ProcessInput implements PreHook.
func (PreHooks) ProcessInputFields ¶
func (s PreHooks) ProcessInputFields(traceIDs belt.TraceIDs, level Level, message string, addFields field.AbstractFields) PreHookResult
ProcessInputFields implements PreHook.
func (PreHooks) ProcessInputf ¶
func (s PreHooks) ProcessInputf(traceIDs belt.TraceIDs, level Level, format string, args ...any) PreHookResult
ProcessInputf implements PreHook.