Golang logging library

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
* [glog - godoc](http://godoc.org/github.com/golang/glog)
* [glog - github](https://github.com/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()
}
```
これでファイル出力はおｋ。

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

# Sirupsen/logrus
* [logrus-github](https://github.com/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
* [seelog-github](https://github.com/cihub/seelog)
* [seelog-godoc](https://godoc.org/github.com/cihub/seelog)

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

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

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

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

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