Signup/Sign In
PUBLISHED ON: FEBRUARY 17, 2023

Logging in Golang

Logging is very important. Every production web application uses logs to assist developers and operations. The type of application you're building will determine the data you actually log.

Why do we need logging in Go language?

The most common reasons to use logging in your programs are:

  • Find programming errors in the application.

  • Analyze the causes of failures and security problems.

  • The timestamp for an event or the creation of a log.

  • Layers of logging like debug, error, or info.

  • Identify performance issues.

  • Contextual information to make it easier to understand what happened and to duplicate the circumstance.

  • Environment variables and information.

You should never log sensitive information, which may contain users data, such as Name, API keys, etc.

Package log

Go language has built-in package to make programmers life easy but we can always use or create third party packages for better results. Instead of the standard error (stderr) output stream, which is where it prints by default.You can force the log package to write to local files or any location that accepts the io.Writer interface and append a timestamps to the log message.

Write logs in a file - Go language

1st method

Based on the Go docs, os.Open() can't work for log.SetOutput, because it opens the file "for reading:"

# open file in read/write mode
f, err := os.OpenFile("testlogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
if err != nil {
    log.Fatalf("Error opening file: %v", err)
}
defer f.Close()

log.SetOutput(f)
log.Println("This is a log entry")

2nd method

To append to a log file you can use shell redirection. The default logger in Go writes to stderr (2).

./app 2>> logfile

3rd method

created a package called logger.go

package logger

import (
  "flag"
  "os"
  "log"
  "go/build"
)

var (
  Log      *log.Logger
)


func init() {
    // set location of log file
    var logpath = build.Default.GOPATH + "/src/chat/logger/info.log"

   flag.Parse()
   var file, err1 = os.Create(logpath)

   if err1 != nil {
      panic(err1)
   }
      Log = log.New(file, "", log.LstdFlags|log.Lshortfile)
      Log.Println("LogFile : " + logpath)
}

import the package wherever you want to log e.g main.go

package main

import (
   "logger"
)

const (
   VERSION = "0.13"
 )

func main() {

    // time to use our logger, print version, processID and number of running process
    logger.Log.Printf("Server v%s pid=%d started with processes: %d", VERSION, os.Getpid(),runtime.GOMAXPROCS(runtime.NumCPU()))

}

What is the difference between log.Println and fmt.Println?

There are two differences:

  1. While plain fmt is not safe from concurrent goroutines, printing via package log is.

  2. Log can automatically add time data

So these are two completely different things. log is for logging and fmt for formatting. (Okay, log uses the same verbs and flags, but that is just convenient).



About the author:
Pradeep has expertise in Linux, Go, Nginx, Apache, CyberSecurity, AppSec and various other technical areas. He has contributed to numerous publications and websites, providing his readers with insightful and informative content.