Fluent-Bit v0.12 リリース
Fluent-Bit v0.12 が2017/08にリリースされました。parser pluginが少しずつ充実してきました。
Fluent-Bit とは?
Cで書かれた軽量なLog forwarder です。どんなソフトかは下記記事を参照して下さい。
おおまかなTopic
- ナノ秒サポート
- in_netif Plugin (送受信パケット数、パケットサイズ収集)
- in_dummy Plugin (テスト用ダミーデータ生成)
- in_systemd Plugin (Systemdのログ収集)
- filter_record_modifier (fieldの追加、余計なfieldの除去)
- filter_parser (任意のfieldをparseして展開)
- out_kafka_rest Plugin (Kafka REST Proxyサーバへの出力)
- parser が型変換をサポート
そのほかもいくつか変更点があります。詳しくは公式のリリースノートを参照してください。
Fluent Bit v0.12.0 - Release Notes
では、個別に追って見ましょう。
ナノ秒サポート
Fluent-bitもナノ秒単位でタイムスタンプを取り扱うようになりました。
$ fluent-bit -i mem -o stdout Fluent-Bit v0.12.0 Copyright (C) Treasure Data [2017/08/21 22:17:46] [ info] [engine] started [0] mem.0: [1503321467.000308167, {"Mem.total"=>3920464, "Mem.used"=>3490564, "Mem.free"=>429900, "Swap.total"=>2064380, "Swap.used"=>0, "Swap.free"=>2064380}] [1] mem.0: [1503321468.000348090, {"Mem.total"=>3920464, "Mem.used"=>3490596, "Mem.free"=>429868, "Swap.total"=>2064380, "Swap.used"=>0, "Swap.free"=>2064380}] [2] mem.0: [1503321469.000500532, {"Mem.total"=>3920464, "Mem.used"=>3490596, "Mem.free"=>429868, "Swap.total"=>2064380, "Swap.used"=>0, "Swap.free"=>2064380}]
従来どおりに秒単位で転送する(Fluentd v0.12系やFluent-Bit v0.11以前 に送信する場合など)
Fluentd v0.12はナノ秒単位のデータを取り扱えません。Fluentd v0.12やFluent-Bit v0.11以前に送信する(Forwardする)場合は、out_forward pluginの設定値Time_as_Integer
をtrueにして使ってください。
[INPUT] Name mem Tag mem [OUTPUT] Name forward Match * Host localhost Time_as_Integer true
in_netif Plugin (送受信パケット数、パケットサイズ収集)
ネットワークパケット数やサイズを定期収集するプラグインです。/proc/net/devを定期的にparseし、送受信パケット数やデータサイズを収集します。
監視するInterface名(e.g. eth0, ens33)が必要になりますので、ifconfigなどで確認の上ご利用ください。なお、verbose
を指定すると取れるだけの情報を収集します。
$ fluent-bit -i netif -p interface=eth0 -o stdout Fluent-Bit v0.12.0 Copyright (C) Treasure Data [2017/08/21 22:32:30] [ info] [engine] started [0] netif.0: [1503322351.000838300, {"eth0.rx.bytes"=>361466756, "eth0.rx.packets"=>270147, "eth0.rx.errors"=>0, "eth0.tx.bytes"=>9581090, "eth0.tx.packets"=>90412, "eth0.tx.errors"=>0}] [1] netif.0: [1503322352.000757569, {"eth0.rx.bytes"=>98, "eth0.rx.packets"=>1, "eth0.rx.errors"=>0, "eth0.tx.bytes"=>98, "eth0.tx.packets"=>1, "eth0.tx.errors"=>0}] [2] netif.0: [1503322353.000829344, {"eth0.rx.bytes"=>98, "eth0.rx.packets"=>1, "eth0.rx.errors"=>0, "eth0.tx.bytes"=>98, "eth0.tx.packets"=>1, "eth0.tx.errors"=>0}]
設定ファイル形式の場合は、下記のような書式で設定します。
[INPUT]
Name netif
Tag netif.all
Interface eth0
in_dummy Plugin (テスト用ダミーデータ生成)
ダミーデータを生成するためのプラグインです。軽めの動作確認やバグ報告時の異常データ作成などに使えます。Fluentdのものを参考に移植しています。
下記のようにJSONでダミーデータを設定可能です。rate
によって1秒間辺りに生成するイベント数を設定できます。
[INPUT] Name dummy Tag dummy.data Dummy {"type":"test", "name":"john", "age":20} Rate 100 [OUTPUT] Name stdout Match *
コマンドラインだと下記のようになります。
$ fluent-bit -i dummy -t dummy.data -p 'dummy={"type":"test", "name":"john", "age":20}' -p rate=100 -o stdout Fluent-Bit v0.12.0 Copyright (C) Treasure Data [2017/08/28 22:05:12] [ info] [engine] started [0] dummy.data: [1503925512.520811870, {"type"=>"test", "name"=>"john", "age"=>20}] [1] dummy.data: [1503925512.530241262, {"type"=>"test", "name"=>"john", "age"=>20}] [2] dummy.data: [1503925512.540228138, {"type"=>"test", "name"=>"john", "age"=>20}]
in_systemd Plugin (Systemdのログ収集)
(TODO)
Systemd · Fluent Bit v0.12 Documentation
filter_record_modifier (fieldの追加、余計なfieldの除去)
filter_record_modifierを使うことでfieldの追加(Record)、削除(Remove_key, Whitelist_key)を行うことができるようになりました。 ユニークな値を付加したり、余計な情報の転送を抑制することで通信量やDiskの使用量を抑える用途に使えます。
Fieldを追加する(hostnameを追加する例)
Record
によってFieldを追加することが出来ます。
下記は環境変数を使ってkeyがhostnameなFieldを追加する例になります。
[INPUT] Name mem Tag mem.local [OUTPUT] Name stdout Match * [FILTER] Name record_modifier Match * Record hostname ${HOSTNAME}
コマンドラインでは下記のように書けます。
$ fluent-bit -i mem -o stdout -F record_modifier -p 'Record=hostname ${HOSTNAME}' -m '*'
出力例は下記のようになります。最後に"hostname"=>"localhost.localdomain"
が追加されていることが分かるかと思います。
[0] mem.local: [1505701696.016712347, {"Mem.total"=>3920464, "Mem.used"=>3508872, "Mem.free"=>411592, "Swap.total"=>2064380, "Swap.used"=>0, "Swap.free"=>2064380, "hostname"=>"localhost.localdomain"}]
Fieldを削除する(memory, swapのused値を削除する)
削除については、Remove_key
もしくは Whitelist_key
で指定できます。
それぞれの違いは、
- Remove_key: 指定されたものを削除する
- Whitelist_key: 指定されたものを残す
点です。
では、memory情報からusedのFieldを削除する例について書いてみます。
[INPUT] Name mem Tag mem.local [OUTPUT] Name stdout Match * [FILTER] Name record_modifier Match * Remove_key Mem.used Remove_key Swap.used
もしくは[FILTER]の箇所を下記のようにWhitelist_key
を使って書くこともできます。
[FILTER] Name record_modifier Match * Whitelist_key Mem.total Whitelist_key Mem.free Whitelist_key Swap.total Whitelist_key Swap.free
これを実行すると、下記のようにMem.used
と Swap.used
が削除されていることが分かります。
[0] mem.local: [1505702284.002455403, {"Mem.total"=>3920464, "Mem.free"=>423088, "Swap.total"=>2064380, "Swap.free"=>2064380}]
参考までにフィルタしない場合の出力例は下記です。
[0] mem.local: [1505702544.015796143, {"Mem.total"=>3920464, "Mem.used"=>3508940, "Mem.free"=>411524, "Swap.total"=>2064380, "Swap.used"=>0, "Swap.free"=>2064380}]
filter_parser (任意のfieldをparseして展開)
parser専用のfilter Pluginが加わりました。今まではin_tailなど一部のinput pluginしかparserをサポートしていませんでした。このfilter_parser を使うことで、任意のinput pluginが生成したFieldをparseすることができます。
下記はin_dummyで生成したFieldをparseする例になります。ここでは、"data":"100 0.5 true This is example"
というFieldを生成しています。parse後は、{"INT"=>"100", "FLOAT"=>"0.5", "BOOL"=>"true", "STRING"=>"This is example"}
というように変換してみましょう。
まず、下記のようにParsers file(parsers.conf)を用意します。dummy_test
というparser名を定義し、正規表現を記述します。名前つきキャプチャを使用することで、展開後のkey名を定義することができます。
[PARSER] Name dummy_test Format regex Regex ^(?<INT>[^ ]+) (?<FLOAT>[^ ]+) (?<BOOL>[^ ]+) (?<STRING>.+)$
そしてconfig fileです。先ほどのParsers fileのパスをParsers_File
として記述する必要があります。
filter_parserの設定としては、Key_Name
でparseするFieldのKey(ここではdata)を指定し、先ほど定義したparser名をParser
によって指定します。
[SERVICE] Parsers_File /path/to/parsers.conf [INPUT] Name dummy Tag dummy.data Dummy {"data":"100 0.5 true This is example"} [FILTER] Name parser Match dummy.* Key_Name data Parser dummy_test [OUTPUT] Name stdout Match *
これを実行すると、下記のように"data":"100 0.5 true This is example"
を各Key-Valueに展開することができます。デフォルトではStringとして展開されますが、後述する機能を使うことで、数値型などに変換することができます。
[0] dummy.data: [1499347993.001371317, {"INT"=>"100", "FLOAT"=>"0.5", "BOOL"=>"true", "STRING"=>"This is example"}]
out_kafka_rest Plugin (Kafka REST Proxyサーバへの出力)
kafkaについては詳しくないので公式ドキュメントを参照して下さい。
Kafka REST Proxy · Fluent Bit v0.12 Documentation
parser が型変換をサポート
parserによって展開された値はデフォルトでは文字列になります。Fluentdライクに型を指定することもできるようになりました。
下記では、"data":"100 0.5 true This is example"
をparseして、integer, float, bool, 文字列に展開する例となります。
Parsers file にて、Types INT:integer FLOAT:float BOOL:bool
のように、types <field_name_1>:<type_name_1> <field_name_2>:<type_name_2> ....
と設定することで型を指定できます。
Fluentd とは異なり、,(コンマ)でなくスペース区切りな点に注意してください。
[PARSER] Name dummy_test Format regex Regex ^(?<INT>[^ ]+) (?<FLOAT>[^ ]+) (?<BOOL>[^ ]+) (?<STRING>.+)$ Types INT:integer FLOAT:float BOOL:bool
config file は filter_parserのものを使用してください。
これによって、下記のように出力されます。細かいですが、ダブルクォート(")が一部無くなっているのが分かるでしょうか。
[0] dummy.data: [1506081688.029663388, {"INT"=>100, "FLOAT"=>0.500000, "BOOL"=>true, "message"=>"This is example"}]
Fluent-Bit v0.11 リリース
Fluent-Bit v0.11 が2017/03にリリースされました。今回のリリースはかなりすごいですよ!
おおまかなTopic
- in_tail Plugin (ログをはじめとするファイルの各行を収集)
- in_disk Plugin (ストレージへの Read/Write アクセスサイズを収集)
- in_proc Plugin (特定プロセスのメモリ使用量やfd消費数を収集)
- out_file Plugin (ファイルへの出力)
- Filter Plugin
- Parser
- out_forward に Secure forward mode追加
- in_memの書式がfree(1)っぽくなりました
あたりでしょうか。他にも色々と新機能がありますので詳しくは公式のリリースノートを参照ください。
Fluent Bit v0.11.0 - Release Notes
では、個別に追って見ましょう。
in_tail Plugin & Parser
本家 Fluentd でも利用頻度が高いと思われるin_tail Plugin、ついにFluent-bitに実装されました! 後述のParser機能と組み合わせることで、お手持ちのログを構造化しつつ転送できます。 ログローテーションや、アスタリスク指定による複数ファイルにも対応しています。
Parser にはOnigmoが、ログファイル内の位置情報を記憶しておくために、sqlite3が使われています。 本家Fluendにはまだまだ及びませんが、プロパティが充実していますので詳しくはドキュメントを参照してください。
Tail · Fluent Bit v0.11 Documentation
in_tail 応用例
Parserを使うことで、ログの各行を構造化することができます。これ非常に強力ですよ。 nginxやApacheのParserはデフォルトで入っていますので、下記のファイルを使いましょう。 おおまかにはParserファイルを指定し、そのファイルの中のどの正規表現を使うか更に指定する流れになります。
fluent-bit/parsers.conf at master · fluent/fluent-bit · GitHub
では、nginxのログをパースして構造化してみましょう。 サンプルのログは下記から取得してみました。
-R オプションでparsers.confを指定し、その中に書かれている定義を、in_tailの"parser"プロパティで指定します。 コマンドラインでのサンプルは下記です。下記のようにログ一行が構造化されている様子が分かるかと思います。
$ fluent-bit -i tail -p 'path=./nginx_logs' -p parser=nginx -R ../conf/parsers.conf -o stdout Fluent-Bit v0.11.0 Copyright (C) Treasure Data [2017/04/04 23:32:12] [ info] [engine] started [0] tail.0: [1431817532, {"remote"=>"93.180.71.3", "host"=>"-", "user"=>"-", "method"=>"GET", "path"=>"/downloads/product_1", "code"=>"304", "size"=>"0", "referer"=>"-", "agent"=>"Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"}] [1] tail.0: [1431817523, {"remote"=>"93.180.71.3", "host"=>"-", "user"=>"-", "method"=>"GET", "path"=>"/downloads/product_1", "code"=>"304", "size"=>"0", "referer"=>"-", "agent"=>"Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"}] [2] tail.0: [1431817524, {"remote"=>"80.91.33.133", "host"=>"-", "user"=>"-", "method"=>"GET", "path"=>"/downloads/product_1", "code"=>"304", "size"=>"0", "referer"=>"-", "agent"=>"Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.17)"}] [3] tail.0: [1431817534, {"remote"=>"217.168.17.5", "host"=>"-", "user"=>"-", "method"=>"GET", "path"=>"/downloads/product_1", "code"=>"200", "size"=>"490", "referer"=>"-", "agent"=>"Debian APT-HTTP/1.3 (0.8.10.3)"}] [4] tail.0: [1431817509, {"remote"=>"217.168.17.5", "host"=>"-", "user"=>"-", "method"=>"GET", "path"=>"/downloads/product_2", "code"=>"200", "size"=>"490", "referer"=>"-", "agent"=>"Debian APT-HTTP/1.3 (0.8.10.3)"}]
設定ファイルは下記。適宜ファイルパスを置き換えてください。
[SERVICE] Parsers_File /path/to/parsers.conf [INPUT] Name tail Path /path/to/nginx_logs # nginx is defined parsers.conf Parser nginx [OUTPUT] Name stdout Match *
in_disk Plugin
ストレージへのRead/Write アクセスサイズを定期収集するプラグインが追加されました。 内部的には/proc/diskstatsを定期的に読み出し、前回からの差分サイズを計算・収集しています。*1 デフォルトでは、/proc/diskstats全てのアクセスについて対象としていますが、 “dev_name” プロパティを指定することでアクセス対象を限定することが出来ます。(e.g. -p dev_name=sda3 のような感じです。)
$ fluent-bit -i disk -p dev_name=sda3 -o stdout Fluent-Bit v0.11.0 Copyright (C) Treasure Data [2017/01/28 16:58:16] [ info] [engine] started [0] disk.0: [1485590297, {"read_size"=>0, "write_size"=>0}] [1] disk.0: [1485590298, {"read_size"=>0, "write_size"=>0}] [2] disk.0: [1485590299, {"read_size"=>0, "write_size"=>0}] [3] disk.0: [1485590300, {"read_size"=>0, "write_size"=>11997184}]
設定ファイル形式の場合は、下記のような書式で設定します。
[INPUT] Name disk Tag disk.all Dev_Name sda3
in_proc Plugin
特定プロセスのメモリ使用量等を収集するプラグインになります。例えば、プロセスのリーク監視に使えるかと思います。 mem.*というキーで、/proc/PID/statusの各種メモリ使用量を収集します。*2 各々の値の詳細はman procを参照してください。オープン中のfd個数も収集します。
$ fluent-bit -i proc -p proc_name=fluent-bit -o stdout Fluent-Bit v0.11.0 Copyright (C) Treasure Data [2017/01/30 21:44:56] [ info] [engine] started [0] proc.0: [1485780297, {"alive"=>true, "proc_name"=>"fluent-bit", "pid"=>10964, "mem.VmPeak"=>14740000, "mem.VmSize"=>14740000, "mem.VmLck"=>0, "mem.VmHWM"=>1120000, "mem.VmRSS"=>1120000, "mem.VmData"=>2276000, "mem.VmStk"=>88000, "mem.VmExe"=>1768000, "mem.VmLib"=>2328000, "mem.VmPTE"=>68000, "mem.VmSwap"=>0, "fd"=>18}] [1] proc.0: [1485780298, {"alive"=>true, "proc_name"=>"fluent-bit", "pid"=>10964, "mem.VmPeak"=>14740000, "mem.VmSize"=>14740000, "mem.VmLck"=>0, "mem.VmHWM"=>1148000, "mem.VmRSS"=>1148000, "mem.VmData"=>2276000, "mem.VmStk"=>88000, "mem.VmExe"=>1768000, "mem.VmLib"=>2328000, "mem.VmPTE"=>68000, "mem.VmSwap"=>0, "fd"=>18}] [2] proc.0: [1485780299, {"alive"=>true, "proc_name"=>"fluent-bit", "pid"=>10964, "mem.VmPeak"=>14740000, "mem.VmSize"=>14740000, "mem.VmLck"=>0, "mem.VmHWM"=>1152000, "mem.VmRSS"=>1148000, "mem.VmData"=>2276000, "mem.VmStk"=>88000, "mem.VmExe"=>1768000, "mem.VmLib"=>2328000, "mem.VmPTE"=>68000, "mem.VmSwap"=>0, "fd"=>18}] [3] proc.0: [1485780300, {"alive"=>true, "proc_name"=>"fluent-bit", "pid"=>10964, "mem.VmPeak"=>14740000, "mem.VmSize"=>14740000, "mem.VmLck"=>0, "mem.VmHWM"=>1152000, "mem.VmRSS"=>1148000, "mem.VmData"=>2276000, "mem.VmStk"=>88000, "mem.VmExe"=>1768000, "mem.VmLib"=>2328000, "mem.VmPTE"=>68000, "mem.VmSwap"=>0, "fd"=>18}]
out_file Plugin
収集したデータをファイルに吐き出すことができるプラグインです。現在はJSONフォーマットのみの出力になります。 出力先のファイル名は"path"プロパティで指定可能ですが、未指定の場合はタグ名でファイルを生成します。
$ fluent-bit -i mem -o file Fluent-Bit v0.11.0 Copyright (C) Treasure Data [2017/04/04 22:58:50] [ info] [engine] started ^C[engine] caught signal
mem.0というタグ名でファイルが出力されますので、catしてみます。
$ cat mem.0 mem.0: [1491314331, {"Mem.total":1016044, "Mem.used":772140, "Mem.free":243904, "Swap.total":2064380, "Swap.used":149084, "Swap.free":1915296}] mem.0: [1491314332, {"Mem.total":1016044, "Mem.used":772172, "Mem.free":243872, "Swap.total":2064380, "Swap.used":149084, "Swap.free":1915296}] mem.0: [1491314333, {"Mem.total":1016044, "Mem.used":772172, "Mem.free":243872, "Swap.total":2064380, "Swap.used":149084, "Swap.free":1915296}] mem.0: [1491314334, {"Mem.total":1016044, "Mem.used":772148, "Mem.free":243896, "Swap.total":2064380, "Swap.used":149084, "Swap.free":1915296}]
設定ファイルによる指定は下記のような感じです。
[OUTPUT] Name file Match * Path output.txt
Filter Plugin
Filter Pluginのサポートが入りました。v0.11ではfilter_stdout, filter_grep, filter_kubernetesが使用可能です。 余剰な情報をフィルタすることで、過度なログ転送を抑制することができ、送信先の負荷を減らすことができます。
filter_grep
正規表現を使い、マッチするログのみ送信(Regex)、マッチするログのみ抑制(Exclude)することができます。
設定ファイルの例は下記。in_tailの例に併せて404のログのみ出力してみましょう。
[SERVICE] Parsers_File /path/to/parsers.conf [INPUT] Name tail Path /path/to/nginx_logs Parser nginx [FILTER] Name grep Match * Regex code 404 [OUTPUT] Name stdout Match *
出力例は下記です。404なログのみ出力されていることがお分かり頂けるでしょうか。 逆に404のログだけ除外したい場合は、上記設定ファイルの"Regex"を"Exclude"と置き換えてみてください。
$ fluent-bit -c tail.conf Fluent-Bit v0.11.0 Copyright (C) Treasure Data [2017/04/04 23:52:06] [ info] [engine] started [0] tail.0: [1431817502, {"remote"=>"217.168.17.5", "host"=>"-", "user"=>"-", "method"=>"GET", "path"=>"/downloads/product_2", "code"=>"404", "size"=>"337", "referer"=>"-", "agent"=>"Debian APT-HTTP/1.3 (0.8.10.3)"}] [1] tail.0: [1431817542, {"remote"=>"217.168.17.5", "host"=>"-", "user"=>"-", "method"=>"GET", "path"=>"/downloads/product_1", "code"=>"404", "size"=>"332", "referer"=>"-", "agent"=>"Debian APT-HTTP/1.3 (0.8.10.3)"}] [2] tail.0: [1431817545, {"remote"=>"46.4.66.76", "host"=>"-", "user"=>"-", "method"=>"GET", "path"=>"/downloads/product_1", "code"=>"404", "size"=>"318", "referer"=>"-", "agent"=>"Debian APT-HTTP/1.3 (1.0.1ubuntu2)"}] [3] tail.0: [1431817526, {"remote"=>"93.180.71.3", "host"=>"-", "user"=>"-", "method"=>"GET", "path"=>"/downloads/product_1", "code"=>"404", "size"=>"324", "referer"=>"-", "agent"=>"Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"}] [4] tail.0: [1431817538, {"remote"=>"37.26.93.214", "host"=>"-", "user"=>"-", "method"=>"GET", "path"=>"/downloads/product_2", "code"=>"404", "size"=>"319", "referer"=>"-", "agent"=>"Go 1.1 package http"}] [5] tail.0: [1431817511, {"remote"=>"93.180.71.3", "host"=>"-", "user"=>"-", "method"=>"GET", "path"=>"/downloads/product_1", "code"=>"404", "size"=>"340", "referer"=>"-", "agent"=>"Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"}]
filter_kubernetes
すいません、kubernetesに疎いのでドキュメントに丸投げします。メタデータの付加をしてくれる?そうです。
当初は組み込みにフォーカスしていたFluent-bitですが、軽量コンテナ内にも居場所を見つけたようなので、そこ向けの機能かと思われます。
Kubernetes · Fluent Bit v0.11 Documentation
out_forward に Secure forward mode追加
従来は平文通信のみだったのですが、TSL/SSLによる暗号通信にも対応したようです。 手元では試せていませんが、ドキュメントに詳しい設定方法がありますので参照ください。 Fluentdと同様に、基本的にSecure forward modeで運用することが推奨されていくと思われます。
Forward · Fluent Bit v0.11 Documentation
余談ですが、v0.11ではOutput側のみサポートで、Input側(つまりin_forward)はSecure forward には対応してなさげです。
in_memの書式がfree(1)っぽくなりました
in_memの書式がfree(1)っぽくなり、併せてSwap量も出力するようになりました。なお、単位はKBです。
$ fluent-bit -i mem -t memory -o stdout -m '*' Fluent-Bit v0.11.0 Copyright (C) Treasure Data [2017/03/03 21:12:35] [ info] [engine] started [0] memory: [1488543156, {"Mem.total"=>1016044, "Mem.used"=>841388, "Mem.free"=>174656, "Swap.total"=>2064380, "Swap.used"=>139888, "Swap.free"=>1924492}] [1] memory: [1488543157, {"Mem.total"=>1016044, "Mem.used"=>841420, "Mem.free"=>174624, "Swap.total"=>2064380, "Swap.used"=>139888, "Swap.free"=>1924492}] [2] memory: [1488543158, {"Mem.total"=>1016044, "Mem.used"=>841420, "Mem.free"=>174624, "Swap.total"=>2064380, "Swap.used"=>139888, "Swap.free"=>1924492}] [3] memory: [1488543159, {"Mem.total"=>1016044, "Mem.used"=>841420, "Mem.free"=>174624, "Swap.total"=>2064380, "Swap.used"=>139888, "Swap.free"=>1924492}]
そのほか
他にもElasticSearch用のoutput PluginがLogstashフォーマットに対応したり、ネストしている出力にも対応したりしています。
余談
今回のリリースですが、なんとメインコミッタの@edsiperさんがプレゼン中にリリースしたとのこと! そんな技があったとは。
@edsiper just released fluent-bit 0.11.0 from the speaker table during his talk! #fluentd #fluentbit pic.twitter.com/YvuHYCg1k9
— tagomoris (@tagomoris) 2017年3月30日
IoTや組み込み向けのデータコレクタ、FluentBitについて
FluentBitとは
IoT機器や組み込み機器を対象としたオープンソースのデータコレクタです。名前から分かる通り、Fluentdの兄弟アプリで、Treasure Dataのエンジニアが中心となって開発が進められています。 このソフトでは、例えば、
といったことが可能です。
名前はFluent-Bitだったり、Fluent Bitだったり、FluentBitだったり、様々な記載が見受けられます。
特徴
本家のFluentdと比べて次のような特徴があります。
- C言語で実装されているため、Rubyが無い環境でも動作する
- 軽量・高速(らしい)*1
- C API経由で自前のアプリからデータを流せる/受け取れる
- ビルドオプションで様々にカスタマイズ可能(Plugin削減やクロスコンパイルなど)
どう使うか
IoT機器のデータをFluentdに集める用途に使われるのではないでしょうか。in_lib
やin_head
でセンサデータを取得し、out_forward
で送信する使い方です。Fluentdに一旦送信できれば、強力で多彩なFluentdのOutput Pluginを使い、より多様な送信先にセンサデータを転送できるので。
Input Plugin
2016年9月現在、下記のプラグインがサポートされています。
in_cpu
: CPU使用率in_mem
: メモリ使用量in_kmsg
: カーネルログバッファ(/dev/kmsg)in_serial
: シリアル入力in_stdin
: 標準入力in_mqtt
: MQTTin_head
: ファイルin_xbee
: xbeein_forward
: Fluentdプロトコルin_random
: ランダム値を生成in_lib
: C API経由でデータをPushするために使う
Output Plugin
2016年9月現在、下記のプラグインがサポートされています。
out_es
: Elasticsearchout_forward
: Fluentdプロトコルout_http
: HTTP出力out_null
: データ破棄用out_stdout
: 標準出力out_td
: Treasure Dataout_nats
: NATS用out_lib
: C API経由でデータを取得するために使う
使い方1: コマンドとして使う
後述のビルドを行うと、fluent-bitという実行ファイルが生成されます。使い方はシンプルで-i
で入力元を、-o
で出力先を指定し、実行するだけです。
例えば、CPU使用率を標準出力に出力する場合は、下記のようになります。
$ fluent-bit -i cpu -o stdout
Fluentdのように、ネットワーク経由の場合は下記のようにサーバ名やポートを指定できます。
$ fluent-bit -i cpu -o forward://127.0.0.1:12225
-c
オプションを使うことでコンフィグファイルを食わせて実行させることもできます。conf
ディレクトリにサンプルが含まれているので確認してみて下さい。
$ fluent-bit -c fluent-bit.conf
Fluentdとはフォーマットが異なりますが、下記のような内容になります。[INPUT]
や[OUTPUT]
はPluginごとに指定可能なパラメータが異なるので、詳しくは公式Documentを参照してください。
[SERVICE]
Log_Level info
Flush 5
[INPUT]
Name cpu
Tag cpu.local
[OUTPUT]
Name stdout
Match **
使い方2: 共有ライブラリとして使う
FluentBitは共有ライブラリとしても提供されている為、他のアプリケーションからFluentBitに一度ログを送信し、FluentBitからFluentdに送信してもらう、といった使い方が可能です。
C APIからデータを入力/出力するには、それぞれin_lib
、out_lib
プラグインを使用します。
下記のAPIが公開されています。
in_lib
経由で自前のデータをPushし、out_lib
に登録したコールバック関数my_stdout
でデータを受け取り標準出力に出力するサンプルです。
#include <unistd.h> #include <fluent-bit.h> #include <msgpack.h> /* out_lib用のコールバック関数 */ int my_stdout(void* data, size_t size) { printf("[%s]",__FUNCTION__); msgpack_object_print(stdout, *(msgpack_object*)data); printf("\n"); /* User has to release the buffer. */ free(data); return 0; } int main() { int i; int n; char tmp[256]; flb_ctx_t *ctx; flb_input_t *input; flb_output_t *output; /* Initialize library */ ctx = flb_create(); /* コンテキスト生成 */ if (!ctx) { exit(EXIT_FAILURE); } input = flb_input(ctx, "lib", NULL); /* Input Plugin in_libを有効化 */ flb_input_set(input, "tag", "test", NULL); /* Input Plugin の設定を行う。可変引数の最後には番兵としてNULLを与える */ output = flb_output(ctx, "lib", my_stdout);/* Output Plugin out_libを有効化。out_libは第三引数としてコールバック関数を与えられる */ flb_output_set(output, "match", "test", NULL);/* Output Plugin の設定を行う。可変引数の最後には番兵としてNULLを与える */ /* Start the background worker */ flb_start(ctx);/* サービス開始 */ /* Push some data */ for (i = 0; i < 100; i++) { n = snprintf(tmp, sizeof(tmp) - 1, "[%lu, {\"key\": \"val %i\"}]", time(NULL), i); flb_lib_push(input, tmp, n); /* データPush */ } flb_stop(ctx); /* サービス停止 */ /* Release Resources */ flb_destroy(ctx);/* コンテキスト破棄 */ return 0; }
他にもexamples
にC APIを使ったサンプルが複数ありますので、確認してみて下さい。
ビルド方法(基本)
ビルドするにはCMakeが必要ですので、予めインストールしておきましょう。
ソース取得、cmake、makeという流れでビルドできます。
masterはビルドエラーになる場合があるので、バージョンタグから引っ張ってくるか、公式サイトからtarballを取得した方が良いでしょう。
$ git clone https://github.com/fluent/fluent-bit.git $ cd build $ cmake .. $ make
ビルド方法(応用)
CMake時に-Dオプションを付けることで、Pluginをそぎ落としてサイズ縮小を図ったり、デバッグビルドを試したりすることができます。
Pluginを減らして、ファイルサイズを小さくする
FluentBitは組み込みを意識しているため、余剰なPluginを削減し、ファイルサイズを抑えたくなりがちです。 下記はInput Pluginの一つ、in_cpuを削減する例になります。
$ cmake .. -DFLB_IN_CPU=No $ make
テストを実行する
FluentBitはGoogleTestを使い、UnitTestを行うことができます。
$ cmake -DFLB_TESTS=yes .. $ make $ make test
クロスコンパイルする
公式にはArmadillo向けのクロスコンパイル用の設定ファイルが含まれていますが、CMakeのお作法に則れば、他のプラットフォームに向けてもクロスコンパイル可能です。
以下は、RaspberryPi 2向けにクロスコンパイルする方法です。
下記をCrossCompile.cmakeというファイルに保存し、適宜CMAKE_FIND_ROOT_PATH
のパスを変更しておきます。
set (CMAKE_SYSTEM_NAME Linux ) set (CMAKE_FIND_ROOT_PATH /PATH/TO/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian ) set (CMAKE_C_COMPILER ${CMAKE_FIND_ROOT_PATH}/bin/arm-linux-gnueabihf-gcc ) set (CMAKE_CXX_COMPILER ${CMAKE_FIND_ROOT_PATH}/bin/arm-linux-gnueabihf-g++ ) set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
CMake実行時に、-DCMAKE_TOOLCHAIN_FILE
として上記ファイルパスを指定しましょう。
$ cmake .. -DCMAKE_TOOLCHAIN_FILE=./CrossCompile.cmake -DFLB_OUT_TD=No $ make
成功すれば、下記のようにARM向けのバイナリができているはずです。
$ file bin/fluent-bit bin/fluent-bit: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, not stripped
リンク
公式サイト http://fluentbit.io/
公式ドキュメント http://fluentbit.io/documentation/
*1:v0.8.5のリリースノートによると、500kレコード/秒を処理できるとのこと
freeし忘れた領域を教えてくれるmtrace
mtraceについてのメモ。
何ができるのか
mallocして、freeし忘れたと思われる領域をピックアップしてくれる。 ただし、GNU拡張機能なので、どこの環境でも使えるわけではない。
どうやるのか
3行のソース修正、デバッグオプションビルド、トレースしながら実行、解析
の順に行う。
1. ソース修正
下記三行を追加する。
- mcheck.hをinclude。
- トレース開始地点にmtrace();
- トレース終了地点にmuntrace();
2. ビルド
-g オプションを付けてデバッグビルドするだけ。
$ gcc -g test.c
3. 実行
MALLOC_TRACE環境変数で、トレース結果の出力先を指定してから実行する。
$ MALLOC_TRACE=output.txt ./a.out
4. 解析
mtraceコマンドにトレース結果ファイルとトレース対象のバイナリを引数として与えて解析する。 mtraceコマンドは、CentOSの場合は、glibc-utilsに含まれている。
free忘れと思われるアドレス、サイズ、呼び元が出力される。 よそのライブラリ内部など、デバッグビルドしていない箇所が呼び元の場合、実行アドレスのみの表示になるようだ。
$ mtrace a.out output.txt
サンプル
下記サンプルコードでお試し。
#include <stdlib.h> #include <mcheck.h> int main(void){ int i; char* p_str = NULL; mtrace(); for(i=0; i<10; i++){ p_str = (char*)malloc(sizeof(char)*4);/* LEAK */ } muntrace(); return 0; }
これを-gオプションを付けてコンパイル。
$ gcc -g test.c
トレース結果の出力先を指定して実行。
$ MALLOC_TRACE=./trace.txt ./a.out
mtraceコマンドで出力結果を解析。
下記のようにアドレス、サイズ、呼び元が出力される。
$ mtrace a.out trace.txt Memory not freed: ----------------- Address Size Caller 0x00000000020d4460 0x4 at /home/.../mtrace_test/test.c:11 0x00000000020d4480 0x4 at /home/.../mtrace_test/test.c:11 0x00000000020d44a0 0x4 at /home/.../mtrace_test/test.c:11 0x00000000020d44c0 0x4 at /home/.../mtrace_test/test.c:11 0x00000000020d44e0 0x4 at /home/.../mtrace_test/test.c:11 0x00000000020d4500 0x4 at /home/.../mtrace_test/test.c:11 0x00000000020d4520 0x4 at /home/.../mtrace_test/test.c:11 0x00000000020d4540 0x4 at /home/.../mtrace_test/test.c:11 0x00000000020d4560 0x4 at /home/.../mtrace_test/test.c:11 0x00000000020d4580 0x4 at /home/.../mtrace_test/test.c:11 $
GithubでPull Requestするまで
ARMでメモリテスト Raspberry Pi2 でLinuxのearly_memtest
Linux Kernel 4.1からARMでもearly_memtest可能になった
メモリチェックソフトとしてはmemtest86が有名だけれど、このソフトのチェック処理はX86のアセンブラで書かれており、ARM上では動作しない。
移植作業はホネが折れるがメモリテストはしておきたい。
と、そんな折、Linux Kernel 4.1からARMのmm初期化処理になにやらearly_memtestの文字が。
4.0まではx86限定?だったCONFIG_MEMTESTがARMでも使えるようになったっぽい。
ということでLinux Kernelのメモリテストを試してみる。
4.1のカーネルソースを取得
2015/07時点で、Raspberry Piの4.1カーネルは実験版のようだ。
Raspberry Pi2のカーネルソースは下記から取得して、4.1系のブランチをチェックアウトする。
4.1系は、rpi-4.1.yというブランチで管理されていたので、下記コマンドでブランチを取得した。
$ git clone https://github.com/raspberrypi/linux.git
$ git checkout -b rpi-4.1.y origin/rpi-4.1.y
ツールチェインをチェックアウトしていない場合は、それもチェックアウトする。
$ git clone https://github.com/raspberrypi/tools.git
MEMTESTのconfigを有効にする
デフォルトのconfigをLoadしてからMEMTEST設定を有効化する。
$ make ARCH=arm bcm2709_defconfig $ make ARCH=arm menuconfig
から、Kernel hackingを選択し、Memtestを選び、設定を有効化する。
カーネルのクロスコンパイル
Raspberry Pi 2 カーネル4.0.7のクロスコンパイルメモ - カッコ仮メモ置き
におおよそのことは書いてあるので、参考にしてコマンドをポチポチしていく。
下記でコンパイルして。
$ make ARCH=arm CROSS_COMPILE=../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- zImage modules dtbs $ scripts/mkknlimg arch/arm/boot/zImage temp/kernel7.img
下記でtemp以下に必要なものを集める。
$ mkdir temp $ mkdir temp/overlays $ make ARCH=arm CROSS_COMPILE=../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- INSTALL_MOD_PATH=./temp modules_install $ cp arch/arm/boot/dts/*.dtb temp $ cp arch/arm/boot/dts/overlays/*.dtb* temp/overlays $ cp arch/arm/boot/dts/overlays/README temp/overlays $ rm temp/lib/modules/4.1.2-v7+/source temp/lib/modules/4.1.2-v7+/build
インストール
上記のtempをscpなどでRaspberry Pi2に転送して、下記コマンドを実行する。
$ sudo cp temp/kernel7.img /boot/kernel7.img $ sudo cp -r temp/lib / $ sudo chown -R root /lib/modules $ sudo chgrp -R root /lib/modules $ sudo cp temp/*dtb /boot $ sudo cp -r temp/overlays/ /boot
pi@raspberrypi ~ $ uname -a Linux raspberrypi 4.1.2-v7+ #4 SMP PREEMPT Fri Jul 24 20:20:26 JST 2015 armv7l GNU/Linux
cmdline設定
menuconfigのhelpによると、cmdlineにてmemtest=という記述をして回数を指定する必要があるらしい。
/boot/cmdline.txtにmemtest=2を追記してみる。
pi@raspberrypi ~ $ sudo vi /boot/cmdline.txt pi@raspberrypi ~ $ cat /boot/cmdline.txt dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait memtest=2
memtestの動作確認結果
dmesgに下記のような出力がなされていれば動いているはず。
memtestを回すようにcmdline設定すると、起動後もシングルコアのままになる問題があったが、ひとまずスルーする。
pi@raspberrypi ~ $ dmesg <中略> [ 0.000000] early_memtest: # of tests: 2 [ 0.000000] 0000000000 - 0000000100 pattern ffffffffffffffff [ 0.000000] 0000008000 - 0000008240 pattern ffffffffffffffff [ 0.000000] 000091f74c - 003a7f2000 pattern ffffffffffffffff [ 0.000000] 003a7ff000 - 003a7ffe48 pattern ffffffffffffffff [ 0.000000] 0000000000 - 0000000100 pattern 0000000000000000 [ 0.000000] 0000008000 - 0000008240 pattern 0000000000000000 [ 0.000000] 000091f74c - 003a7f2000 pattern 0000000000000000 [ 0.000000] 003a7ff000 - 003a7ffe48 pattern 0000000000000000 <中略>
どのようなテストか
実装はmm/memtest.cにある。
予め決まったパターンで8byteごとに値を書きこみ、その後の読み出しで化けていないかをチェックしているようだ。 パターンは4bit周期で0x0から0xfを繰り返した16パターンと、ASCIIでyeah ;-)となる数字列の17パターン。
ループ回数ごとに17パターンのうちのどれかを実施するようで、非常にシンプルなテスト。
memtest86+ほどの検知力は期待しない方が良いかも?
NGな領域があった場合は
ソースによると、下記のような文言が出力されるようだ。
static void __init reserve_bad_mem(u64 pattern, phys_addr_t start_bad, phys_addr_t end_bad) { printk(KERN_INFO " %016llx bad mem addr %010llx - %010llx reserved\n", (unsigned long long) pattern, (unsigned long long) start_bad, (unsigned long long) end_bad); memblock_reserve(start_bad, end_bad - start_bad); }
Raspberry Pi2 Model B ボード&ケースセット (Standard, Clear)
- 出版社/メーカー: TechShare
- メディア: エレクトロニクス
- この商品を含むブログ (5件) を見る
Raspberry Pi 2 カーネル4.0.7のクロスコンパイルメモ
(参考サイト)
Kernel Building - Raspberry Pi Documentation
RaspberryPi - Raspberry Piのカーネルをクロスコンパイルする - Qiita
Raspberry Pi2のカーネルの再構築とGW-450Dを使えるようにする。 - 石を売る
raspberry pi 2のカーネルソースとツール取得
githubから取得。git pullしないなら--depth 1 をつけた方が早く取得できると思う。
$ git clone https://github.com/raspberrypi/linux.git $ git clone https://github.com/raspberrypi/tools.git
取得した時点で4.0.7だった。
pi@raspberrypi ~ $ uname -a Linux raspberrypi 4.0.7-v7+ #3 SMP PREEMPT Wed Jul 8 23:31:48 JST 2015 armv7l GNU/Linux
環境構築 CentOS 6.6 x86_64
いろいろと怒られたので、zlib.i686とlibstdc++.i686をyumで導入した。
$ sudo yum install zlib.i686 libstdc++.i686
ビルド
config設定
下記コマンドでデフォルトのコンフィグで.configが生成される。旧Raspberry Piの場合は引数が違うらしいので注意。
$ make ARCH=arm bcm2709_defconfig
カーネル、カーネルモジュール、デバイスツリーのビルド
gitで取得したtoolsのパスをCROSS_COMPILE以降に適切に入力する。
64bit CentOSでトライしたものの、x64だとライブラリが不足していたので32bitツールチェインでコンパイルした。
$ make ARCH=arm CROSS_COMPILE=../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- zImage modules dtbs
コンパイルされたものを集める
適当なディレクトリを作っておいて、そちらにモジュールやらカーネルイメージやらを集める。 下記のコマンドだとtemp以下に集まる。
$ mkdir temp $ mkdir temp/overlays $ make ARCH=arm CROSS_COMPILE=../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- INSTALL_MOD_PATH=./temp modules_install $ scripts/mkknlimg arch/arm/boot/zImage temp/kernel7.img $ cp arch/arm/boot/dts/*.dtb temp $ cp arch/arm/boot/dts/overlays/*.dtb* temp/overlays $ cp arch/arm/boot/dts/overlays/README temp/overlays
sourceとbuildのシンボリックリンクが出来ていたので、転送サイズを減らすためにも消しておく。
シンボリックリンクを削除するので、パスの最後に/を付けないように注意。
$ rm temp/lib/modules/4.0.7-v7+/source temp/lib/modules/4.0.7-v7+/build
インストール
Raspberry Pi2の場合、カーネルイメージは/boot/kernel7.imgらしい。7が付いていない方は旧Raspberry Pi用とのこと。
適当なディレクトリ下に集めた雑多なファイルをRaspberry Pi2にscpして、下記コマンドをRaspberry Pi上で実行する。
$ sudo cp temp/kernel7.img /boot/kernel7.img $ sudo cp -r temp/lib / $ sudo chown -R root /lib/modules $ sudo chgrp -R root /lib/modules $ sudo cp temp/*dtb /boot $ sudo cp -r temp/overlays/ /boot
終わったら再起動する。失敗すると虹色画面で止まってしまうので、LED点灯が消えたら電源OFFして、SDカードの中身を修復してやりなおし。
Raspberry Pi2 Model B ボード&ケースセット (Standard, Clear)
- 出版社/メーカー: TechShare
- メディア: エレクトロニクス
- この商品を含むブログ (5件) を見る