Golang Logging Configuration with Zap: Practical Implementation Tips

Hi everybody, continuing from the previous post, which was a basic setup with Golang. In this part, we’re setting up our logging in the app.

PART 1.

Installing the package zap

https://github.com/uber-go/zap

In our project, we need to install the zap package. To do this, put the following command in our terminal.

go get -u go.uber.org/zap

If you’re using Docker like me, you need to enter the container. So, if you’re running the app in the background, execute this command.

docker exec -it demogolang bash

To run the app in the background, use the command: docker-compose up -d.

The name ‘demogolang’ is declared inside the docker-compose.yml file.

Setting up the logging

Dockerfile

In our Dockerfile add 2 environment variables and created a folder to save the logs.

  • APP_LOG_LEVEL: The app log level could be debug or error. We use the debug level when we’re in development and error when the app is in production mode. So, if you’re in error mode when you print logs, Info or Debug, these are not shown in the terminal. If you want to use more levels, you can edit the function to get the current level.
  • APP_LOG_FOLDER: This is the path where you place the log file. You can set whatever path you want.
ENV APP_LOG_LEVEL debug
ENV APP_LOG_FOLDER /tmp/logs/

RUN mkdir -p ${APP_LOG_FOLDER}

Reading environment variables

Inside our app folder, I created a folder called config. Inside config, I put the file called envs.go.

package config

import "os"

var APP_ENV = os.Getenv("APP_ENV")
var IS_DEVELOP_MODE = APP_ENV == "develop"
var APP_LOG_LEVEL = os.Getenv("APP_LOG_LEVEL")
var APP_LOG_FOLDER = os.Getenv("APP_LOG_FOLDER")

Logger file

Inside the app, I created a utils folder and put the logger.go file with the following content.

I

package utils

import (
	"example/demogo/config"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var Logger *zap.SugaredLogger

func getLevelLogger(level string) zapcore.Level {
	if level == "debug" {
		return zap.DebugLevel
	}

	return zap.ErrorLevel
}

func init() {
	var err error
	level := zap.NewAtomicLevelAt(getLevelLogger(config.APP_LOG_LEVEL))
	encoder := zap.NewProductionEncoderConfig()

	zapConfig := zap.NewProductionConfig()
	zapConfig.EncoderConfig = encoder
	zapConfig.Level = level
	zapConfig.Development = config.IS_DEVELOP_MODE
	zapConfig.Encoding = "json"
	zapConfig.InitialFields = map[string]interface{}{"idtx": "999"}
	zapConfig.OutputPaths = []string{"stdout", config.APP_LOG_FOLDER + "app_log.log"}
	zapConfig.ErrorOutputPaths = []string{"stderr"}
	logger, err := zapConfig.Build()

	if err != nil {
		panic(err)
	}

	Logger = logger.Sugar()
}

I created a global variable called Logger; this will be set when the package is initialized. The function getLevelLogger is used to get the current level from the environment variable.

The init function is automatically called before the main function.

  • encoder: Is the log format, how you want to apply the format.
  • InitialFields: The values ​​that you want to always be in the log.
  • OutputPaths: The output of the file.
  • ErrorOutputPaths: To print error log in the terminal.

Finally our main.go.

package main

import (
	"example/demogo/utils"
	"time"
)

func main() {
	defer utils.Logger.Sync()

	for {
		time.Sleep(5 * time.Second)
		utils.Logger.Infoln("hello world")
	}
}

It’s important to call defer utils.Logger.Sync() in the entry point of our app. Normally ensures that all buffered log messages are sent to their final destination if the application crashes.

docker-compose up -d --build

docker logs -f demogolang

Additional information

If you’re working inside the container, you can use the devcontainer extension. For example, if you are using a Mac, you can open the command palette by pressing Shift+Command+P.

Then choose Attach to running container.

Open folder /usr/src/app.

Now you can install the extension you want inside the container.

Now all features the editor is available. This extension has more configuration for this tutorial I think is ok.


Comentarios

Una respuesta a “Golang Logging Configuration with Zap: Practical Implementation Tips”

Deja un comentario