GoVector is a vector clock logging library written in Go.



Build Status GoDoc Go Report Card License: MIT Coverage Status

GoVector is a vector clock logging library written in Go. The vector clock algorithm is used to order events in distributed systems in the absence of a centralized clock. GoVector implements the vector clock algorithm and provides feature-rich logging and encoding infrastructure.

Vector clock events are generated using 3 key functions, PrepareSend, UnpackReceive, and LogLocalEvent. PrepareSend encodes messages for network transport, updates GoVectors local time, and logs a sending event. UnpackReceive decodes messages from the network, merges GoVectors local clock with the received clock, and logs a receiving event. LogLocalEvent event ticks the clock, and logs a message.

This library can be added to a Go project to generate a ShiViz-compatible vector-clock timestamped log of events in a concurrent or distributed system. This library can also be used to generate TSViz-compatible log of events. GoVector is compatible with Go 1.11+ and requires support for Go modules.

  • govec/ : Contains the Library and all its dependencies
  • govec/vclock : Pure vector clock library
  • govec/vrpc : Go's rpc with GoVector integration
  • example/ : Contains some examples instrumented with different features of GoVector


To install GoVector you must have a correctly configured go development environment. See How to Write Go Code.

Once you set up your environment, GoVector can be installed with the go tool command:

$ go get -u


The following is a basic example of how this library can be used:

package main

import ""

