Technical Resources
Educational Resources
APM Integrated Experience
Connect with Us
It’s hard to overstate how important logging is for most applications. When troubleshooting a bug in production, logging is often the difference between a quick fix and hours or days of fruitless investigation. This is true regardless of programming language or platform. Your app might be written in Java, Python, or a web framework, but logging remains equally important. Today we’ll venture into yet another programming language by offering an introductory guide to Golang logging.
We’ll start with a brief overview of Golang and the basics of logging. Then, we’ll teach you how to log in Go in the simplest possible way. Afterward, we’ll improve on this approach by making use of a third-party tool. Before wrapping up, we’ll share some final tips on the next steps you should take.
There’s no better place to start than at the beginning. Let’s begin with some Golang and logging fundamentals.
Go is an open-source programming language originally designed by Google in late 2009. It’s a statically typed and compiled language. The objective of Go is to be as efficient as a low-level language like C and cater to some of the same problems and challenges. However, it also offers developers some of the conveniences of more modern programming languages, such as memory safety, garbage collection, and support for parallel programming.
Though the proper name of the language is simply “Go,” people often call it “Golang” because its domain name is golang.org (and probably also because its name is a generic English word, which makes it hard to search on search engines).
So what is logging? Here’s how Wikipedia defines it:
In computing, a log file is a file that records either events that occur in an operating system or other software runs, or messages between different users of a communication software. Logging is the act of keeping a log. In the simplest case, messages are written to a single log file.
In a nutshell, we could say logging is writing information about your application to some external destination so you can go back later and read it. Even though the definition above emphasizes log files, there are plenty of destinations you can write your events to, including database tables, cloud services, and more.
With the “what” of logging out of the way, let’s turn our attention to the “why.” What are the benefits of logging?
Logging is mainly used as a troubleshooting mechanism. By reading through log entries, you can understand how your application behaved in production and retrace users’ actions. This information can help you diagnose and fix whatever problem the application was presenting.
But software organizations have been increasingly using logging in more proactive—rather than reactive—ways. By leveraging log analysis, organizations can extract valuable insights from their logs. They can then use this knowledge to help them in their decision-making processes and fix problems before they become critical.
The first step to logging in Golang is downloading and installing Go. There are versions for Linux, Windows, and macOS, so you’re likely covered no matter which operating system you have. We won’t provide detailed installation instructions here for brevity’s sake, but you can find what you need on the Go website.
When you’re all set, you’ll be ready to write and run your first Go program. Paste the code below on a new text file and save it as golang-demo.go. Since I’m on Windows, I’ll be using Notepad++, but feel free to use your preferred text editor.
package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}
Afterward, run your program by executing the following command:
go run golang-demo.go
If everything goes right, you should see “Hello, world!” displayed on the screen:
Pretty basic stuff, right? Let’s spice things up by adding some logging.
Unlike many other languages, Go doesn’t require you to install a third-party tool to start logging. This is because the language offers a logging package you can use right off the bat.
Start by importing the package. Add the following line to your code before the main() function:
import "log"
Then, add the following line to your main function:
log.Print("This is our first log message in Go.")
If you run the program again, you should get an output like this:
Hello, world!
2020/06/12 13:40:02 This is our first log message in Go.
Congratulations! You’ve just logged in Go for the first time.
We just provided you with the quickest Golang logging example we could get away with. Logging to the console might be enough for performing simpler debugging tasks, but when it comes to logging in production or doing more robust debugging, this approach falls hopelessly short.
When logging in the “real world,” you’ll probably want to log to a persistent medium, such as a file. Also, you’ll want to use log levels—not using them will make it harder for future readers to find the information they need. Additionally, you might need to format your logging output in specific ways.
There are many possible logging destinations, but the most popular is certainly files on disk. So let’s change our example to log to a file instead of to the console.
Our first task is to create a file to write to (or open it, if it already exists). Start by importing the os package:
import "os"
You’re now ready to handle I/O. Add the following code to your main() function above the calling to log.Print:
f, err := os.OpenFile("golang-demo.log", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
defer f.Close()
If you run the program again by this point, it’ll behave the same as before. But if you go to the folder where your golang-demo.log lives, you’ll see an empty file called golang-demo.log.
The next step is to set our file as the output for the logger. Add the following line right before the call to log.Print:
log.SetOutput(file)
Run the program again and open your log file. Its contents should look like this:
2020/06/12 14:27:33 This is our first log message in Go.
We used the function Fatalf() to handle issues when opening or creating our log file. Even though the function shares the name of one of the common logging levels offered by most logging tools, it actually calls os.Exit(1) after writing the message, which terminates the program. So how do you use log levels with the standard logging package in Go?
Well, you don’t. Unfortunately, it doesn’t support leveled logging, so we’ll have to resort to third-party logging tools. And there’s a large number of them, too. For a long time, logrus was the most popular logging framework for Go. However, it’s currently in maintenance mode, so we’ll go with zap instead.
To install zap, run go get -u go.uber.org/zap. Then, remove the os package from your list of imports and replace it with this:
import "go.uber.org/zap".
Then, replace all of our logging code with the following:
// first, we create a configuration (i.e. a builder) for our logger
config := zap.NewProductionConfig()
// we configure the destination for our log, in this case, a file
config.OutputPaths = []string{"zap-demo.log"}
// we build the logger
zapLogger, err := config.Build()
// Go doesn't support exceptions, so we check for the error, exiting the application if needed
if err != nil {
log.Fatalf("can't initialize zap logger: %v", err)
}
// flushes buffer, if any
defer zapLogger.Sync()
// we finally log our message at the INFO level
zapLogger.Info("This is our first log message using zap!")
If you run the program, you should see a new file called zap-demo.log. Since zap supports structured logging, the result is JSON and should look like this:
{
"level":"info",
"ts":1591987596.1284277,
"caller":"Desktop/golang-demo.go:19",
"msg":"This is our first log message using zap!"
}
Logging is essential for most nontrivial applications. In this post, we’ve provided you with an introduction to logging in Go. Go offers a standard logging package you can use from the get-go. The package is somewhat limited, though, so we had to resort to a third-party tool—zap—to obtain features such as structured logging and levels.
So what should your next steps be? Well, you have an exciting and long journey of learning ahead of you. Here are some things you might try next:
This post was written by Carlos Schults. Carlos is a .NET software developer with experience in desktop and web development, and he’s now trying his hand at mobile. He has a passion for writing clean and concise code, and he’s interested in practices capable of helping you improve app health, such as code
Updated: 2023