Skip to main content

Introduction

go-log is an opinionated, modularized, structured and production-ready GO logging library.

It was created, at first, to be used in webservers and CLI tools. But feel free to explore the possibilities.

Getting Started#

You will need to install go-log before starting. To do it, execute the following command:

go get github.com/mathbalduino/go-log

The library is built around the Logger interface type, that contains all the main methods:

// new.gotype Logger interface {  ...}

Once you get a Logger instance, you're ready to throw logs by calling the correspondent methods:

// logLevels.gofunc Trace(msg string, adHocFields ...LogFields)  { ... }func Debug(msg string, adHocFields ...LogFields)  { ... }func Info(msg string, adHocFields ...LogFields)   { ... }func Warn(msg string, adHocFields ...LogFields)   { ... }func Error(msg string, adHocFields ...LogFields)  { ... }func Fatal(msg string, adHocFields ...LogFields)  { ... }func ErrorFrom(e error, adHocFields ...LogFields) { ... }func FatalFrom(e error, adHocFields ...LogFields) { ... }

As you may have seen, this library contains some builtin Log levels, but you can customize it.

To create a new Logger instance, you have two options:

  1. Function New, that will create an empty Logger instance (takes a Configuration struct as argument)
  2. Function NewDefault, that will create a Logger instance with the Default configuration

Basic concepts#

To understand this library, you'll have to understand 4 different concepts:

  1. Log fields
  2. Hooks
  3. Log life cycle
  4. Outputs

Log fields#

Logs are represented as a set of fields, just like a JSON object:

{  "msg": "some log message",  "lvl": 10,  ...  "custom": "field",  ...}

Looking at the GO type definition for log fields, it becomes clear that it's just a map from string to anything:

// fields.go// Just an aliastype LogFields = map[string]interface{}

Fields can be statically or dynamically added or overrided, so you have freedom to structure your log as you please.

You can set log fields in 3 different ways, using:

  1. Base fields
  2. PreHooks
  3. Ad hoc fields
  4. PostHooks

Hooks#

Hooks are used to define dynamic fields. They're divided in two categories:

  1. PreHooks
  2. PostHooks

A set of Hooks is defined as a map from field name to a function that evaluates to the field value:

// hooks.go// Just an aliastype Hooks = map[string]func(Log) interface{}
note

Hooks are intended to be used to calculate the value of non-constant fields, just like the log timestamp, for example

Log life cycle#

Every created log will go through four different phases, sending the final log fields to the configured outputs:

  1. Creation
  2. Pre handling
  3. Post handling
  4. Output

For more details, see the Log life cycle page.

Outputs#

When some log is created it needs to be sent to somewhere, be it the stdout, some database, or anything. Outputs are functions that handle these scenarios, forwarding the created logs to it's final destiny.

The library contains some basic Output functions already defined, so you can play around with them or create your own, from scratch.

At the end of the day, outputs are just functions that will receive some log fields:

// outputs.go// Just an aliastype Output = func(lvl uint64, msg string, fields LogFields)

For more details, see the Outputs page.

Extras#

Sync vs Async#

Logs can be handled in two ways: sync or async. When set to async, the expensive part of the logging operation will run in a different go routine.

In order to configure the Logger to be async, you will need to read more about Async Loggers.

Advanced customization#

Virtually everything is customizable. You can change the name of the required fields msg and lvl, create new log levels, new error parsers, etc.

For more details, see the Configuration, Log levels and Outputs pages.