func main() {
    // Initialize GoVector logger
    logger := govec.InitGoVector("MyProcess", "LogFile", govec.GetDefaultConfig())

    // Encode message, and update vector clock
    messagePayload := []byte("sample-payload")
    vectorClockMessage := logger.PrepareSend("Sending Message", messagePayload, govec.GetDefaultLogOptions())

    // Send message

    // In Receiving Process

    // Decode message, and update local vector clock with received clock
    logger.UnpackReceive("Receiving Message", vectorClockMessage, &messagePayload, govec.GetDefaultLogOptions())

    // Log a local event
    logger.LogLocalEvent("Example Complete", govec.GetDefaultLogOptions())

For complete documentation with examples see GoVector's GoDoc.

End-to-End Examples

Generating ShiViz/TSViz compatible logs

By default, when you download the GoVector package using the go get command, the command installs a binary of the to-level file govec.go by the name of GoVector in the directory $GOPATH/bin. As long as this directory is part of your path, you can run the GoVector binary to generate a ShiViz or TSViz compatible log from all the logs in a given directory.

Note: Make sure that you are running the GoVector binary on a directory that contains log files from the same execution of the system. If it contains logs from multiple executions, then ShiViz and TSViz won't be able to interpret the log file.


To generate a ShiViz-compatible log file called hello.log from all log files in the directory path/to/logs do the following:

$ GoVector --log_type shiviz --log_dir path/to/logs --outfile hello.log

Similarly, to generate a TSViz-compatible log file called hello-ts.log from all log files in the directory path/to/logs do the following:

$ GoVector --log_type tsviz --log_dir path/to/logs --outfile hello-ts.log


GoVector was initially developed as a pedagogical tool for UBC's computer science course on distributed systems (CPSC 416). Students new to the development of distributed systems can feed generated logs into ShiViz to visualize their program executions and reason about event orderings. Furthermore, GoVector's marshaling functionality reduces the effort needed to write networking code that is largely boilerplate.

Eventually, as a result of student requests, GoVector has been transformed into a general-purpose logging tool. Additional features include optimized IO, priority logging, TSViz compatibility, and RPC instrumentation.


GoVector has the following dependencies:


  • Ivan Beschastnikh
  • Mike Fink
  • Stewart Grant
  • Clement Fung
  • Fabian Ruffy
  • Vaastav Anand

Output Example

The source code from the usage example produces the following log into a file named "LogFile.txt":

MyProcess {"MyProcess":1}
Initialization Complete
MyProcess {"MyProcess":2}
Sending Message
MyProcess {"MyProcess":3}
Receiving Message
MyProcess {"MyProcess":4}
Example Complete

Here is a sample output of the priority logger: PriorityLoggerOutput.png

Here is an example of ShiViz output generated by an RPC client server interaction: ShivizExample.png

  • Import issue

    Import issue

    I can't import GoVector into the project and keep getting error where it is looking for

    GoVector/govec/gopublisher.go:10:2: cannot find package "" in any of: /usr/lib/go/src/pkg/ (from $GOROOT) /home/vm/gowork/src/ (from $GOPATH)

    And then the same thing for gopublisher.go and other components. I added GoVector as git submodule to our project and did the import from the root of the project "project/GoVector/govec" where project is root directory of our project. As far as I understand GOROOT needs to be set when you install go into a custom directory, but I haven't. GOPATH is working fine (so far) and is pointing to $HOME/gowork where the project is as well. Should GoVector be installed under $GOPATH as well for this to work? I was trying to make it self contained by having it as submodule.

    Some info:

    • GoVector cloned using git submodule init
    • project is at $GOPATH/src/project
    • GoVector is at $GOPATH/src/project/GoVector
    • the file that's importing GoVector is at $GOPATH/src/project/server
    • import statement "project/GoVector/govec"

    I would really appreciate some help. Might be something I am doing wrong. Thanks.

    opened by sergenikov 6
  • Interface reflection causes crash

    Interface reflection causes crash

    Sending an interface over vrpc causes a crash. For example the following types

    type Operation interface {
    	OperationType() OperationType
    	GetMinerID() string
    	GetFileName() string
    type AppendOperation struct {
    	Timestamp time.Time
    	Filename  string
    	Record    Record
    	RecordNum uint16
    	MinerId   string

    Where we are sending and expecting Operation. This causes deserialization to fail with the following message:

    panic: reflect.Set: value of type map[string]interface {} is not assignable to type blockchain.Operation
    goroutine 5 [running]:
    reflect.Value.assignTo(0x74a1c0, 0xc00040c2d0, 0x15, 0x7b4559, 0xb, 0x75cf60, 0xc0003ee1d0, 0xc00040c2d0, 0x0, 0x0)
    	C:/Go/src/reflect/value.go:2239 +0x453
    reflect.Value.Set(0x75cf60, 0xc0003ee1d0, 0x194, 0x74a1c0, 0xc00040c2d0, 0x15)
    	C:/Go/src/reflect/value.go:1373 +0xae*Decoder).interfaceValue(0xc00029e700, 0x75cf60, 0xc0003ee1d0, 0x194, 0x535792, 0xc00029e700)
    	C:/Users/Denis/go/src/ +0x163, 0x75cf60, 0xc0003ee1d0, 0x194, 0xc0003ee1d0, 0x194)
    	C:/Users/Denis/go/src/ +0x1ea, 0x71eb20, 0xc0003ee1d0, 0x16, 0x71eb20, 0x0)
    	C:/Users/Denis/go/src/ +0xca*Decoder).DecodeValue(0xc00029e700, 0x71eb20, 0xc0003ee1d0, 0x16, 0xc0003ee1d0, 0x16)
    	C:/Users/Denis/go/src/ +0x93, 0x748420, 0xc00040c288, 0x194, 0x748420, 0x749800)
    	C:/Users/Denis/go/src/ +0xaa*Decoder).DecodeValue(0xc00029e700, 0x748420, 0xc00040c288, 0x194, 0xc00040c288, 0x194)
    	C:/Users/Denis/go/src/ +0x93*Decoder).decode(0xc00029e700, 0x7216e0, 0xc00040c288, 0xc0003ea110, 0xe)
    	C:/Users/Denis/go/src/ +0x182*Decoder).Decode(0xc00029e700, 0xc00006f9d0, 0x1, 0x1, 0x0, 0x763718)
    	C:/Users/Denis/go/src/ +0x73*VClockPayload).DecodeMsgpack(0xc00040c270, 0xc00029e700, 0xc00040c270, 0x2b70338)
    	C:/Users/Denis/go/src/ +0xcf, 0x7636e0, 0xc00040c270, 0x16, 0xc00040c270, 0x16)
    	C:/Users/Denis/go/src/ +0x118, 0x772fe0, 0xc00040c270, 0x199, 0x772fe0, 0x452130)
    	C:/Users/Denis/go/src/ +0x7c*Decoder).DecodeValue(0xc00029e700, 0x772fe0, 0xc00040c270, 0x199, 0xc00040c270, 0x199)
    	C:/Users/Denis/go/src/ +0x93*Decoder).decode(0xc00029e700, 0x7636e0, 0xc00040c270, 0x0, 0x40)
    	C:/Users/Denis/go/src/ +0x182*Decoder).Decode(0xc00029e700, 0xc00006fcc8, 0x1, 0x1, 0xc000036000, 0xc00006fcb8)
    	C:/Users/Denis/go/src/ +0x73, 0x52, 0x52, 0xc00006fcc8, 0x1, 0x1, 0x30, 0x772fe0)
    	C:/Users/Denis/go/src/ +0xb1, 0x52, 0x52, 0x7636e0, 0xc00040c270, 0x71eaa0, 0xc0000fe3e0)
    	C:/Users/Denis/go/src/ +0x85*GoLog).UnpackReceive(0xc000108080, 0x7b886f, 0x14, 0xc000286060, 0x52, 0x52, 0x71eb20, 0xc0003ee1d0, 0x1)
    	C:/Users/Denis/go/src/ +0x102*RPCServerCodec).ReadRequestBody(0xc000202080, 0x71eb20, 0xc0003ee1d0, 0x71eb20, 0xc0003ee1d0)
    	C:/Users/Denis/go/src/ +0xee
    net/rpc.(*Server).readRequest(0xc0000943c0, 0x814ea0, 0xc000202080, 0xc00003c360, 0xc00003c3c0, 0xc00042df88, 0x6f897a, 0x5040408, 0xc0000524a0, 0x20, ...)
    	C:/Go/src/net/rpc/server.go:569 +0x299
    net/rpc.(*Server).ServeCodec(0xc0000943c0, 0x814ea0, 0xc000202080)
    	C:/Go/src/net/rpc/server.go:465 +0x9e
    created by
    	C:/Users/Denis/go/src/ +0xb6

    This likely because under the hood go might be serializing the interface as a map.

    opened by dtrailin 5
  • Add ability to buffer writes to the Log file

    Add ability to buffer writes to the Log file

    Currently govector Logger doesn't have the ability to buffer writes to the associated Log file and opens/writes/closes to the file at every event. File IO is expensive and this makes the govector Logger pretty much impossible to work with applications/protocols that require low latency (eg: real time game).

    This PR adds the ability to enable/disable buffered writes for the logger and passes this control to the user of the Logger.

    opened by vaastav 4
  • RPC Codecs for automatically capturing RPC messages

    RPC Codecs for automatically capturing RPC messages

    This PR adds custom RPC Codecs and convenience functions which use a govector logger to automatically capture all RPC Calls made by the client and the responses by the server.

    opened by vaastav 3
  • Don't Log flag?

    Don't Log flag?


    Say I am very pleased with the logging and believe everything works perfectly. I don't want to change my code but I now longer want to log large number of files for my system.

    Is there a method/flag in the library to disable logging completely? I see there are some to print out the logging to the screen, but none to disable.

    opened by Neo-X 3
  • Fixed bug in VClock.Compare and added tests for this method

    Fixed bug in VClock.Compare and added tests for this method

    As attributed to in the TODO comment by cfung on lines 92-96 of vclock_test.go, there was indeed a bug in the VClock.Compare method. The method as is would not detect all concurrent clocks, as it was premature to return false in lines 161-163 and 172-174 of the original code.

    I corrected the method, uncommented the test commented out by cfung and added several new tests to vclock_test.go to comprehensively check the VClock.Compare method. All tests pass.

    opened by savreline 2
  • Goreport


    I just ran gofmt and changed some variable names to make the linter happy. I figured that now that we have more than 100 stars we should try and keep the A+

    opened by wantonsolutions 2
  • Update example snippet in

    Update example snippet in

    In the example snippet available in the file, the parameters passed to UnpackReceive do not seem to match the signature of the function currently available in the API (the order of buf []byte, unpack interface{} is inverted). It also looks like for all of PrepareSend,UnpackReceive and LogLocalEvent a GoLogOptions value is required in all calls.

    opened by agottardo 2
  • nil pointer dereference when calling PrepareToSend(..)

    nil pointer dereference when calling PrepareToSend(..)

    Code I am using:

    package main
    import (
    func main() {
    	LoggerClient := govec.InitGoVectorMultipleExecutions("2", "test")
    	LoggerClient.PrepareSend("Sending", "blabla")

    Problem: I get the following error

    panic: runtime error: invalid memory address or nil pointer dereference
    [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x12dd1ad]
    goroutine 1 [running]:*GoLog).PrepareSend(0xc420134100, 0x1393dde, 0x7, 0x1316880, 0x13d6600, 0x0, 0xc420125f70, 0x12de28e)
            /Users/annygakh/go/src/ +0x25d
            /Users/annygakh/go/src/test-shiviz/test.go:12 +0x93
    exit status 2

    Possible fix: It seems like there is missing initialization of private fields gv.encodingStrategy (and gv.decodingStrategy). The fields are initialized in InitGoVector, but not in InitGoVectorMultipleExecutions (which is what I am using). Attached is a proposed fix.


    opened by annygakh 2
  • Bug on vclock.Compare()

    Bug on vclock.Compare()

    Method vclock have been implmented again to solve bug when comparing two concurrent vclocks. More tests for vclock.COmpare method have also been implemented for validation. The new method is more inefficient with large vectors.

    opened by mariuscrsn 1
  • Remove capture library.

    Remove capture library.

    This removes the circular dependency between dinv and Govector. This library should really live inside the Dinv repository as it explicitly uses Dinv's Pack and Unpack for logging vector clock timestamps and events.

    opened by vaastav 1
  • Make ReturnVCString Deterministic

    Make ReturnVCString Deterministic

    Currently when getting the string representation for a vector clock, you will get a non-deterministic order of keys and values. The reason is that ranging over a map in Go gives you its keys in a random order. Nevertheless, the current implementation of ReturnVCString in the vclock package relies on ranging over the keys to sort the output (note that the comment is from the original code):

    ids := make([]string, len(vc))
    i := 0
    for id := range vc {
    	ids[i] = id

    So I'm assuming that non-deterministic output is a bug and not intentional.
    For some use-cases (notably: my use-case 🙂), this can be problematic. My proposal is to add an additional sort.Strings(ids) step before using the array of keys so that iff v1 == v2 => v1.ReturnVCString() == v2.ReturnVCString(). This should prevent any further surprises.

    There is a performance overhead but I find it negligible. For a vector clock with 100 entries (quite large):

    goos: darwin
    goarch: amd64
    cpu: Intel(R) Core(TM) i5-8210Y CPU @ 1.60GHz
    BenchmarkVCString-4         	   28614	     40648 ns/op
    BenchmarkVCStringSorted-4   	   20901	     57339 ns/op
    ok	3.386s

    (This benchmark is not included in this PR, just illustrative.)
    0.017ms is acceptable, although that difference is grows or shrinks with the size of the clock.

    opened by pfandzelter 0
  • Added support for message broadcast via RPC

    Added support for message broadcast via RPC

    Here are the changes that allow to broadcast messages via RPC with the same vector clock. An end-to-end example has been added in example/RpcBroadcast/RpcBroadcast.go and the ShiViz output of this example in .images/shiviz_broadcast.png. The example and ShiViz output has been linked from the README. Also, a quick smoke test has been added to govec_test.go.

    The changes are only really needed to enable broadcasting within the RPC framework, as if RPCs are not used, the end-user has full control to call GoLog.PrepareSend just once per several calls to conn.Write. On the other hand, when using RPCs, calls to GoLog.PrepareSend are automatically made on each RPC call and automatically tick the clock several times.

    opened by savreline 1
  • Little Code Error

    Little Code Error


    I've used this library in college for a little proyect and all the teammates I meet had the same problem I had.

    In the govec program, inside the govec folder, line 208 has a bug where you passed 3 arguments to the function dec.Decode(). An error pop up saying how it's supposed to be and, actually, in the line 183 is correctly used. So i changed it to err = dec.Decode(&d.Payload) and it works.

    I see is an easy fix, but using an IDE (for example Goland) it warns you and tries to prevent you from changing any file that is an external library. Maybe, for an even more amateur programmer than me, this could be the end of the work for a while.

    opened by DiegoCCMM 0
  • Mocking Library for Log Outputs

    Mocking Library for Log Outputs

    We need to test the outputs written to Log files. This would involve creating a mock library that can capture and test the outputs written to the Log File.

    Something like this:

    opened by clementfung 0
  • In pubmanager.go registerPublisher should return an error

    In pubmanager.go registerPublisher should return an error

    if registerPublisher tries to register a nonce that already exists it should return an error to be dealt with in setupPubManagerTCP, otherwise the pubmanager will be shutdown for all potential new publishers.

    bug priority 1 broker 
    opened by mikegfink 0
  • v1.0(Oct 1, 2018)

    GoVector is a vector clock logging library written in Go. The vector clock algorithm ( is used to order events in distributed systems in the absence of a centralized clock. GoVector implements the vector clock algorithm and provides feature-rich logging and encoding infrastructure.

    GoVector is one of the libraries provided as part of the Distributed Clocks project ( which also provides vector clock logging libraries written in C++, C, and Java.

    The logs produced by GoVector are compatible with log analysis tools like ShiViz ( and TSViz ( which visualize the aggregated logs of the entire system as a time-space diagram.

    Source code(tar.gz)
    Source code(zip)
Distributed clocks
Distributed clocks
A simple digital clock written in go to show time in hh : mm : ss format in console

Go console clock a simple digital clock written in go to show time in "hh : mm :

Mojtaba Khodami 0 Feb 3, 2022
Gomol is a library for structured, multiple-output logging for Go with extensible logging outputs

gomol Gomol (Go Multi-Output Logger) is an MIT-licensed structured logging library for Go. Gomol grew from a desire to have a structured logging libra

Kristin Davidson 18 Dec 20, 2021
Simple text-line analog clock

anaclock anaclock prints a simple analog clock as a line of text. Demo $ anaclock 23 . : .| 00 anaclock is easy to use in CLI prompts or anywhere

null 0 Dec 31, 2021
A simple logging module for go, with a rotating file feature and console logging.

A simple logging module for go, with a rotating file feature and console logging. Installation go get Usage Sample usage W

Juan B. Rodriguez 25 Jun 11, 2022
FactorLog is a logging infrastructure for Go that provides numerous logging functions for whatever your style may be

FactorLog FactorLog is a fast logging infrastructure for Go that provides numerous logging functions for whatever your style may be. It could easily b

Kevin Darlington 54 Oct 12, 2021
Package logging implements a logging infrastructure for Go

Golang logging library Package logging implements a logging infrastructure for Go. Its output format is customizable and supports different logging ba

Luke Zhang 0 Nov 10, 2021
Generate vector tiles for the entire planet on relatively low spec hardware.

Sequentially Generate Planet Mbtiles Sequentially generate and merge an entire planet.mbtiles vector tileset on low memory/power devices for free. com

Jack Bizzell 18 Jun 24, 2022
The Simplest and worst logging library ever written

gologger A Simple Easy to use go logger library. Displays Colored log into console in any unix or windows platform. You can even store your logs in fi

Sadlil Rhythom 41 Jun 22, 2022
LogVoyage - logging SaaS written in GoLang

No longer maintained, sorry. Completely rewritten v2 is going to be released soon. Please follow LogVoyage - fast and simp

null 91 Apr 21, 2022
A reusable logger module for basic logging, written in Go

logger A reusable logger module for basic logging, written in Go. Usage Client p

Praveen Ravichandran 1 Jan 8, 2022
Simple and blazing fast lockfree logging library for golang

glg is simple golang logging library Requirement Go 1.11 Installation go get Example package main import ( "net/http" "time"

Yusuke Kato 161 Jul 2, 2022
Logging library for Golang

GLO Logging library for Golang Inspired by Monolog for PHP, severity levels are identical Install go get Severity levels Deb

Lajos Bencz 14 Aug 26, 2021
Minimalistic logging library for Go.

logger Minimalistic logging library for Go. Blog Post Features: Advanced output filters (package and/or level) Attributes Timers for measuring perform

Azer Koçulu 153 Jun 29, 2022
Seelog is a native Go logging library that provides flexible asynchronous dispatching, filtering, and formatting.

Seelog Seelog is a powerful and easy-to-learn logging framework that provides functionality for flexible dispatching, filtering, and formatting log me

Seelog project repository 1.6k Jun 30, 2022
A pure Go contextual logging library with "batteries included"

Cue Overview Cue implements contextual logging with "batteries included". It has thorough test coverage and supports logging to stdout/stderr, file, s

Bob Ziuchkovski 26 Sep 16, 2019
Golang logging library

Golang logging library Package logging implements a logging infrastructure for Go. Its output format is customizable and supports different logging ba

Örjan Fors 1.8k Jun 23, 2022
Hierarchical, leveled, and structured logging library for Go

spacelog Please see for info License Copyright (C) 2014 Space Monkey, Inc. Licensed under the Apach

Space Monkey Go 98 Apr 27, 2021
Minimal structured logging library for Go

slog slog is a minimal structured logging library for Go. Install go get Features Minimal API First class context.Context support First c

Coder 242 Jul 4, 2022
Parametrized JSON logging library in Golang which lets you obfuscate sensitive data and marshal any kind of content.

Noodlog Summary Noodlog is a Golang JSON parametrized and highly configurable logging library. It allows you to: print go structs as JSON messages; pr

Gyoza Tech 37 Apr 19, 2022