Go

Golang logging library

More than 3 years have passed since last update.

Goのlogging libraryを調べてみましたー。


標準のlog package

package main

import (
"log"
)

func main() {
log.Println("hello log")
}

>> 実行結果
2014/07/22 11:49:15 hello log


func main() {
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
log.Println("hello log")
}

>> 実行結果
2014/07/22 11:50:04 main.go:9: hello log

そのほかにも


  • log.Fatal(...)

  • log.Panic(…)

を主に使う感じ。

file出力したい場合は以下のようにする。

func main() {

f, err := os.OpenFile("/tmp/test.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)

if err != nil {
log.Fatal("error opening file :", err.Error())
}

log.SetOutput(f)

log.Println("hello log")
}

これをそのまま使うときの問題点


  • log levelで制御できない。

  • fatal, panic 以外はPrintlnを使わないといけない

  • ※FATAL以上のログはすべてexit(1)するので注意


golang/glog

package main

import (
"flag"
"github.com/golang/glog"
)

func main() {
flag.Parse() <= これ忘れがちなので注意

glog.Error("glog error log")
glog.Info("glog info log")
glog.V(3).Info("glog v3 info log")
}

>> 実行結果
E0722 15:18:50.820728 10063 main.go:11] glog error log

基本的にはcommand optionでログを制御する。

> go run main.go -stderrthreshold=INFO

E0722 15:20:08.205781 10097 main.go:11] glog error log
I0722 15:20:08.206806 10097 main.go:12] glog info log

> go run main.go -stderrthreshold=INFO -v=3
E0722 15:21:13.663785 10281 main.go:11] glog error log
I0722 15:21:13.664880 10281 main.go:12] glog info log
I0722 15:21:13.664889 10281 main.go:13] glog v3 info log

ファイル出力してみる。

> go run main.go -alsologtostderr -v=3 -log_dir="./log"

E0722 15:41:32.389452 11561 main.go:11] glog error log
I0722 15:41:32.390634 11561 main.go:12] glog info log
I0722 15:41:32.390647 11561 main.go:13] glog v3 info log

> cat ./log/main.INFO
Log file created at: 2014/07/22 15:41:32
Running on machine: PC-8247
Binary: Built with gc go1.3 for darwin/amd64
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg

ファイルは作成されているのに、metadataのみ出力されてログが出力されていない模様。

flushしてないからか。。。

package main

import (
"flag"
"github.com/golang/glog"
)

func main() {

glog.Flush()
}

これでファイル出力はおk。

とりあえず、標準よりはいいという位置づけだけどオプション長いなーとか、ファイル名変えられないからなんか変なファイルいっぱいできるなーとか。


Sirupsen/logrus

package main

import (
"github.com/Sirupsen/logrus"
)

func main() {
logger := logrus.New()

logger.WithFields(logrus.Fields{
"test": "test-value",
"hoge": 1,
}).Info("info log test")

logger.WithFields(logrus.Fields{
"flag": true,
"hoge": 1,
}).Warn("warn log test")

logger.WithFields(logrus.Fields{
"flag": true,
"hoge": 10,
}).Fatal("fatal log test")
}

>> 実行結果
INFO[0000] info log test hoge=1 test=test-value
WARN[0000] warn log test flag=true hoge=1
FATA[0000] fatal log test flag=true hoge=10
exit status 1

JSON形式ではきだしてみる。

package main

import (
"github.com/Sirupsen/logrus"
)

func main() {
logger := logrus.New()

logger.Formatter = new(logrus.JSONFormatter)

}

>> 実行結果
{"hoge":1,"level":"info","msg":"info log test","test":"test-value","time":"2014-07-22 17:07:20.837500348 +0900 JST"}
{"flag":true,"hoge":1,"level":"warning","msg":"warn log test","time":"2014-07-22 17:07:20.837678408 +0900 JST"}
{"flag":true,"hoge":10,"level":"fatal","msg":"fatal log test","time":"2014-07-22 17:07:20.837702453 +0900 JST"}
exit status 1

file出力してみる。

package main

import (
"github.com/Sirupsen/logrus"
"os"
)

func main() {
logger := logrus.New()

logger.Formatter = new(logrus.JSONFormatter)

f, _ := os.OpenFile("/tmp/test.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
logger.Out = f

}

log level設定してみる

package main

import (
"github.com/Sirupsen/logrus"
"os"
)

func main() {
logger := logrus.New()

logger.Formatter = new(logrus.JSONFormatter)
logger.Level = logrus.Warn

}

これはいい感じかなー、と思ったけど、bunyanさんみたいなcli toolがないのかー。bunyanとうまく共存できないかあとで調べてみる。あと、textフォーマットで勝手にconsole color付けて出力するので、vimとかでゆっくりlog見た時に見づらい、設定させてほしい。

あと、いい感じなのが、hookスクリプトが書ける模様。例えばエラーに対するフックとか。


seelog

とりあえず、設定ファイルがXMLです。なので、それに耐えられないといけない。

あと、デフォルトで非同期出力らしいのでかなり強力か?

XMLにちょっと耐えられないので、一旦保留。


まとめ

とりあえず、logrusがよさげ。コマンドラインで制御する程度のものであればglogがさくっと使えそう。

ただ、実はXMLに抵抗がなければseelogが割りといい感じなのではと思った。設定できる自由度が高めそうだし。