log

package
v0.4.2 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2025 License: MIT Imports: 7 Imported by: 0

README

Meta Logger

This implements zap-based meta logger with buffering capability, allowing to merge multiple log records into one log line.

Usage

import "github.com/workato/engine-packages/log"

logLevel := "info"
oneLiner := false
logger, err := log.New(logLevel, oneLiner)
logger.Info("my message", log.String("dummy", "value"), log.Bool("noted", true))

One line logging

This mode is intended to decrease the load on log processing subsystems and help to reduce disk space requirements in case of intensive logging when you cannot just enable sampling, for system observability reasons.

With oneLiner == false the logger works just like a normal zap logger.

With oneLiner == true it aggregates log data in memory until logger.Flush() is called, then it outputs a single log record. Suppose we have the following calls:

logger.Info("loading", log.String("dummy", "foo"))
// ...
logger.Info("operation", log.String("status", "good"))
// ...
logger.Warn("system", log.Int("memory low", 33))
// ...
logger.Flush() // MUST EXPLICITLY FLUSH

If we set our logger to normal mode, like this:

logger, err := log.New("info", false) // normal mode

we will get 3 separate log records:

{ "level":"info", "time":"...", "msg":"loading", "dummy":"foo" }
{ "level":"info", "time":"...", "msg":"operation", "status":"good" }
{ "level":"warn", "time":"...", "msg":"system", "memory low":33 }

However, if we set our logger to "oneliner" mode, like this:

logger, err := log.New("info", true) // oneliner mode

we will get a single log record:

{ "level":"warn", "time":"...", "msg":"system", "dummy":"foo", "status":"good", "memory low":33 }

Note that the whole log record has "warn" type as it is the highest level of all.

Main message in oneliner mode

When merging multiple log records into a single one we need to set a message (msg field) for the whole record. Naturally you want it to be the most informative among all records, for example it may be the type of the endpoint currently working or something similar. If nothing is specified explicitly the first message of the highest level is used.

However, since we can switch oneliner mode on and off, we may want to explicitly mark the main message which should be selected amonth other messages of the same level. You may do it using MainMessage() method:

logger.Info("start request", log.String("connections", conns))
// ...
logger.Info("my operation", log.String("status", status), log.MainMessage()) // <--
// ...
logger.Info("stop request", log.Float("duration", dur), log.Int("items processed", nItems))
// ...
logger.Flush()

the result in oneliner mode will be:

{ "level":"info", "time":"...", "msg":"my operation", "connections": 20, "status":"good", "duration":"0.004", "items processed":6 }

In the normal mode we will just get three separate log lines without any extra fields.

Verbose (normal multi-line) mode

Sometimes the "oneliner" mode is not suitable for certain uses, like, for example, logging in multiple goroutines running in parallel. In this case there's a possibility of merging log records from different goroutines and the result log line can be messy. For such cases the Verbose() method is used which returns a normal multi-line logger, even if the logging has been initially switched to a one-line mode. So, you can have a "oneliner" logger for your request handler and "verbose" logger for background processes.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ContextMetaLoggerType

type ContextMetaLoggerType string
const (
	ContextMetaLogger ContextMetaLoggerType = "ContextMetaLogger"
)

type Field

type Field struct {
	Key       string
	Type      FieldType
	Integer   int64
	Float64   float64
	String    string
	Interface any
}

func Any

func Any(name string, val any) Field

func Bool

func Bool(key string, val bool) Field

func Duration

func Duration(key string, val time.Duration) Field

func Error

func Error(err error) Field

func Float64

func Float64(key string, val float64) Field

func Float64p

func Float64p(key string, val *float64) Field

func Int

func Int(key string, val int) Field

func Int64

func Int64(key string, val int64) Field

func MainMessage

func MainMessage() Field

func Stack

func Stack(name string) Field

func String

func String(key string, val string) Field

func Stringp

func Stringp(key string, val *string) Field

func Strings

func Strings(key string, val []string) Field

func Time

func Time(key string, val time.Time) Field

type FieldType

type FieldType uint8
const (
	BoolType FieldType = iota
	IntType
	IntpType
	Float64Type
	Float64pType
	StringType
	StringsType
	StringpType
	ErrorType
	TimeType
	DurationType
	AnyType
	MessageType
)

type MetaLogger

type MetaLogger interface {
	Debug(msg string, fields ...Field)
	Info(msg string, fields ...Field)
	Warn(msg string, fields ...Field)
	Error(msg string, fields ...Field)
	DPanic(msg string, fields ...Field)
	Panic(msg string, fields ...Field)
	Fatal(msg string, fields ...Field)
	Infof(template string, args ...interface{})
	Add(fields ...Field)
	With(fields ...Field) MetaLogger
	Sync() error
	Flush()
	Verbose() MetaLogger
	SetContextLogger(ctx context.Context) context.Context
	SlogHandler() slog.Handler
}

MetaLogger implements logging functionality

func GetContextLogger

func GetContextLogger(ctx context.Context) MetaLogger

GetContextLogger returns a meta logger extracted from context.

func New

func New(level string, oneline bool) (MetaLogger, error)

New returns new logger. 'level' defines required logging level.

func NewNop

func NewNop() MetaLogger

NewNop returns no-op logger

Jump to

Keyboard shortcuts

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