fluent-logger-golang を使って Go で Fluentd にログを転送する

Fluentd でログを収集する場合,例えば nginx のアクセスログであれば in_tail で転送したりするけど,アプリケーションログなら選択肢として in_tail だけじゃなくて in_forward もある.アプリケーションから直接 Fluentd にログを転送できる in_forward を知らない人が案外いるなーという印象があって,知っておくと便利なので,簡単にまとめておこうと思う.

docs.fluentd.org

fluent-logger-golang

今回は Go で使える fluent-logger-golang を紹介する.

github.com

README.md にサンプルコードが載っている通り,簡単に Go から Fluentd にログを転送することができる.logger.Post() は自動的に現在時刻を設定するが,もし意図的な時刻を設定したい場合は logger.PostWithTime() を使う.また fluent.New(fluent.Config{}) はデフォルト設定にしていて,必要に応じて fluent.New(fluent.Config{FluentHost: "127.0.0.1", FluentPort: 24224}) のように設定することができる(今回はローカル環境に Fluentd を用意した).

package main

import (
    "fmt"

    "github.com/fluent/fluent-logger-golang/fluent"
)

func main() {
    logger, err := fluent.New(fluent.Config{})
    if err != nil {
        fmt.Println(err)
    }
    defer logger.Close()

    tag := "app.sample"
    var data = map[string]string{
        "key1": "value1",
        "key2": "value2",
        "key3": "value3",
    }

    // ログを転送する
    err = logger.Post(tag, data)
    if err != nil {
        fmt.Println(err)
    }
}

なお logger.Post()logger.PostWithTime() もログとしては interface{} を受けるため,struct をそのままログとして流すこともできる.アプリケーションの要件次第で使い分ければ良いかと.

package main

import (
    "fmt"

    "github.com/fluent/fluent-logger-golang/fluent"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    logger, err := fluent.New(fluent.Config{})
    if err != nil {
        fmt.Println(err)
    }
    defer logger.Close()

    tag := "app.sample"
    var data = Person{"Bob", 20}

    // ログを転送する
    err = logger.Post(tag, data)
    if err != nil {
        fmt.Println(err)
    }
}

動作確認

サクッと動作確認をする場合は,Docker で Fluentd を上げてしまうのが良いかと思う.

github.com

イメージを pull して,以下のように起動する.

$ docker run -d -p 24224:24224 -p 24224:24224/udp -v ~/fluentd:/fluentd/log fluent/fluentd

デフォルトで in_forward の設定が入っているので,アプリケーションを実行するだけで,動作確認をすることができる.

<source>
  @type  forward
  @id    input1
  @label @mainstream
  port  24224
</source>

実際に以下のように出力された.

20171103T043957+0000 app.sample  {"key1":"value1","key2":"value2","key3":"value3"}
20171103T044808+0000    app.sample  {"Name":"Bob","Age":20}

まとめ

アプリケーションログなど,ログの特性によっては in_tail よりも in_forward の方が便利な場合があるので,知っておくと便利だと思う.Go の場合は fluent-logger-golang を使うと簡単に実装することができる.今回,記事を書きながら README.md を見ていたら,サンプルコードの実装が間違っていたので,修正プルリクを出しておいた.

github.com