goでfluentdを使ってlogを吐いてみる
macにfluentdをインストールする
まずは手元の環境にfluentdをインストールする (そこから?!)
公式サイトからインストールする 今回は手元のmacのversionがv10.10なのでtd-agent-v2.1.4-0.dmg
をインストールした
$ which td-agent
/usr/sbin/td-agent
$ td-agent --version
td-agent 0.10.60
インストールした .dmg
のバージョンと td-agent —version
の値が違うのであれ?と思ったけどChangelogを見ると正しいみたい
td-agentを起動してみる
$ td-agent
2016-10-17 12:36:35 +0900 [info]: reading config file path="/etc/td-agent/td-agent.conf"
2016-10-17 12:36:35 +0900 [info]: starting fluentd-0.10.60
2016-10-17 12:36:36 +0900 [info]: gem 'fluent-mixin-config-placeholders' version '0.3.0'
2016-10-17 12:36:36 +0900 [info]: gem 'fluent-mixin-plaintextformatter' version '0.2.6'
2016-10-17 12:36:36 +0900 [info]: gem 'fluent-plugin-mongo' version '0.7.5'
2016-10-17 12:36:36 +0900 [info]: gem 'fluent-plugin-rewrite-tags-filter' version '1.4.1'
2016-10-17 12:36:36 +0900 [info]: gem 'fluent-plugin-s3' version '0.5.3'
2016-10-17 12:36:36 +0900 [info]: gem 'fluent-plugin-scribe' version '0.10.14'
2016-10-17 12:36:36 +0900 [info]: gem 'fluent-plugin-td' version '0.10.25'
2016-10-17 12:36:36 +0900 [info]: gem 'fluent-plugin-td-monitoring' version '0.2.0'
2016-10-17 12:36:36 +0900 [info]: gem 'fluent-plugin-webhdfs' version '0.4.1'
2016-10-17 12:36:36 +0900 [info]: gem 'fluentd' version '0.10.60'
2016-10-17 12:36:36 +0900 [info]: using configuration file: <ROOT>
<match td.*.*>
type tdlog
apikey YOUR_API_KEY
auto_create_table
buffer_type file
buffer_path /var/log/td-agent/buffer/td
<secondary>
type file
path /var/log/td-agent/failed_records
</secondary>
</match>
<match debug.**>
type stdout
</match>
<source>
type forward
</source>
<source>
type http
port 8888
</source>
<source>
type debug_agent
bind 127.0.0.1
port 24230
</source>
</ROOT>
2016-10-17 12:36:36 +0900 [info]: adding source type="forward"
2016-10-17 12:36:36 +0900 [info]: adding source type="http"
2016-10-17 12:36:36 +0900 [info]: adding source type="debug_agent"
2016-10-17 12:36:36 +0900 [info]: adding match pattern="td.*.*" type="tdlog"
2016-10-17 12:36:36 +0900 [info]: adding match pattern="debug.**" type="stdout"
2016-10-17 12:36:36 +0900 [info]: listening fluent socket on 0.0.0.0:24224
2016-10-17 12:36:36 +0900 [info]: listening dRuby uri="druby://127.0.0.1:24230" object="Engine"
```
$ curl -X POST -d 'json={"json":"message"}' http://localhost:8888/debug.test
でhttp経由でlogをポストすると起動したtd-agentの標準出力に
2016-10-17 12:39:32 +0900 debug.test: {"json":"message"}
と出力される
設定ファイルは /etc/td-agent/td-agent.conf
を参照しているので修正したければそのファイルを修正するか起動時にtd-agent -c <config file>
で指定すればよさそう
go-fluentd-loggerを使ってみる
td-agentの準備はできたのでgoから触ってみる サンプルコードもあるのでこれを少し修正してみる
package main
import (
"log"
"github.com/fluent/fluent-logger-golang/fluent"
"github.com/mattn/go-gimei"
)
type Player struct {
ID int
Name string
}
func main() {
logger, err := fluent.New(fluent.Config{FluentPort: 24224, FluentHost: "127.0.0.1"})
if err != nil {
log.Fatalln(err.Error())
}
defer logger.Close()
tags := "debug.player"
for i := 1; i < 100; i++ {
p := Player{
ID: i,
Name: gimei.NewName().Kanji(),
}
err := logger.Post(tags, p)
if err != nil {
log.Println(err.Error())
}
}
log.Println("done")
}
こんなファイルで実行すると
2016-10-17 14:53:52 +0900 debug.player: {"ID":89,"Name":"岡本 紫薫"}
2016-10-17 14:53:52 +0900 debug.player: {"ID":90,"Name":"池上 暖芽"}
2016-10-17 14:53:52 +0900 debug.player: {"ID":91,"Name":"三木 嘉耶"}
2016-10-17 14:53:52 +0900 debug.player: {"ID":92,"Name":"津田 麻月"}
2016-10-17 14:53:52 +0900 debug.player: {"ID":93,"Name":"熊谷 柚和"}
2016-10-17 14:53:52 +0900 debug.player: {"ID":94,"Name":"角田 留治"}
2016-10-17 14:53:52 +0900 debug.player: {"ID":95,"Name":"森川 敬輔"}
2016-10-17 14:53:52 +0900 debug.player: {"ID":96,"Name":"中野 浩紀"}
2016-10-17 14:53:52 +0900 debug.player: {"ID":97,"Name":"小田 征男"}
2016-10-17 14:53:52 +0900 debug.player: {"ID":98,"Name":"岸 暖"}
2016-10-17 14:53:52 +0900 debug.player: {"ID":99,"Name":"菊池 岳人"}
こんな感じのlogを出してくれる
type Player struct {
ID int `msg:"id"`
Name string `msg:"name"`
}
msg
でtagsを指定すると指定したtagsで出力してくれる
2016-10-17 15:04:38 +0900 debug.player: {"id":97,"name":"岡野 浩志"}
2016-10-17 15:04:38 +0900 debug.player: {"id":98,"name":"足立 岳治"}
2016-10-17 15:04:38 +0900 debug.player: {"id":99,"name":"小柳 遼太"}
他にも map[string]interface
形式も対応しているので
logObj := make(map[string]interface{})
logObj["player.name"] = p.Name
logObj["player.id"] = p.ID
err := logger.Post(tags, logObj)
if err != nil {
log.Println(err.Error())
}
2016-10-17 15:26:47 +0900 debug.player: {"player.name":"新田 実喜","player.id":93}
2016-10-17 15:26:47 +0900 debug.player: {"player.name":"前田 俊之","player.id":94}
2016-10-17 15:26:47 +0900 debug.player: {"player.name":"庄司 一樹","player.id":95}
2016-10-17 15:26:47 +0900 debug.player: {"player.name":"中山 敏之","player.id":96}
2016-10-17 15:26:47 +0900 debug.player: {"player.id":97,"player.name":"緒方 靖憲"}
2016-10-17 15:26:47 +0900 debug.player: {"player.name":"島田 智啓","player.id":98}
2016-10-17 15:26:47 +0900 debug.player: {"player.name":"溝口 守理","player.id":99}
こんな感じで出力できる
まとめ
Goでも比較的簡単にfluentdでlogを出力することができる
実際に自分のプロジェクトで使うなら
fluentPrint(logTag string, v...interface{})
みたいに複数structを受け付けられるようにしてfluentPrintのなかでstructを分解し利用するようにすればいいのかなと思います。