zerologを標準logの代用にするための設定

ログレベルのない標準logでは辛くなってきたので、高速構造化LoggerであるzerologのPretty loggingで代用するための設定について調べました。構造化ログを知らなかった無知が書いております。

公式で紹介されている例

zerolog公式でもPretty loggingの設定方法が軽く紹介されているのですが、その出力は

2006-01-02T15:04:05+09:00 | INFO  | ***Hello World**** foo:BAR

で、個人的にマイクロ秒とファイル名、行番号が欲しかったのですが(あとタイムゾーンは不要)検索では見つけられず、godocを眺めつつの試行錯誤で探しました。

設定方法

以下の手順でできました。なお移行中に標準logと混在しても困らないようにzerolog/logはzlogにエリアスしています。またglobal loggerを書き換えています。

import (
    "fmt"
    "log"
    "path/filepath"
    "strings"
    "time"

    "github.com/rs/zerolog"
    zlog "github.com/rs/zerolog/log"
)

func initLog() {
    zerolog.SetGlobalLevel(zerolog.InfoLevel)
    zerolog.TimeFieldFormat = time.RFC3339Nano
    output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: "2006-01-02 15:04:05.000000"}
    output.FormatLevel = func(i interface{}) string {
        return fmt.Sprintf("%-6s", i)
    }
    output.FormatMessage = func(i interface{}) string {
        return fmt.Sprintf(" %s ", i)
    }
    output.FormatFieldName = func(i interface{}) string {
        return fmt.Sprintf("%s:", i)
    }
    output.FormatFieldValue = func(i interface{}) string {
        return fmt.Sprintf("%s", i)
    }
    output.FormatCaller = func(i interface{}) string {
        t := fmt.Sprintf("%s", i)
        s := strings.Split(t, ":")
        if 2 != len(s) {
            return t
        }
        f := filepath.Base(s[0])
        return f + ":" + s[1]
    }
    zlog.Logger = zerolog.New(output).With().Timestamp().Caller().Logger()
    zlog.Info().Str("foo", "bar").Int("baz", 123).Msg("Hello World")
}

// 2019-01-20 18:48:25.743394 info   main.go:257  Hello World  baz:123 foo:bar

なお複数のpackageで構成するプログラムの場合にはglobal loggerを書き換えるよりもファイル先頭で

var Logger zerolog.Logger

としておき、

    Logger = zerolog.New(output).With().Timestamp().Caller().Logger()
    Logger.Info().Str("foo", "bar").Int("baz", 123).Msg("Hello World")

と設定して使う方が、packageごとに異なるログレベルを設定したりできるようになるので良さそうです。

使い方補足

zerologは本来機械可読な構造化ログを出力するためのものなので、表示したいパラメータは一つずつStr()やInt()といった型ごとのメソッドに名前と一緒に渡し、それをメソッドチェーンで繋ぐという思想の様です。自作のstructもInterface()で表示できます(リフレクションを使うので遅くはなるはずです)。

後づけの狙い

開発時にはログレベル付Loggerとして利用、出荷時にはPretty loggingをやめれば超高速Loggerであるzerologの恩恵にあやかれるはずだと思います。

ログローテーション

lumberjackを使うのが簡単そうです。

writer := &lumberjack.Logger{
    Filename:   "/var/log/myapp/foo.log",
    MaxSize:    10, // megabytes
    MaxBackups: 5,
    MaxAge:     28, //days
    Compress:   true, // disabled by default
}

としておいて、

output := zerolog.ConsoleWriter{Out: writer, ... 

これでできました。

※動作確認バージョン go 1.8.1 / zerolog v1.11.0
※当初zapを試そうとしましたが、最新2バージョンのみサポートだそうで、2019/1現在すでにgo 1.8.1では動きませんでした

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account