galog

package module
v0.0.0-...-ec5a17c Latest Latest
Warning

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

Go to latest
Published: Jan 11, 2025 License: Apache-2.0 Imports: 16 Imported by: 31

README

galog (Guest Agent Logging Library)

Guest Agent Logging Library implements a generic, highly configurable, queueable, with a plug-able backend architecture. By default, galog provides a set of predefined backends, such as: CloudBackend, EventlogBackend, FileBackend, SyslogBackend etc.

Guest Agent Logging Library was created to accommodate the GCE's Guest Agent requirements.

Documentation

Overview

Package galog implements a generic, highly configurable, queueable, with a plug-able backend architecture. By default galog provides a set of predefined backends, such as: CloudBackend, EventlogBackend, FileBackend, SyslogBackend etc.

Initialization & Registration

An application using galog will follow the pattern of setting up basic parameters and registering backends before starting to use it, such as:

galog.SetMinVerbosity(2)
galog.SetLevel(galog.DebugLevel)

ctx := context.Background()
galog.RegisterBackend(ctx, galog.NewFileBackend("/var/log/app.log"))
galog.Info("Logger initialized.")
...

Multiple backends can be registered at the same time and a backend can be unregistered with UnregisterBackend at any time.

Verbosity

In addition to log levels (ErrorLevel, WarningLevel, InfoLevel and DebugLevel) galog also provides a notion of verbosity. An application may have for example a definition of multiple verbosity level logs by using V such as:

// Will be logged if the set verbosity is greater or equal than 1.
galog.V(1).Info("Info logged message with verbosity 1")
// Will be logged if the set verbosity is greater or equal than 2.
galog.V(2).Info("Info logged message with verbosity 2")

The application can then define its current verbosity by using SetMinVerbosity. Combined with SetLevel the application can fine tune levels of interest and its verbosity.

Enqueued Log Entries

Internally galog implements a queueing strategy when backends fail to write the log entries to the backing storage.

When a backend fails to write an entry the Backend's Log() function returns an error reporting the failure, the enqueuing code will detect such error condition and append the failed entry to a dedicated queue (each backend has its own queue).

Honoring the frequency set with QueueRetryFrequency galog will keep retrying to write entries from the queue in such a defined frequency. All log entries will be queued if there are pending writes (so the order of writes reflect the same order the entries were created), otherwise the entries are written immediately.

When the queue size limit is reached galog will start to drop the oldest entries so the newest ones have room to be enqueued.

Each backend has its own definition of "good default" queue sizes, however applications can redefine them by using SetQueueSize() from Config - accessing it with Backend's Config() operation, i.e.:

ctx := context.Background()

fileBackend := galog.NewFileBackend("/var/log/app.log")
fileBackend.Config().SetQueueSize(200) // resetting the FileBackend's queue size to 200

galog.RegisterBackend(ctx, fileBackend)
galog.Info("Logger initialized.")
...

Shutting down

