How to Create a Log in Golang

To create a log in Golang, you can use the built-in “log” library. The package log in Go implements the simple logging package that defines a type, Logger, with methods for formatting output.

You can use these rough-and-ready logs for local development in which you need to get fast feedback from your code may be more important than generating rich, structured logs.

To generate rich and structured logs, third-party packages will be more helpful.

Example

For example, you can define the division function that returns the error to the caller rather than exiting the program when you attempt to divide by zero.

package main

import (
  "errors"
  "fmt"
  "log"
)

func division(x float32, y float32) (float32, error) {
  if y == 0 {
    return 0, errors.New("can't divide by zero")
  }

  return x / y, nil
}

func main() {

  var x float32 = 11
  var y float32

  res, err := division(x, y)

  if err != nil {
    log.Print(err)
  }

  fmt.Println(res)
}

Output

2019/11/28 18:50:19 can't divide by zero 
0 

In the above program, we have imported three packages.

  1. errors
  2. fmt
  3. log

Then we have defined a function division(), which accepts two parameters. 

We are checking the dividing by 0 error; if it occurs, we log that error in the console.

If we meet the divide by 0 conditions, one error will be generated, and then we log that error in the console and print the return value.

In the above program, we got the divide by 0 conditions; that is why we got the output log.

The logger writes to standard error and prints the date and time of each logged message which is quite helpful in general case scenarios.

Every log message has an output on a separate line: if the printed message does not end in the new line, the logger will add one line.

The Fatal functions call os.Exit(1) after writing the log message.

The Panic functions call panic after writing a log message.

How to store the logged messages in files in Go

In Go, you can store logged messages in files by configuring the logger from the log package to write to a file.

Example

package main

import (
  "errors"
  "fmt"
  "log"
  "os"
)

func division(x float32, y float32) (float32, error) {
  if y == 0 {
    return 0, errors.New("can't divide by zero")
  }

  return x / y, nil
}

func main() {
  var x float32 = 11
  var y float32

  res, exception := division(x, y)
  file, err := os.OpenFile("info.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)

  if err != nil {
    log.Fatal(err)
  }

  defer file.Close()

  log.SetOutput(file)
  log.Print(exception)
  fmt.Println(res)
}

Output

0 

Also, you will find the info.log created in your directory. Open the file, and you will see something like the following printed.

2019/11/28 19:29:33 can't divide by zero 

The os interface in Go is intended to be uniform across all operating systems. Therefore, features not generally available appear in the system-specific package syscall.

If the open fails on file, the error string will be self-explanatory.

What we are doing in the above code is creating one log file and printing our log message inside that file.

After printing the log message, we close the file, and that is it.

GitHub package logrus for formatted logs

The logrus is a package designed for structured logging that is well-suited for logging in JSON. The JSON format allows machines to parse your Golang logs quickly.

And since JSON is a well-defined standard, adding context by including new fields makes it straightforward—a parser should be able to pick them up automatically.

Using the logrus package, you can define standard fields to add to your JSON logs using the function WithFields, as shown below.

You can then make calls to the logger at different levels, such as Info(), Warn(), and Error().

The logrus library will automatically write the log as JSON and insert the standard fields and any fields you’ve defined on the fly.

To use the package, first, you need to install it. Type the following command.
go get github.com/Sirupsen/logrus

Example

package main

import (
  log "github.com/sirupsen/logrus"
)

func main() {
  log.WithFields(log.Fields{
    "Best Song": "Sunflower",
  }).Info("One of the best song")
}

Output

Golang Log Example

Note that it’s utterly API-compatible with the stdlib logger so that you can replace your log imports everywhere with log github.com/sirupsen/logrus, and you’ll now have the flexibility of Logrus. You can customize it all you want.

Best practices for writing and storing Golang logs

The first thing while writing a log is to find a perfect library. Then after you have chosen the logging library, you’ll also want to plan for where in your code to make calls to the logger, how to store your logs, make them available at any given time, and analyze them.

Let’s see some of the best practices.

  1. You can call the logger from within your primary application process, not within the goroutines.
  2. It is considered good practice to write logs from your application to a local file, even if you will ship them to a central platform later.
  3. You can standardize your logs with a set of predefined messages.
  4. You can send your logs to the central platform to analyze and aggregate them.
  5. Use the HTTP headers and unique IDs to log user behavior across microservices.

That’s it.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.