fluent-plugin-geoip というプラグインを使うとfluentdで流れてくるログに含まれるIPアドレスから国名などの地名や経緯度情報を付与できます。
こんな感じのログ
{
"ip":"XXX.XXX.XXX.XXX",
"msg":"Hello",
}
を、こんな感じに変換できます。
{
"ip":"XXX.XXX.XXX.XXX",
"msg":"Hello",
"country_code":"JP",
"country_name":"Japan",
"latitude":35.69,
"longitude":139.69
}
MaxMind社のGeoIPのデータベースを利用しているようです。
インストール
インストール方法はGitHubレポジトリのREADMEに書いてあります。
y-ken/fluent-plugin-geoip: Fluentd output plugin to geolocate with geoip.
gemでfluentdをインストールしてあるのであれば
$ gem install -N fluent-plugin-geoip
※td-agentであれば td-agent-gem
でインストールします。
fluentdの設定ファイル
以下のような設定ファイルで試せます。
<source>
@type tail
path input.txt
pos_file input.pos
tag test
<parse>
@type csv
keys ip,msg
</parse>
</source>
<filter test>
@type geoip
geoip_lookup_keys ip
backend_library geoip2_c
skip_adding_null_record true
<record>
country_code ${country.iso_code["ip"]}
country_name ${country.names.en["ip"]}
latitude ${location.latitude["ip"]}
longitude ${location.longitude["ip"]}
</record>
</filter>
<match test>
@type stdout
</match>
ファイルからのコンマ区切りの入力としています。
試してみる
この設定ファイルでfluentdを起動しておいて、別のターミナルなどで次のようにデータを送ります。 XXX.XXX.XXX.XXX
のところはIPアドレスです。
$ echo "XXX.XXX.XXX.XXX,Hello" >> input.txt
fluentdからは次のように出力されました。
2020-07-18 12:54:04.999460343 +0900 test: {"ip":"XXX.XXX.XXX.XXX","msg":"Hello","country_code":"JP","country_name":"Japan","latitude":35.69,"longitude":139.69}
※経緯度を見ても正確に指しているようには見えませんでしたが、国レベルでは合ってました。
skip_adding_null_record
上記サンプルの設定ファイルでは skip_adding_null_record true
という記述を入れているので、地理情報のないプライベートIPを入れてみると、地理情報のキーは付与されません。
$ echo "192.168.0.1,Hello" >> input.txt
2020-07-18 12:58:01.055174554 +0900 test: {"ip":"192.168.0.1","msg":"Hello"}
設定ファイルから skip_adding_null_record true
を省くと null
として出力されます。
2020-07-18 12:59:55.737619793 +0900 test: {"ip":"192.168.0.1","msg":"Hello","country_code":null,"country_name":null,"latitude":null,"longitude":null}
コマンドラインでGeoIPのデータベースに問い合わせてみる
fluent-plugin-geoipのソースの中に utils/dump.rb
という名前でコマンドラインから簡単にGeoIPを試せるスクリプトがあります。
これを動かすには私の環境では以下のgemを手動でインストールすることが必要でした。
$ gem install -N geoip2_compat
utils/dump.rb
をrubyコマンドで直接呼び出します。
1つ目のパラメータはバックエンドのライブラリを指定するもので、 geoip2
, geoip2_compat
, geoip
の3種類あります。
2つ目のパラメータはIPです。
$ ruby ~/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/fluent-plugin-geoip-1.3.2/utils/dump.rb geoip2 XXX.XXX.XXX.XXX
{"continent"=>
{"code"=>"AS",
"geoname_id"=>6255147,
"names"=>
{"de"=>"Asien",
"en"=>"Asia",
"es"=>"Asia",
"fr"=>"Asie",
"ja"=>"アジア",
"pt-BR"=>"Ásia",
"ru"=>"Азия",
"zh-CN"=>"亚洲"}},
"country"=>
{"geoname_id"=>1861060,
"iso_code"=>"JP",
"names"=>
{"de"=>"Japan",
"en"=>"Japan",
"es"=>"Japón",
"fr"=>"Japon",
"ja"=>"日本",
"pt-BR"=>"Japão",
"ru"=>"Япония",
"zh-CN"=>"日本"}},
"location"=>
{"accuracy_radius"=>500,
"latitude"=>35.69,
"longitude"=>139.69,
"time_zone"=>"Asia/Tokyo"},
"registered_country"=>
{"geoname_id"=>1861060,
"iso_code"=>"JP",
"names"=>
{"de"=>"Japan",
"en"=>"Japan",
"es"=>"Japón",
"fr"=>"Japon",
"ja"=>"日本",
"pt-BR"=>"Japão",
"ru"=>"Япония",
"zh-CN"=>"日本"}}}
$ ruby ~/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/fluent-plugin-geoip-1.3.2/utils/dump.rb geoip2_compat XXX.XXX.XXX.XXX
{:country_code=>"JP",
:country_name=>"Japan",
:latitude=>35.69,
:longitude=>139.69}
$ ruby ~/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/fluent-plugin-geoip-1.3.2/utils/dump.rb geoip XXX.XXX.XXX.XXX
{:country_code=>"JP",
:country_code3=>"JPN",
:country_name=>"Japan",
:latitude=>35.689998626708984,
:longitude=>139.69000244140625}