To nicely shutdown galog exposes the Shutdown function that will attempt to write all the pending entries from all backends and force a flush (see Backend's Flush() function). When completed all previously registered backends will also be unregistered.

Index

Constants

View Source
const (
	// DefaultSerialBaud is the default serial baud for serial port writing.
	DefaultSerialBaud = 115200
)

Variables

View Source
var (

	// FatalLevel is the log level definition for Fatal severity.
	FatalLevel = Level{0, "FATAL"}

	// ErrorLevel is the log level definition for Error severity.
	ErrorLevel = Level{1, "ERROR"}

	// WarningLevel is the log level definition for Warning severity.
	WarningLevel = Level{2, "WARNING"}

	// InfoLevel is the log level definition for Info severity.
	InfoLevel = Level{3, "INFO"}

	// DebugLevel is the log level definition for Deug severity.
	DebugLevel = Level{4, "DEBUG"}
)

Functions

func Debug

func Debug(args ...any)

Debug logs to the DEBUG log. Arguments are handled in the manner of fmt.Print; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func Debugf

func Debugf(format string, args ...any)

Debugf logs to the DEBUG log. Arguments are handled in the manner of fmt.Printf; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func Error

func Error(args ...any)

Error logs to the ERROR log. Arguments are handled in the manner of fmt.Print; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func Errorf

func Errorf(format string, args ...any)

Errorf logs to the ERROR log. Arguments are handled in the manner of fmt.Printf; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func Fatal

func Fatal(args ...any)

Fatal logs to the FATAL log. Arguments are handled in the manner of fmt.Print; New line adding is handled by each backend and will be added when it makes sense considering the backend context. The Fatal function also exists the program with os.Exit(1).

Since it's calling os.Exit() the fatal functions will also Shutdown() the logger specifying the queue retry frequency as the timeout (see SetQueueRetryFrequency).

func Fatalf

func Fatalf(format string, args ...any)

Fatalf logs to the FATAL log. Arguments are handled in the manner of fmt.Printf; New line adding is handled by each backend and will be added when it makes sense considering the backend context. The Fatal function also exists the program with os.Exit(1).

Since it's calling os.Exit() the fatal functions will also Shutdown() the logger specifying the queue retry frequency as the timeout (see SetQueueRetryFrequency).

func Info

func Info(args ...any)

Info logs to the INFO log. Arguments are handled in the manner of fmt.Print; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func Infof

func Infof(format string, args ...any)

Infof logs to the INFO log. Arguments are handled in the manner of fmt.Printf; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func MinVerbosity

func MinVerbosity() int

MinVerbosity returns an integer representing the currently min verbosity set.

func QueueRetryFrequency

func QueueRetryFrequency() time.Duration

QueueRetryFrequency returns the currently log queue processing frequency.

func RegisterBackend

func RegisterBackend(ctx context.Context, backend Backend)

RegisterBackend inserts/registers a backend implementation. This function is thread safe and can be called from any goroutine in the program.

func RegisteredBackendIDs

func RegisteredBackendIDs() []string

RegisteredBackendIDs returns the list of registered backend IDs.

func SetLevel

func SetLevel(level Level)

SetLevel sets the current log level.

func SetMinVerbosity

func SetMinVerbosity(v int)

SetMinVerbosity sets the min verbosity to be assumed/used across the V() calls.

func SetPrefix

func SetPrefix(prefix string)

SetPrefix sets the prefix to be used for the log message. When present the default backend's formats will prefix the provided string to all log messages.

In cases where multiple backends are writing to the same backing storage (i.e. same file or the same syslog's ident) the prefix adds a meaningful context of the log originator.

func SetQueueRetryFrequency

func SetQueueRetryFrequency(frequency time.Duration)

SetQueueRetryFrequency sets the frequency which the log queue will be processed. This function is thread safe and can be called from any goroutine in the program.

func Shutdown

func Shutdown(timeout time.Duration)

Shutdown shuts down the default logger.

func UnregisterBackend

func UnregisterBackend(backend Backend)

UnregisterBackend removes/unregisters a backend implementation. This function is thread safe and can be called from any goroutine in the program.

func ValidLevels

func ValidLevels() string

ValidLevels returns a string representation of all the valid log levels, the only exception is the Fatal level as it's a special internal level.

func Warn

func Warn(args ...any)

Warn logs to the WARNING log. Arguments are handled in the manner of fmt.Print; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func Warnf

func Warnf(format string, args ...any)

Warnf logs to the WARNING log. Arguments are handled in the manner of fmt.Printf; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

Types

type Backend

type Backend interface {
	// ID returns the backend's implementation ID.
	ID() string
	// Log is the entry point with the Backend implementation, the log
	// framework will use Log() to forward the logging entry to the backend.
	Log(entry *LogEntry) error
	// Config returns the backend configuration interface implementation.
	Config() Config
	// Shutdown performs shutdown operations for the backend service.
	// The operations should include flushing the backend's backing log storage
	// and closing the backend's logging service if applicable.
	Shutdown(ctx context.Context) error
}

Backend defines the interface of a backend implementation.

type BackendQueue

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

BackendQueue wraps all the entry queueing control objects.

type CloudBackend

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

CloudBackend is a Backend implementation for cloud logging.

func NewCloudBackend

func NewCloudBackend(ctx context.Context, mode CloudLoggingInitMode, opts *CloudOptions) (*CloudBackend, error)

NewCloudBackend returns a Backend implementation that will log out to google cloud logging.

Initialization Mode:

If mode is InitModeLazy the backend object will be allocated and only the the basic elements will be initialized, all log entries will be queued until InitClient is called.

Why lazy initialization is important/needed?

The Cloud Logging depends on instance name that's mainly a data fed by - or accessed from - metadata server and depending on the application and environment the metadata server might not be available at the time of the application start - being only available later on. In such cases the early initializing and registering the backend will result into entries being queued and written/sent to the cloud logging later on - that way no logging entries are lost.

func (*CloudBackend) Config

func (cb *CloudBackend) Config() Config

Config returns the configuration of the cloud logging backend.

func (*CloudBackend) ID

func (cb *CloudBackend) ID() string

ID returns the cloud logging backend implementation's ID.

func (*CloudBackend) InitClient

func (cb *CloudBackend) InitClient(ctx context.Context, opts *CloudOptions) error

InitClient initializes the cloud logging client and logger. If the backend was initialized in "active" mode this function is no-op.

func (*CloudBackend) Log

func (cb *CloudBackend) Log(entry *LogEntry) error

Log prints sends the log entry to cloud logging.

func (*CloudBackend) Shutdown

func (cb *CloudBackend) Shutdown(ctx context.Context) error

Shutdown forces the cloud logging backend to flush its content and closes the logging client. This operation is skipped if Cloud Logging is unreachable.

type CloudEntryPayload

type CloudEntryPayload struct {
	// Message is the formatted message.
	Message string `json:"message"`
	// LocalTimestamp is the unix timestamp got from the entry's When field.
	LocalTimestamp string `json:"localTimestamp"`
	// ProgName is the program name - or the binary name.
	ProgName string `json:"progName,omitempty"`
	// ProgVersion is the program version.
	ProgVersion string `json:"progVersion,omitempty"`
}

CloudEntryPayload contains the data to be sent to cloud logging as the entry payload. It's translated from the log subsystem's Entry structure.

type CloudLoggingInitMode

type CloudLoggingInitMode int

CloudLoggingInitMode is the cloud logging backend initialization mode.

const (
	// CloudLoggingInitModeLazy is the lazy initialization mode. In this mode the
	// backend object is created but the cloud logging client and logger are not
	// initialized until the first call to InitClient.
	CloudLoggingInitModeLazy CloudLoggingInitMode = iota
	// CloudLoggingInitModeActive is the active initialization mode. In this mode
	// the backend object is created and the cloud logging client and logger are
	// initialized immediately.
	CloudLoggingInitModeActive
	// DefaultCloudLoggingPingTimeout is the default timeout for pinging cloud
	// logging.
	DefaultCloudLoggingPingTimeout = time.Second
)

type CloudOptions

type CloudOptions struct {
	// Ident is the logger's ident, or the logger's name.
	Ident string
	// ProgramName is the program name, it's used on the logging payload.
	ProgramName string
	// ProgramVersion is the program version, it's used on the logging payload.
	ProgramVersion string
	// Project the gcp project name.
	Project string
	// Instance the running instance name.
	Instance string
	// UserAgent is the logging user agent option.
	UserAgent string
	// FlushCadence is how frequently we should push the log to the server.
	FlushCadence time.Duration
	// PingTimeout is the timeout for pinging Cloud Logging.
	//
	// This is required currently because the cloud logging flush operation hangs
	// indefinitely when the server is unreachable due to having no external IP
	// address or private Google access enabled. The timeout is used to attempt
	// pinging the Cloud Logging server, and if it's not reachable, we skip the
	// flush operation.
	PingTimeout time.Duration
	// WithoutAuthentication is whether to use authentication for cloud logging
	// operations.
	WithoutAuthentication bool
}

CloudOptions defines the cloud logging behavior and setup options.

type Config

type Config interface {
	// QueueSize returns the max size of the queue for a given backend.
	QueueSize() int
	// SetQueueSize sets the max size of the queue for a given backend.
	SetQueueSize(size int)
	// SetFormat sets the log format of the specified level for a given backend.
	SetFormat(level Level, format string)
	// Format returns the log format of the specified level from a given backen.
	Format(level Level) string
}

Config is the interface used to bridge behavior configurations between the log framework and the backend implementation.

type EventlogBackend

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

EventlogBackend implements the Backend interface for logging to windows eventlog.

func NewEventlogBackend

func NewEventlogBackend(eventID uint32, ident string) (*EventlogBackend, error)

NewEventlogBackend returns a no-op eventlog linux implementation.

func (*EventlogBackend) Config

func (eb *EventlogBackend) Config() Config

Config returns the configuration of the eventlog backend.

func (*EventlogBackend) ID

func (eb *EventlogBackend) ID() string

ID returns the eventlog backend implementation's ID.

func (*EventlogBackend) Log

func (eb *EventlogBackend) Log(entry *LogEntry) error

Log no-op eventlog implementation for linux.

func (*EventlogBackend) Shutdown

func (eb *EventlogBackend) Shutdown(context.Context) error

Shutdown is a no-op implementation for event backend as we are opening eventlog for every log operation.

type FileBackend

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

FileBackend is an implementation for logging to a file.

func NewFileBackend

func NewFileBackend(logFilePath string) *FileBackend

NewFileBackend returns a Backend implementation that will log out to the file specified by logFilePath.

func (*FileBackend) Config

func (fb *FileBackend) Config() Config

Config returns the backend configuration of the file backend.

func (*FileBackend) ID

func (fb *FileBackend) ID() string

ID returns the file backend implementation's ID.

func (*FileBackend) Log

func (fb *FileBackend) Log(entry *LogEntry) error

Log prints the log entry to setup file.

func (*FileBackend) Shutdown

func (fb *FileBackend) Shutdown(context.Context) error

Shutdown is a no-op implementation for file backend as we are opening the file for every log operation.

type FormatMap

type FormatMap map[Level]string

FormatMap wraps the level <-> format map type.

type Level

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

Level wraps id and description of a log level.

func CurrentLevel

func CurrentLevel() Level

CurrentLevel returns the default logger current log level.

func ParseLevel

func ParseLevel(level int) (Level, error)

ParseLevel returns the log level object for a given level id. In case of invalid level id, an error is returned.

func (Level) String

func (level Level) String() string

String returns the string representation of a log level.

type LogEntry

type LogEntry struct {
	// Level is the log level of the log record/entry.
	Level Level
	// File is the file name of the log caller.
	File string
	// Line is the file's line of the log caller.
	Line int
	// Function is the function name of the log caller.
	Function string
	// When is the time when this log record/entry was created.
	When time.Time
	// Message is the formated final log message.
	Message string
	// Prefix is a string/tag prefixed to the log message.
	Prefix string
}

LogEntry describes a log record.

func (*LogEntry) Format

func (en *LogEntry) Format(format string) (string, error)

Format processes a template provided in format and return it as a string.

type SerialBackend

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

SerialBackend is an implementation for logging to serial.

func NewSerialBackend

func NewSerialBackend(ctx context.Context, opts *SerialOptions) *SerialBackend

NewSerialBackend returns a Backend implementation that will log out to the configured serial port.

func (*SerialBackend) Config

func (sb *SerialBackend) Config() Config

Config returns the configuration of the serial backend.

func (*SerialBackend) ID

func (sb *SerialBackend) ID() string

ID returns the cloud logging backend implementation's ID.

func (*SerialBackend) Log

func (sb *SerialBackend) Log(entry *LogEntry) error

Log prints the log entry to setup serial.

func (*SerialBackend) Shutdown

func (sb *SerialBackend) Shutdown(context.Context) error

Shutdown is a no-op implementation for serial backend as we are opening the file for every log operation.

type SerialOptions

type SerialOptions struct {
	// Port is the serial port name to be written to.
	Port string
	// Baud is the serial port baud.
	Baud int
}

SerialOptions contains the options for serial backend.

type StderrBackend

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

StderrBackend is a simple backend implementation for logging to stderr.

func NewStderrBackend

func NewStderrBackend(writer io.Writer) *StderrBackend

NewStderrBackend returns a Backend implementation that will log out to the process' stderr.

func (*StderrBackend) Config

func (wb *StderrBackend) Config() Config

Config returns the backend configuration of the stderr backend.

func (*StderrBackend) ID

func (wb *StderrBackend) ID() string

ID returns the stderr backend implementation's ID.

func (*StderrBackend) Log

func (wb *StderrBackend) Log(entry *LogEntry) error

Log prints the log entry to stderr.

func (*StderrBackend) Shutdown

func (wb *StderrBackend) Shutdown(context.Context) error

Shutdown flushes the stderr file.

type SyslogBackend

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

SyslogBackend is an implementation for logging to the linux syslog.

func NewSyslogBackend

func NewSyslogBackend(ident string) *SyslogBackend

NewSyslogBackend returns a Backend implementation that will log out to the underlying system's syslog framework.

func (*SyslogBackend) Config

func (sb *SyslogBackend) Config() Config

Config returns the configuration of the syslog backend.

func (*SyslogBackend) ID

func (sb *SyslogBackend) ID() string

ID returns the syslog backend implementation's ID.

func (*SyslogBackend) Log

func (sb *SyslogBackend) Log(entry *LogEntry) error

Log prints the log entry to syslog.

func (*SyslogBackend) Shutdown

func (sb *SyslogBackend) Shutdown(context.Context) error

Shutdown is a no-op implementation for syslog backend as we are opening (and closing) syslogger for every log operation.

type Verbose

type Verbose bool

Verbose is the verbosity controlled log operations.

func V

func V(v int) Verbose

V returns a boolean of type Verbose, it's value is true if the requested level is less or equal to the min verbosity value (i.e. by passing -V flag). The returned value implements the logging functions such as Debug(), Debugf(), Info(), Infof() etc.

func (Verbose) Debug

func (v Verbose) Debug(args ...any)

Debug logs to the DEBUG log assumed that the Verbosity v is smaller or equal to the configured min verbosity (see V for more). Arguments are handled in the manner of fmt.Print; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func (Verbose) Debugf

func (v Verbose) Debugf(format string, args ...any)

Debugf logs to the DEBUG log assumed that the Verbosity v is smaller or equal to the configured min verbosity (see V for more). Arguments are handled in the manner of fmt.Printf; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func (Verbose) Error

func (v Verbose) Error(args ...any)

Error logs to the ERROR log assumed that the Verbosity v is smaller or equal to the configured min verbosity (see V for more). Arguments are handled in the manner of fmt.Print; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func (Verbose) Errorf

func (v Verbose) Errorf(format string, args ...any)

Errorf logs to the ERROR log assumed that the Verbosity v is smaller or equal to the configured min verbosity (see V for more). Arguments are handled in the manner of fmt.Printf; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func (Verbose) Info

func (v Verbose) Info(args ...any)

Info logs to the INFO log assumed that the Verbosity v is smaller or equal to the configured min verbosity (see V for more). Arguments are handled in the manner of fmt.Print; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func (Verbose) Infof

func (v Verbose) Infof(format string, args ...any)

Infof logs to the INFO log assumed that the Verbosity v is smaller or equal to the configured min verbosity (see V for more). Arguments are handled in the manner of fmt.Printf; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func (Verbose) Warn

func (v Verbose) Warn(args ...any)

Warn logs to the WARNING log assumed that the Verbosity v is smaller or equal to the configured min verbosity (see V for more). Arguments are handled in the manner of fmt.Print; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

func (Verbose) Warnf

func (v Verbose) Warnf(format string, args ...any)

Warnf logs to the WARNING log assumed that the Verbosity v is smaller or equal to the configured min verbosity (see V for more). Arguments are handled in the manner of fmt.Printf; New line adding is handled by each backend and will be added when it makes sense considering the backend context.

Jump to

Keyboard shortcuts

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