2019年8月28日水曜日

go-kit の kit/log を使ってみた

概要

go-kit/kit/log は golang 標準のログパッケージにはない強力な機能を提供してくれます
また標準の log パッケージとの親和性もあるため導入がシームレスにできます
今回は基本的な使い方やログのフォーマットの設定方法など紹介したいと思います

環境

  • CentOS 7.6.1810
  • go 1.12.1
    • go-kit/kit dc489b75b9cdbf29c739534c2aa777cabb034954

基本的なロギング方法

まずは基本的なロギング方法です
デフォルトのフォーマットはイコールでつなぎ合わせるフォーマットになっています

  • cd $GOPATH/src/github.com/hawksnowlog/a
  • vim main.go
package main

import (
        "github.com/go-kit/kit/log"
        "os"
)

func main() {
        w := log.NewSyncWriter(os.Stdout)
        logger := log.NewLogfmtLogger(w)
        name := "hawksnowlog"
        age := 99
        logger.Log("name", name, "age", age)
}
  • go fmt github.com/hawksnowlog/a
  • go build github.com/hawksnowlog/a
  • ./a

=> name=hawksnowlog age=99

上記は os.Stdout を使っているため標準出力に出力されます
logger を作成してあとは Log 関数を使えばイコールつなぎのログになります
この logger に対していろいろと設定することで様々なロギングを行うことができます

常に同じ情報をログに含める

例えばリクエスト ID などは常に表示しておきたい情報です
そんな場合には With を使うことでロギング時に常に同じ情報を含めることができます

package main

import (
        "github.com/go-kit/kit/log"
        "os"
)

func main() {
        w := log.NewSyncWriter(os.Stdout)
        logger := log.NewLogfmtLogger(w)
        logger = log.With(logger, "host", "localhost")

        name := "hawksnowlog"
        logger.Log("name", name)
}

=> host=localhost name=hawksnowlog

こんな感じのログになります
この With を使うことでタイムスタンプなどの表示に応用することができます (後述)

JSON フォーマットでロギング

JSON にする場合は NewLogfmtLogger -> NewJSONLogger にすれば OK です

package main

import (
        "github.com/go-kit/kit/log"
        "os"
)

func main() {
        w := log.NewSyncWriter(os.Stdout)
        logger := log.NewJSONLogger(w)
        logger = log.With(logger, "host", "localhost")

        name := "hawksnowlog"
        logger.Log("name", name)
}

=> {"host":"localhost","name":"hawksnowlog"}

タイムスタンプと実行しているプログラムのファイル名を表示する

With を使ってタイムスタンプとファイル名を表示する方法です
デフォルトは UTC なので JST の場合は少し工夫が必要です

package main

import (
        "github.com/go-kit/kit/log"
        "os"
        "time"
)

func main() {
        w := log.NewSyncWriter(os.Stdout)
        logger := log.NewLogfmtLogger(w)
        format := log.TimestampFormat(
                func() time.Time { return time.Now().UTC() },
                time.RFC3339Nano,
                // func() time.Time { return time.Now().UTC().In(time.FixedZone("Asia/Tokyo", 9*60*60)) },
                // time.RFC3339,
        )
        logger = log.With(logger, "timestamp", format, "caller", log.DefaultCaller)

        name := "hawksnowlog"
        logger.Log("name", name)
}

=> timestamp=2019-08-27T20:34:05.1738304758Z00:00 caller=main.go name=hawksnowlog

log.TimestampFormat でフォーマットを指定できます
時刻のフォーマットもいろいろと選択できます
JST の場合はコメントされているほうを使えば OK dえす

ログレベルを設定する

ログレベルを設定することもできます
その場合は github.com/go-kit/kit/log/level と組み合わせます

package main

import (
        "github.com/go-kit/kit/log"
        "github.com/go-kit/kit/log/level"
        "os"
)

func main() {
        w := log.NewSyncWriter(os.Stdout)
        logger := log.NewLogfmtLogger(w)
        // logger = level.NewFilter(logger, level.AllowInfo())
        logger = level.NewFilter(logger, level.AllowDebug())
        // logger = level.NewFilter(logger, level.AllowWarn())
        // logger = level.NewFilter(logger, level.AllowError())

        logger.Log("msg", "no level always show")
        level.Info(logger).Log("msg", "info level")
        level.Debug(logger).Log("msg", "debug level")
        level.Warn(logger).Log("msg", "warn level")
        level.Error(logger).Log("msg", "error level")
}

=> msg="no level alyways show"
=> level=info msg="info level"
=> level=debug msg="debug level"
=> level=warn msg="warn level"
=> level=error msg="error level"

level.NewFilter でログレベルを設定します
上記のように level.AllowDebug() の場合はデバッグレベルのログまででるので詳細なログになります
エラーレベルのログだけで良いのであれば level.AllowError() を設定します
また設定したログレベルに沿ったログを出力したい場合は level.XXX(logger).Log 関数を使ってログを出力するようにしましょう
logger から直接 Log 関数をコールした場合は level に関係なくログが表示されます

最後に

go-kit の kit/log を使ってみました
ロギングのフォーマットやコンテキストロギングなどいろいろと強力な機能が備わっているので便利です
また golang のデフォルトの log パッケージとも親和性があるので互いに干渉しないようにできます

参考サイト

0 件のコメント:

コメントを投稿