Help us understand the problem. What is going on with this article?

Fluentd Formatter プラグイン入門

More than 5 years have passed since last update.

Fluentd update 2014で言及されている通り、Fluentd に Formatter プラグイン というものが導入されているので、作り方を解説します。

2014/12/14 更新

  • v0.10.58、v0.12.0以降で新APIが生えた[1][2]のでそちらを使うようにサンプルコードを更新

概説

現在サポートしているのは、out_file、out_s3 プラグインだけですが、例えば

<match foo.bar>
  type file
  path /path/to/file
  format ltsv
</match>

のように format パラメタに値(このサンプルでは ltsv)を指定することで、出力形式を変えることができます。これ自体は以前からできたのですが、Formatter プラグインを作成することによって、この format を自由に増やすことができるようになりました。

デフォルト formatter 一覧

現在デフォルトで bundle されている Formatter はコード的にはこの行で定義されており、以下のようになっています。

      'out_file' => Proc.new { OutFileFormatter.new },
      'json' => Proc.new { JSONFormatter.new },
      'msgpack' => Proc.new { MessagePackFormatter.new },
      'ltsv' => Proc.new { LabeledTSVFormatter.new },
      'csv' => Proc.new { CsvFormatter.new },
      'single_value' => Proc.new { SingleValueFormatter.new },

それぞれの使い方は公式ドキュメントが詳しいのでそちらを参照すると良いでしょう。

Formatter プラグインの作り方

さて、本題である Formatter プラグインの作り方ですが、サンプルとして新規に tsv フォーマットを作ってみることにします。cf. 公式ドキュメント

以下のコードを formatter_tsv.rb というファイル名で保存します。ディレクトリは任意ですが、今回は myplugin ディレクトリに保存してみます。

# myplugin/formatter_tsv.rb
module Fluent
  module TextFormatter
    class TSVFormatter < Formatter
      Plugin.register_formatter('tsv', self)

      include Configurable # This enables the use of config_param
      include HandleTagAndTimeMixin # If you wish to use tag_key, time_key, etc.

      def configure(conf)
        super
      end

      def format(tag, time, record)
        "#{record.values.join("\t")}\n"
      end
    end
  end
end

format メソッドに、tag, time, record の3つが渡されてくるので、それを加工して、実際に出力する文字列を返します。今回は TSV フォーマットなので、record ハッシュの値 (values) を取り出して、タブ区切りで出力しています。

また include HandleTagAndTimeMixin しておくと、include_time_key, time_key, time_format, include_tag_key, tag_key, localtime, timezone といったオプションが生えるので便利です。それらのオプションについて詳しくは http://docs.fluentd.org/articles/out_file#format のページを読むと良いでしょう。

動作確認として次のような fluent.conf を書いて

<source>
  forward
</source>

<match raw.**>
  type file
  format tsv
  path /tmp/tsv_test
</match>

fluentd を起動します。plugin をおいたディレクトリを -p オプションで指定します。

$ fluentd -c fluent.conf -p myplugin

fluent-cat でテストデータを送ってみましょう

$ echo '{"a":"foo","b":"bar"}' | fluent-cat raw.test

file プラグインの出力先 /tmp/tsv_test.*

foo[TAB]bar

のように TSV 形式で出力されていれば成功です。

今回は適当なディレクトリにおいて -p オプションでプラグインディレクトリを指定して読み込みましたが、Input プラグインや Output プラグインのように gem にして公開することも可能です。cf. sonots/fluent-plugin-formatter_tsv

Formatter プラグインをサポートするプラグインの作り方

out_file のように Formatter プラグインをサポートする Output プラグインの作り方を解説します。サンプルとして Formatter プラグイン通りに標準出力に print するだけの out_print プラグインを定義してみます。

module Fluent
  class PrintOutput < Output
    Plugin.register_output('print', self)

    config_param :format, :string, :default => 'json'

    def configure(conf)
      super

      @formatter = Plugin.new_formatter(@format)
      @formatter.configure(conf)
    end

    def emit(tag, es, chain)
      es.each do |time, record|
        print @formatter.format(tag, time, record)
      end

      chain.next
    end
  end
end

Plugin.new_formatter でインスタンスを作ります。また、オプションをサポートしている Formatter プラグインのために、#configure メソッドに conf をそのまま渡してあげます。こうしないと大抵の Formatter プラグインが持つ include_time_key オプションなどが効きません。

あとは Formatter プラグインで実装した format メソッドを呼び出して print しているだけです。

おわりに

Formatter プラグインの作り方、および Formatter プラグインをサポートしたプラグインの作り方を紹介しました。

Formatter プラグインをサポートしているのは今の所 out_fileout_s3 ぐらいですが、カスタムフォーマットを独自に定義できるようになったので、是非ご活用ください。

PS. out_stdout も Formatter プラグインをサポートしたほうがよい気がしてきたので、そのうちやります。

sonots
A Ruby, Fluentd, and Chainer Committer. SRE Engineer. Qiitaは小ネタの投稿場所として利用しています。業務コードで、なぜそういう書き方をしているのか解説をQiitaに書いて、コードにはQiitaへのリンクを張る、という使い方をしていることが多いです(自己紹介じゃない)
https://medium.com/@sonots
zozotech
70億人のファッションを技術の力で変えていく
https://tech.zozo.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした