Jan 9, 2023 • 8 min read
The 5 Best Logging Libraries for Golang
When you deploy an application in production, you must monitor it to ensure that is working as intended, and observe any issues that arise. One of the tools you can use is Logging, which records activities on the application and forwards them to persisting storages, such as files, sockets, or a monitoring tool. If the application has an issue, you can go through the logs to analyze the state of the application before the problem emerged. Good logs tell you the severity of the log messages, the date the log entries were created, and are usually in a format that is human and machine-readable.
In this article, we'll explore the five best logging libraries for Go:
Why Use Logging Libraries for Go?
If you have used
fmt.Println() to log messages, and you wonder why a logging library is necessary, this section is for you.
Let's say you have logged a message with
fmt.Println() as follows:
The message here has no severity levels to tell you the significance of the message. It has no timestamps to let you know when the log entry was made, and nor is the message in a format like JSON that a machine can parse or filter.
Compare the output
fmt.Println() with the output from a structured logging library for Go:
The following are some of the fascinating details about the message:
- The message is structured using the JSON format, which is machine-readable.
- It contains a level showing the severity of the message. Examples of levels include
- It includes a timestamp that tells you when the log entry was made.
Most logging libraries can create the preceding structured message out of the box.
They also make it easier to specify destinations to send logs, such as files, sockets, emails, monitoring tools, etc.
Now that you know why a logging library is important for your project, let's explore the best logging libraries in Go.
5 Best Go Logging Libraries
The first on our list is Zap, which is a popular structured, leveled logging library for Go. Uber developed it as a high-performance alternative to the
log library built-in Go, as well as third-party libraries like Logrus. It claims to be 4-10x faster than the competing libraries and ranks high on most benchmarks in terms of speed. At the time of writing, it has 18.4K stars on GitHub.
The following are some of the key features available in the library:
- It is fast
- Can forward logs to multiple destinations, such as files, standard output, syslog, or network streams.
- Allows you to customize the log messages format or add custom fields to messages.
- Extensible with the use of third-party libraries.
How to Use Zap
With the latest version Go on your system, install the Zap package as follows:
Next, create a
zap_demo.go with the following code that logs messages in a structured format:
To quickly get started with Zap, you call the
NewProduction() preset, which already has some configurations. Depending on your performance needs, you can choose between two loggers:
Logger when performance is critical and
SugaredLogger when performance is nice, but not too critical. In the example, you call
Sugar() to use the
Following that, you flush the buffer, then call the methods that correspond to the levels that the library supports.
The following is a brief overview of the supported levels:
DEBUG: Information useful to developers during debugging.
INFO: Confirms that the application is working the way it is supposed to.
WARN: Indicates a problem that can disturb the application in the future.
ERROR: An issue causing malfunctioning of one or more features.
FATAL: a serious issue that prevents the program from working.
Zap also supports other levels
PANIC, which are out of the scope of this post.
When you run the file, you will receive the following output:
In the output, you see structured log messages containing the severity
ts, the actual message
msg, and the
stacktrace property for the messages with
The standard output isn't the only destination to send logs. You can forward the logs to a file as well. For that, you will need to configure the
NewProduction preset. Take look at the latest example:
NewProductionConfig() creates a configuration for the logger. Next, you use the
OutputPaths to specify the destination to send the logs, which is the
app.log file. You then invoke
config.Build() to build the logger. Then after that, you check if there is an error, and exit the application if need be. Similar to the last example, you use the
Sugar() logger, and log a warning message.
Upon running the file, you will find a file
app.log in the directory containing a log message that looks similar to the following:
Zap also allows you to customize a message and add extra fields. The
Sugaredlevel logger provides extra methods that end with
w, such as
WarnW, etc., which accepts fields as demonstrated below:
Warnw() method now takes an extra field
process_id set to the process ID of the Go program.
To test the new changes, remove the
app.log in your directory and then run the file. It will create the
app.log file again with the following:
You will now see the
process_id field in the output.
NewProduction() preset doesn't suit your need, you can configure your own logger with JSON or YAML, and then pass it to the Zap logger:
main() function, you create a raw JSON, which contains fields that specify the minimum severity level, encoding, and destination to send logs. In the
encoderConfig option, you include and customize the fields that should show up in the log message.
To decode the JSON array elements into Go array elements, you invoke
json.Unmarshal(), which takes the raw JSON you created. Following this, you build the logger and log a warning message in the console.
Running the file produces the following output:
We have barely scratched the surface of what Zap is capable of doing, visit the documentation to explore more Zap features.
Zerolog is another high-performance structured logging library for Go. It was inspired by Zap, and aims to provide an optimized logger with a simple API for a great developer experience. At the time of writing, it has close to 8K Github Stars.
Zerolog has the following features to consider:
- high performance
- can integrate with
- Binary encoding with JSON or CBOR encoding formats
- log sampling
- Pretty printing
How to Use Zerolog
Install the package with the following command:
Then create a
zerolog_demo.go file and add the following code:
Zerolog has a pre-configured logger that supports the following levels:
Running the file will log all the messages in the console:
As you can see in the output, every message is structured in JSON and has a level, time, as well actual message.
Zap defaults to the minimum level
TRACE, which you can change anytime with the following
SetGlobaLevel() method of Zerolog library changes the minimum level. In the output, you will see that only messages with a severity level of
WARN or higher are logged:
You can also configure Zerolog to send log messages to files as demonstrated in this new example:
In the preceding code, you open the file
app.log and pass the file instance to the Zerolog logger so that it should forward the log messages to the file.
When you run the file, it creates an
app.log file with the following contents:
Now that you have an idea of what Zerolog, is capable of doing, the documentation covers a lot more other cool features.
Get the visibility you need
Go ships with a logging module
log in its standard library, which has a lot of limitations. For one, it lacks log levels, and for another, it has no support for structured logging. In October 2022, a proposal was made for a logging library with support for structured logging and levels called Slog. The proposal was accepted and it will be included in Go 1.21. The preliminary implementation is at https://pkg.go.dev/golang.org/x/exp/slog, and you can use it with the recent versions of Go. Once implemented in Go, you will be able to access it from
The following are some of the features of Slog:
- Structured logging with support for JSON and Logfmt format.
- A faster performance
- Support for levels
- Allows adding custom fields to logs
- Forwarding logs to multiple destinations. -Part of the standard library. No need for a third-party logging library.
How to Use Slog
Ensure you have the latest version of Go. If the version is 1.20 or lower, install
slog as follows:
For Go versions 1.21 or higher, Slog will be included in the standard library. So the installation won't be necessary.
In your text editor, create a
slog_demo.go file, and paste the following:
Slog has a default logger that formats and sends messages to the standard output. If you save and run the file, you will see the output looking like the following:
Currently, the messages are unstructured. To make the messages structured, you can create a logger, which lets you choose the log message format.
Let's structure the messages using Logfmt with the following example:
slog.New() creates a logger, and takes a handler, which is used to customize the format of a message and the destination. The
NewTextHandler() method formats the message in Logfmt format and forwards the message to the standard output.
After you run the file, the output will show you a sequence of key=value pairs that machines can parse:
To use the JSON format instead, all you have to do is replace
You can add also add custom fields to the message, the following simplified examples show you how to do it:
slog.Int() is an attr, which is a key-pair value.
Running the file yields the following:
The log message now has an extra field
version with a value
There is a lot to unpack about Slog, see the documentation for more details.
If you haven't decided on the logging library to use yet, you can consider the apex/log library. It is a structured logging library, which at the time of writing has over 1.3K stars.
Here are some of the interesting features:
- structured logging with JSON or Logfmt
- customizing log messages
- filtering logs
- forwarding logs to multiple destinations.
How to Use apex/log
Download the package with the following command:
apex_demo.go file with the following content:
SetHandler() customizes the message, as well as set the destination to send the logs.
The following is the output the code yields:
Similar to the other logging libraries, the
apex/log includes the level, timestamp, and message with minimal effort.
You can also add extra fields to the message as shown in the following:
The output looks like this once you run the file:
version field shows up in all the log messages.
We have looked at a few basic features in this section, for more information, take a look at the documentation.
Logrus is one of the oldest structured logging library available for Go. While its performance is not as good as the libraries we saw earlier in this post, it is still a good library to use. Note that it is currently in maintenance mode, and new features won't be introduced. So keep that in mind if you want to start using it.
The following are some of the features:
- Structured logging support.
- Has an API compatible with the standard library
- Supports adding extra fields to log messages.
- customizing log messages.
How to Use Logrus
Install the package as follows:
logrus_demo.go file as follows:
SetFormatter() formats the messages in JSON format. You then invoke some log methods, corresponding to the supported levels. Other levels we haven't included are
The output will look the following when you run the file:
In the output, the message with the
DEBUG level is omitted. This is because Logrus defaults to a minimum level of
INFO. You can customize this with the
Logrus now has a minimum level of
ERROR, and will show messages more severe than
ERROR, such as
If you want to learn more about Logrus features, read through the documentation.
In this article, we looked at the 5 best logging libraries for Go. We hope you have now chosen the logging library for your next project. If you are still undecided, we would suggest you go with Zap, but keep a close eye on Slog, which will soon be part of the core library. It also is having a positive reception within the Go community.