Logging in Golang
Native Go Logging
Go offers native logging library:
Logging to Stdout/Stderr
$ mkdir logging-frameworks && cd logging-frameworks
$ cat > native.go <<EOF
package main
import "log"
func main() {
log.Println("Hello world!")
log.Debug("Debugging is fun")
log.Info("Something is interesting!")
log.Warn("Something bad may come!")
log.Error("Something must be wrong!")
log.Fatal("OMG!")
}
EOF
$ go run native.go
INFO[0000] Hello world!
INFO[0000] Something is interesting!
WARN[0000] Something bad may come!
ERRO[0000] Something must be wrong!
FATA[0000] OMG!
exit status 1The code above prints the text "Hello world!" to the standard error, but it also includes the date and time, which is handy for filtering log messages by date.
Logging to a File
A file named logs.txt will be created with content:
You can basically output your logs to any destination that implements the io.Writer interface, so you have a lot of flexibility when deciding where to log messages in your application.
Creating custom loggers
Output in logs.txt:
Log flags
There are log flags we can use to enhance the logs:
So:
Community Logging Frameworks
Surprisingly, there is a long list of community logging frameworks, with different design philosophies. Let's name some of the popular ones
glog - Leveled execution logs for Go.
logrus - Structured logger for Go.
zap - Fast, structured, leveled logging in Go.
Let's try out logrus.
logrus
Get Started
As logrus is fully compliant to Golang's standard logging APIs, it can be very easy to get started:
Logging in JSON
Log levels
Unlike the standard log package, logrus supports log levels.
We will get:
Notice that the Debug level message was not printed. To include it in the logs, set log level to equal log.DebugLevel:
Logging Method Name
Using Fields
Default Fields
Often it's helpful to have fields always attached to log statements in an application or parts of one. For example, you may want to always log the request_id and user_ip in the context of a request. Instead of writing log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip}) on every line, you can create a logrus.Entry to pass around instead:
We got this -- note that only user activity logs logged with extra fields:
Hooks
There are many hooks, besides the built-in ones: https://github.com/sirupsen/logrus/wiki/Hooks
A simple writer-based hook mechanism can be implemented like:
Now:
Formatters
The built-in logging formatters are logrus.TextFormatter, logrus.JSONFormatter.
There is a series of 3rd party fomatters too:
FluentdFormatter. Formats entries that can be parsed by Kubernetes and Google Container Engine.GELF. Formats entries so they comply to Graylog's GELF 1.1 specification.prefixed. Displays log entry source along with alternative layout.zalgo. Invoking the Power of Zalgo.nested-logrus-formatter. Converts logrus fields to a nested structure.powerful-logrus-formatter. get fileName, log's line number and the latest function's name when print log; Sava log to files.caption-json-formatter. logrus's message json formatter with human-readable caption added.
References
Last updated
Was this helpful?