govec

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2025 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package govec is a vector clock logging library

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// LogToTerminal controls whether internal GoLog debugging statements are printed to stdout. False by default
	LogToTerminal = false
)

Functions

func NewNopCore

func NewNopCore() zapcore.Core

NewNopCore returns a no-op Core. Copy of zap's but enable returns true instead of false

Types

type GoLog

type GoLog struct {

	// Embedded Zap logger to pass all logs to
	*zap.Logger

	// Cached loggers derived from the embedded Zap logger.
	// Wrapped loggers are used to skip different levels of the stacktrace so only user
	// code appears in the stacktrace
	SugaredLogger *zap.SugaredLogger
	// contains filtered or unexported fields
}

GoLog struct provides an interface to creating and maintaining vector timestamp entries in the generated log file. GoLogs are initialized with Configs which control logger output, format, and frequency.

Example (Basic)

Basic example of GoVectors key functions

package main

import (
	"fmt"

	"github.com/jmcmenamy/GoVector/govec"
)

func main() {
	//Initialize logger with default configuration. This can be done in
	//a var block to ensure that GoVector is initialized at boot time.
	Logger := govec.InitGoVector("MyProcess", "LogFile", govec.GetDefaultRegexConfig())
	opts := govec.GetDefaultLogOptions()

	//An example message
	messagepayload := []byte("samplepayload")

	//Prior to sending a message, call PrepareSend on the payload to
	//encode the payload and append this processes vector clock to the
	//payload
	encodedVCpayload := Logger.PrepareSend("Sending Message", messagepayload, opts)

	//encodedVCpayload is ready to be written to the network
	//ex) conn.Write(encodedVCpayload)

	//Receiving Example
	//First allocate a buffer to receive a message into. This must be
	//the same type as the encoded message. Here incommingMessage and
	//messagepayload are the same type []byte.
	var incommingMessage []byte

	//Prior to unpacking call a message must be received
	//ex) conn.Read(encodedVCPayload)

	//Call UnpackReceive on received messages to update local vector
	//clock values, and decode the original message.
	Logger.UnpackReceive("Received Message from server", encodedVCpayload, &incommingMessage, opts)
	fmt.Printf("Received Message: %s\n", incommingMessage)

	//Important local events can be timestamped with vector clocks
	//using LogLocalEvent, which also increments the local clock.
	Logger.LogLocalEvent("Example Complete", opts)

}
Output:

Received Message: samplepayload
Example (DisVizCompatible)

GoVector logs can produce JSON logs for visualization with DisViz

package main

