【Golang】zapを用いたロギング


概要

Golangのロギングのライブラリであるzapのロギング例を示す。本記事では、以下のようなJSON形式のログを想定している。内容は、ログレベル、時刻、呼ばれた場所、メッセージである。

{"level":"debug","time":"2020-02-02T23:24:13.185+0900","caller":"logger/utils_test.go:31","msg":"test msg"}
{"level":"info","time":"2020-02-02T23:24:13.186+0900","caller":"logger/utils_test.go:32","msg":"test msg"}
{"level":"error","time":"2020-02-02T23:24:13.186+0900","caller":"logger/utils_test.go:34","msg":"test error"}

zapライブラリは、Readmeのパフォーマンス表では、Golangのロギングライブラリとして有名なlogrusより高速らしいです。

logrusは、Golang logrusによるロギングにて、記事にしましたが、zapの方が高速ということで、今回記事にしました。

プログラム

以下に、初期化のプログラムを示します。基本的には、出力方法やログレベルを環境変数から読み込み、それに合わせて初期化しているだけです。呼び出し時に初期化され、logger.Log.Info()などで使用できる。


package logger

import (
    "fmt"

    "go.uber.org/zap/zapcore"

    "go.uber.org/zap"
)

/*zap
https://github.com/uber-go/zap#performance
*/

var (
    Log *zap.Logger
)

func init() {
    envVals, err := getEnv()
    if err != nil {
        fmt.Println(err)
        panic(err)
    }
    outputPaths := []string{}
    if envVals.filePath != "" {
        outputPaths = append(outputPaths, envVals.filePath)
    }

    if envVals.stdout {
        outputPaths = append(outputPaths, "stdout")
    }

    logConfig := zap.Config{
        OutputPaths: outputPaths,
        Level:       zap.NewAtomicLevelAt(envVals.level),
        Encoding:    "json",
        EncoderConfig: zapcore.EncoderConfig{
            LevelKey:     "level",
            TimeKey:      "time",
            MessageKey:   "msg",
            CallerKey:    "caller",
            EncodeTime:   zapcore.ISO8601TimeEncoder,
            EncodeLevel:  zapcore.LowercaseLevelEncoder,
            EncodeCaller: zapcore.ShortCallerEncoder,
        },
    }

    if Log, err = logConfig.Build(); err != nil {
        panic(err)
    }
}

以下プログラムに使用する環境変数取得など、、、


package logger

import (
    "os"
    "strconv"
    "strings"

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

type envVals struct {
    filePath string
    stdout   bool
    level    zapcore.Level
}

//getEnv ログに関する環境変数を設定
func getEnv() (*envVals, error) {
    res := envVals{}
    res.filePath = os.Getenv("LOGGER_FILE_PATH")

    var err error
    res.stdout, err = strconv.ParseBool(os.Getenv("LOGGER_STDOUT"))
    if err != nil {
        res.stdout = true
    }

    level := os.Getenv("LOGGER_LEVEL")
    switch level {
    case "debug":
        res.level = zapcore.DebugLevel
    case "error":
        res.level = zapcore.ErrorLevel
    default:
        res.level = zapcore.InfoLevel
    }

    return &res, nil
}