yet another golang logging library
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


An idiomatic and simple go logger.


Some alternative packages:

Neither of the builtin options support standard log levels.

All three of these solutions override application behavior, forcing os.Exit() or Panic().

The complexity surrounding embedding syslog into the logger, which creates a network dependency and forces New() syntax, are a pungent code smell that does not easily cross platforms.

There are over 1000 lines of code in go-logging, not counting the tests.

sales pitch

If you can read my source at-a-glance then my work is done.

Easy to read code is also easy to use and implement, and boosts confidence in stability.

This library:

  • provides standard log levels
  • uses the ever-flexible stderr
  • prints messages in standard syslog format
  • utilizes sync.Mutex for thread safe execution
  • includes file name and line numbers for debugging
  • supplies idiomatic go initialization (eg. l := glog.Logger{})
  • has configurable severity controlled via LOG_LEVEL environment variable
  • omits transient dependencies (only a minimal set of standard library packages)
  • totals 345 lines of code (including comments, unit tests, and benchmarks)
  • detects compatible terminals and automatically applies color to message prefixes

While this use-case seems like a perfect fit for channels, numerous benchmarks have indicated that a sync.Mutex provides superior performance.

Eliminating severity configuration from the application developer domain is surprisingly wonderful for everybody (eg. no longer worry about -v, -vv, -vvv, -d, -s, -q, --verbose, --debug, --silent, or --quiet).


Install it:

go get

Import it:

import ""

Create a new logger instance:

logger := glog.Logger{}

The severity of messages defaults to Error, and can be set using LOG_LEVEL as an environment variable string matching the supported severities (including silent).

Format your own messages with any data types synchronously or with goroutines:

logger.Info("message %v", object)
go logger.Debug("message %v", object)

Keep in mind goroutines are cheap but not free; if you have bursty traffic such as a web application this may work, but real-time applications with a tight loop may simply accrue memory and cpu debt.


Let's say you have some structure like this:

type Configuration struct {
	Port     int
	Address  string
	Username string
	Password string

You may already be familiar with the MarshalJSON() override (as well as json:"-" comment formatting):

func (self *Configuration) MarshalJSON() ([]byte, error) {
	return []byte(`{"port": ` + strconv.Itoa(self.Port) + `, "address": "` + self.Address + `", "username": "` + self.Username + `"}`), nil

However, did you know the same works with %s formatting:

func (self Configuration) String() string {
	s, _ := self.MarshalJSON()
	return string(s)

Even better, the "golden goose" does exist for %v too:

func (self Configuration) GoString() string {
	return self.String()

Note the lack of pointer-receivers on the String() and GoString() methods.

It seems go exposes complexity to help enforce good application design, so if you find these solutions to be painful it may indicate some flaws to investigate.


You can run tests via:

go test -v -race -cover

All logger output is redirected during tests (and benchmarks) to /dev/null using io.Discard.


Benchmarks can be run on the project via:

go test -run=X -bench=.

While biased by system, here are the results of the last run:

BenchmarkLogger-8   	 1000000	      2292 ns/op
ok	2.319s