import (
	"fmt"

	"github.com/jmcmenamy/GoVector/govec"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

func main() {
	//Initialize logger with default zap configuration. This can be done in
	//a var block to ensure that GoVector is initialized at boot time.
	Logger := govec.InitGoVector("MyProcess", "LogFile", govec.GetDefaultZapConfig())

	//An example message
	messagepayload := []byte("samplepayload")

	//Prior to sending a message, call PrepareSendZapWrapPayload on the payload to
	//encode the payload and append this processes vector clock to the
	//payload. This will wrap messagepayload inside encodedVCpayload
	encodedVCpayload := Logger.PrepareSendZapWrapPayload("Sending Message", messagepayload, zapcore.InfoLevel, zap.Int("messageNum", 1))

	//encodedVCpayload is ready to be written to the network
	//ex) conn.Write(encodedVCpayload)

	//Receiving Example
	//First allocate a buffer to receive a message into. This must be
	//the same type as the encoded message. Here incommingMessage and
	//messagepayload are the same type []byte.
	var incommingMessage []byte

	//Prior to unpacking call a message must be received
	//ex) conn.Read(encodedVCPayload)

	//Call UnpackReceiveZapWrapPayload on received messages to update local vector
	//clock values, and decode the original message.
	Logger.UnpackReceiveZapWrapPayload("Received Message from server", encodedVCpayload, &incommingMessage, zapcore.InfoLevel)
	fmt.Printf("Received Message: %s\n", incommingMessage)

	//Important local events can be timestamped with vector clocks
	//using LogLocalEvent, which also increments the local clock.
	Logger.LogLocalEventZap(zapcore.InfoLevel, "Example Complete")

	//The Zap API is also embedded in the GoLog object, so all Zap methods can also be called
	Logger.Info("Example Complete", zap.Bool("boolField", false))

	//Instead of wrapping the user payload inside the GoLog payload,
	//PrepareSendZap/UnpackReceiveZap can be used to put the GoLog payload inside the user payload
	//that is sent over the network.
	type samplePayload struct {
		encodedVCPayload []byte
	}

	payloadToSend := samplePayload{
		encodedVCPayload: Logger.PrepareSendZap("Sending Message", zapcore.InfoLevel, zap.String("stringField", "value")),
	}

	//payloadToSend is ready to be encoded, written to the network, then decoded by another device.

	//Then, we can grab the GoLog payload out of the decoded user payload.
	Logger.UnpackReceiveZap("Received Message from server", payloadToSend.encodedVCPayload, zapcore.InfoLevel)

}
Output:

Received Message: samplepayload
Example (Priority)

Logging with priority trims all events which are lower from the specified priority from the log. This functionality is useful for isolating behaviour such as recovery protocols, from common behaviour like heartbeats.

package main

import (
	"github.com/jmcmenamy/GoVector/govec"
	"go.uber.org/zap/zapcore"
)

func main() {
	//Access GoVectors default configureation, and set priority
	config := govec.GetDefaultRegexConfig()
	config.Level = zapcore.DebugLevel
	config.PrintOnScreen = true
	//Initialize GoVector
	Logger := govec.InitGoVector("MyProcess", "PrioritisedLogFile", config)
	opts := govec.GetDefaultLogOptions()

	Logger.LogLocalEvent("Debug Priority Event", opts.SetPriority(zapcore.DebugLevel))
	Logger.LogLocalEvent("Info Priority Event", opts.SetPriority(zapcore.InfoLevel))
	Logger.LogLocalEvent("Warning Priority Event", opts.SetPriority(zapcore.WarnLevel))
	Logger.LogLocalEvent("Error Priority Event", opts.SetPriority(zapcore.ErrorLevel))
	Logger.LogLocalEvent("Fatal Priority Event", opts.SetPriority(zapcore.FatalLevel))

	//BUG Output contains timestamps so it cant be tested with *******
	//comments
	//Debug Priority Event
	//Info Priority Event
	//Warning Priority Event
	//Error Priority Event
	//Fatal Priority Event
}
Example (TSVizCompatable)

GoVector logs can be used to associate real time events for visualization with TSViz

package main

import (
	"fmt"

	"github.com/jmcmenamy/GoVector/govec"
)

func main() {
	//Access config and set timestamps (realtime) to true
	config := govec.GetDefaultRegexConfig()
	config.UseTimestamps = true
	//Initalize GoVector
	Logger := govec.InitGoVector("MyProcess", "LogFile", config)
	opts := govec.GetDefaultLogOptions()

	//In Sending Process

	//Prepare a Message
	messagepayload := []byte("samplepayload")
	finalsend := Logger.PrepareSend("Sending Message", messagepayload, opts)
	//In Receiving Process

	//receive message
	var incommingMessage []byte
	Logger.UnpackReceive("Received Message from server", finalsend, &incommingMessage, opts)
	fmt.Printf("Received Message: %s\n", incommingMessage)
	//Can be called at any point
	Logger.LogLocalEvent("Example Complete", opts)

}
Output:

Received Message: samplepayload

func InitGoVector

func InitGoVector(processid string, logfilename string, config GoLogConfig) *GoLog

InitGoVector returns a GoLog which generates a logs prefixed with processid, to files with names logfilenames, appended with a -Log.txt or -zap-Log.txt. Any old log with the same name will be truncated for non-zap logs. zap logs will be parsed and used to initialize the vector clock Config controls logging options. See GoLogConfig for more details.

func UninitializedGoVector

func UninitializedGoVector() *GoLog

Creates an Uninitialized GoLog that can still be logged to with zap logs Logs are buffered and will be logged immediately once this logger is initialized and output paths are given

func (*GoLog) DisableBufferedWrites

func (gv *GoLog) DisableBufferedWrites() (err error)

DisableBufferedWrites disables buffered writes to the log file. All the log messages from now on will be written to the Log file immediately. Writes all the existing log messages that haven't been written to Log file yet.

func (*GoLog) EnableBufferedWrites

func (gv *GoLog) EnableBufferedWrites() (err error)

EnableBufferedWrites enables buffered writes to the log file. All the log messages are only written to the LogFile via an explicit call to the function Flush. Note: Buffered writes are automatically disabled.

func (*GoLog) Flush

func (gv *GoLog) Flush() bool

Flush writes the log messages stored in the buffer to the Log File. This function should be used by the application to also force writes in the case of interrupts and crashes. Note: Calling Flush when BufferedWrites is disabled is essentially a no-op. Only to be used for regex style logging; no op for zap style logging

func (*GoLog) GetCurrentVC

func (gv *GoLog) GetCurrentVC() vclock.VClock

GetCurrentVC returns the current vector clock

func (*GoLog) InitGoVector

func (gv *GoLog) InitGoVector(processid string, config GoLogConfig, logfilenames ...string)

InitGoVector returns a GoLog which generates a logs prefixed with processid, to files with names logfilenames, appended with a -Log.txt or -zap-Log.txt. Any old log with the same name will be truncated for non-zap logs. zap logs will be parsed and used to initialize the vector clock Config controls logging options. See GoLogConfig for more details.

func (*GoLog) LogLocalEvent

func (gv *GoLog) LogLocalEvent(mesg string, opts GoLogOptions) (logSuccess bool)

LogLocalEvent implements LogLocalEvent with priority levels. If the priority of the logger is lower than or equal to the priority of this event then the current vector timestamp is incremented and the message is logged it into the Log File. A color coded string is also printed on the console. * LogMessage (string) : Message to be logged * Priority (LogPriority) : Priority at which the message is to be logged

func (*GoLog) LogLocalEventZap

func (gv *GoLog) LogLocalEventZap(level zapcore.Level, msg string, fields ...zap.Field)

Ticks the clock and logs the given msg and fields and level level If the zap logger isn't initialized yet, store the entry for logging later

func (*GoLog) Named

func (gv *GoLog) Named(s string) *GoLog

Named adds a new path segment to the logger's name. Segments are joined by periods. By default, Loggers are unnamed.

func (*GoLog) PrepareSend

func (gv *GoLog) PrepareSend(mesg string, buf interface{}, opts GoLogOptions) (encodedBytes []byte)

PrepareSend is meant to be used immediately before sending. mesg will be logged buf is encode-able data (structure or basic type) Returned is an encoded byte array with logging information. This function is meant to be called before sending a packet. It updates the Vector Clock for its own process, packages with the clock using gob support and returns the new byte array that should be sent onwards over the network

func (*GoLog) PrepareSendZap

func (gv *GoLog) PrepareSendZap(mesg string, level zapcore.Level, fields ...zap.Field) (encodedBytes []byte)

PrepareSendZap is meant to be used immediately before sending. mesg will be logged Returned is an encoded byte array with logging information. This function is meant to be called before sending a packet. It updates the Vector Clock for its own process, and returns the byte array that should be placed in the payload sent over the network.

func (*GoLog) PrepareSendZapWrapPayload

func (gv *GoLog) PrepareSendZapWrapPayload(mesg string, buf interface{}, level zapcore.Level, fields ...zap.Field) (encodedBytes []byte)

PrepareSendZapWrapPayload is meant to be used immediately before sending. mesg will be logged buf is encode-able data (structure or basic type) buf is encoded inside of encodedBytes Returned is an encoded byte array with logging information. This function is meant to be called before sending a packet. It updates the Vector Clock for its own process, packages buf with the clock using gob support and returns the new byte array that should be sent onwards over the network.

func (*GoLog) StartBroadcast

func (gv *GoLog) StartBroadcast(mesg string, opts GoLogOptions)

StartBroadcast allows to use vector clocks in the context of casual broadcasts sent via RPC. Any call to StartBroadcast must have a corresponding call to StopBroadcast, otherwise a deadlock will occur. All RPC calls made in-between the calls to StartBroadcast and StopBroadcast will be logged as a single event, will be sent out with the same vector clock and will represent broadcast messages from the current process to the process pool.

func (*GoLog) StopBroadcast

func (gv *GoLog) StopBroadcast()

StopBroadcast is called once all RPC calls of a message broadcast have been sent.

func (*GoLog) UnpackReceive

func (gv *GoLog) UnpackReceive(mesg string, buf []byte, unpack interface{}, opts GoLogOptions)

UnpackReceive is used to unmarshall network data into local structures. mesg will be logged the vector clock of this process will be merged with the vector clock received in the payload buf is the network data, previously packaged by PrepareSend. unpack is a pointer to a structure, the same as was packed by PrepareSend. This function is meant to be called immediately after receiving a packet. It unpacks the data by the program, the vector clock. It updates vector clock and logs it. and returns the user data

func (*GoLog) UnpackReceiveZap

func (gv *GoLog) UnpackReceiveZap(mesg string, buf []byte, level zapcore.Level, fields ...zap.Field)

UnpackReceiveZap is used to unmarshall network data into local structures. mesg will be logged the vector clock of this process will be merged with the vector clock received in the payload buf is the network data, previously packaged by PrepareSendZap. unpack is a pointer to a structure, the same as was packed by PrepareSendZap. This function is meant to be called immediately after receiving a packet. It unpacks the data by the program, the vector clock. It updates vector clock and logs it. and returns the user data

func (*GoLog) UnpackReceiveZapWrapPayload

func (gv *GoLog) UnpackReceiveZapWrapPayload(mesg string, buf []byte, unpack interface{}, level zapcore.Level, fields ...zap.Field)

UnpackReceiveZapWrapPayload is used to unmarshall network data into local structures. mesg will be logged the vector clock of this process will be merged with the vector clock received in the payload buf is the network data, previously packaged by PrepareSendZapWrapPayload. unpack is a pointer to a structure, the same as was packed by PrepareSendZapWrapPayload. This function is meant to be called immediately after receiving a packet. It unpacks the data by the program, the vector clock. It updates vector clock and logs it. and returns the user data

func (*GoLog) With

func (gv *GoLog) With(fields ...zap.Field) *GoLog

With creates a child logger and adds structured context to it. Fields added to the child don't affect the parent, and vice versa. Any fields that require evaluation (such as Objects) are evaluated upon invocation of With.

func (*GoLog) WithLazy

func (gv *GoLog) WithLazy(fields ...zap.Field) *GoLog

WithLazy creates a child logger and adds structured context to it lazily.

The fields are evaluated only if the logger is further chained with [With] or is written to with any of the log level methods. Until that occurs, the logger may retain references to objects inside the fields, and logging will reflect the state of an object at the time of logging, not the time of WithLazy().

WithLazy provides a worthwhile performance optimization for contextual loggers when the likelihood of using the child logger is low, such as error paths and rarely taken branches.

Similar to [With], fields added to the child don't affect the parent, and vice versa.

func (*GoLog) WithOptions

func (gv *GoLog) WithOptions(opts ...zap.Option) *GoLog

WithOptions clones the current Logger, applies the supplied Options, and returns the resulting Logger. It's safe to use concurrently.

func (*GoLog) WrapBaseZapLogger

func (gv *GoLog) WrapBaseZapLogger(baseLogger *zap.Logger, opts ...zap.Option) *zap.Logger

Given an existing zap Logger, return a new zap logger that will keep the same configuration, but also write any logs to this GoLog logger the level of the core of this logger will be the level of gv

type GoLogConfig

type GoLogConfig struct {
	// Buffered denotes if the logging events are buffered until flushed. This option
	// increase logging performance at the cost of safety.
	Buffered bool
	// PrintOnScreen denotes if logging events are printed to screen.
	PrintOnScreen bool
	// AppendLog determines to continue writing to a log from a prior execution.
	AppendLog bool
	// UseTimestamps determines to log real time timestamps for TSVis
	UseTimestamps bool
	// EncodingStrategy for customizable interoperability
	EncodingStrategy func(interface{}) ([]byte, error)
	// DecodingStrategy for customizable interoperability
	DecodingStrategy func([]byte, interface{}) error
	// LogToFile determines to write logging events to a file
	LogToFile bool
	// Level determines the minimum priority event to log
	Level zapcore.Level
	// AddCaller determines to add caller information to each log. For Zap logs only.
	AddCaller bool
	// AddStacktrace determines to add the stacktrace to each log. For Zap logs only.
	AddStacktrace bool
	// When buffering, the maximum amount of data the writer will buffer before flushing
	Size int
	// When buffering, how often the writer should flush data if there have been no writes. 0 if only manual Syncing
	Interval time.Duration
	// InitialVC is the initial vector clock value, nil by default
	InitialVC vclock.VClock
	// Whether or not to generate logs with zap, which supports arbitrary key value pairs
	GenerateZapLogs bool
	// Whether or not to generate logs using regex style, compatible with the original Shiviz
	GenerateRegexLogs bool
	// Prefix to add to zap log paths for where to write files. Empty is fine
	ZapLogPrefix string
}

GoLogConfig controls the logging parameters of GoLog and is taken as input to GoLog initialization. See defaults in GetDefaultZapConfig or GetDefaultRegexConfig.

func GetDefaultRegexConfig

func GetDefaultRegexConfig() GoLogConfig

GetDefaultRegexConfig returns the default GoLogConfig with default values for various fields.

func GetDefaultZapConfig

func GetDefaultZapConfig() GoLogConfig

GetDefaultZapConfig returns the default GoLogConfig with default values for various fields when generating logs with Zap

type GoLogCore

type GoLogCore struct {
	zapcore.Core
	// contains filtered or unexported fields
}

GoLogCore wraps an existing zapcore.Core and intercepts writes, to add a pid and vector clock to every log entry

func (*GoLogCore) Check

Have to overwrite method and copy implementation so our GoLogZapCore receiver is used instead of zapcore.ioCore when adding a core to a checkedEntry Check determines whether the supplied Entry should be logged (using the embedded LevelEnabler and possibly some extra logic). If the entry should be logged, the Core adds itself to the CheckedEntry and returns the result.

Callers must use Check before calling Write.

func (*GoLogCore) With

func (c *GoLogCore) With(fields []zapcore.Field) zapcore.Core

With adds structured context to the Core. Return copy of this core where fields will be added to every log to the GoLog and the base logger

func (*GoLogCore) Write

func (c *GoLogCore) Write(entry zapcore.Entry, fields []zapcore.Field) error

Write entry with fields to this core, and pass write through to base wrapped core Write serializes the Entry and any Fields supplied at the log site and writes them to their destination.

If called, Write should always log the Entry and Fields; it should not replicate the logic of Check.

type GoLogOptions

type GoLogOptions struct {
	// The Log priority for this event
	Priority zapcore.Level
}

GoLogOptions provides logging parameters for individual logging statements. Used in Regex logs only.

func GetDefaultLogOptions

func GetDefaultLogOptions() GoLogOptions

GetDefaultLogOptions returns the default GoLogOptions with default values for the fields

func (*GoLogOptions) SetPriority

func (o *GoLogOptions) SetPriority(Priority zapcore.Level) GoLogOptions

SetPriority returns a new GoLogOptions object with its priority field set to Priority. Follows the builder pattern. Priority : (GoLogPriority) The Priority that the new GoLogOptions object must have

type GoLogWriteSyncer

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

GoLogWriteSyncer lets you flip between an unbuffered and a buffered write syncer.

func NewGoLogWriteSyncer

func NewGoLogWriteSyncer(unbuf zapcore.WriteSyncer) *GoLogWriteSyncer

Create a new GoLogWriteSyncer, which eventually writes to unbuf. Initially unbuffered

func (*GoLogWriteSyncer) DisableBuffering

func (s *GoLogWriteSyncer) DisableBuffering() (err error)

DisableBuffering switches back to the unbuffered writer Syncs any data in the existing buf

func (*GoLogWriteSyncer) EnableBuffering

func (s *GoLogWriteSyncer) EnableBuffering(size int, interval time.Duration) error

EnableBuffering switches over to the buffered writer size is the maximum amount of data the writer will buffered before flushing. interval is how often the writer should flush data if there have been no writes. 0 if only manual Syncing

func (*GoLogWriteSyncer) Sync

func (s *GoLogWriteSyncer) Sync() error

Sync calls the Sync method of the currently active Zap WriteSyncer

func (*GoLogWriteSyncer) Write

func (s *GoLogWriteSyncer) Write(p []byte) (int, error)

Write calls the Write method of the currently active Zap WriteSyncer

type ZapEntryInput

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

Represents an entry that we log later, once the zap logger is initialized

type ZapLogInput

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

Represents a log that we try to log later, once the zap logger is initialized

Directories

Path Synopsis
Package vrpc provides support for automatically logging RPC Calls from a RPC Client to a RPC Server
Package vrpc provides support for automatically logging RPC Calls from a RPC Client to a RPC Server

Jump to

Keyboard shortcuts

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