Y-Ken Studio

新しもの好きのデータエンジニアが四方山話をお届けします。

プレースホルダ設定に対応した fluent-plugin-geoip v0.1.1 をリリースしました

GeoIPを用いてIPアドレスを元に位置情報をレコードに付与するFluentdプラグイン、fluent-plugin-geoip v0.1.1をリリースしました。
今回の目玉は、GeoIP判定対象の複数キー対応化と、プレースホルダ記法への対応するための設定ファイル仕様の変更です。

前回記事はv0.0.4の紹介でしたので、それ以降にリリースしたv0.0.5とv0.0.6とv0.1.0、そしてv0.1.1のリリースノートをまとめたいと思います。

アップデート方法

次の手順でアップデート後、fluentd (td-agent)を再起動してください。

# for fluentd
$ gem install fluent-plugin-geoip --no-ri --no-rdoc

# for td-agent
$ sudo /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-geoip --no-ri --no-rdoc

変更内容概要

v0.0.4とv0.1.1の修正差分より紹介します。

プレースホルダについて

今回導入した<record>...</record>ディレクティブでは、より柔軟なレコード追加が出来るようになります。
実際の設定ファイルのサンプルは次の通りです。

# 従来の設定ファイル記述例
<match input.access>
  type                 geoip
  geoip_lookup_key     host
  enable_key_latitude  geoip_lat
  enable_key_longitude geoip_lon
  enable_key_lonlat    geoip_lonlat
  remove_tag_prefix    input.
  add_tag_prefix       geoip.
</match>

# 今回導入した設定ファイル記述例
<match input.access>
  type                 geoip
  
  # GeoIP判定を行うキーを指定
  ## 2つ以上のキーを対象とする場合には、カンマ区切りで並べます
  geoip_lookup_key     host
  
  # レコードに追加するキーと、その値をそれぞれ指定
  ## 各キーの中にJSON形式で記載すれば、ネスト構造のデータをレコードに追加可能
  <record>
    geoip_lat          ${latitude['host']}
    geoip_lon          ${longitude['host']}
    
    # Array型を追加する場合
    ## elasticsearch+Kibana3構成でbettermapを利用する際に必要となる、
    ## GeoJSONという配列型 [longitude,latitude] を追加する場合の例です
    coordinate         [ ${longitude['host']}, ${latitude['host']} ]
  </record>
  
  # タグの書き換えルールを指定
  ## tagオプション内では${tag}のほか${tag_parts[n]}が利用可能
  ## この例ではinput.accessというタグが、geoip.accessとなります
  tag                  geoip.${tag_parts[1]}
</match>

tag_partsを用いたタグ書き換えの詳細については次の記事が参考になります。

Kibana3のbettermapについては、次のページが参考になります。

そして、次の例はいずれもelasticsearchのgeo point typeにて対応している位置情報のデータ構造です。

<match input.access>
  type                 geoip
  geoip_lookup_key     host
  <record>
    # lat lon as properties
    location_properties  { "lat":${latitude['host']}, "lon":${longitude['host']}}
  
    # lat lon as string
    location_string      ${latitude['host']},${longitude['host']}
    
    # lat lon as array
    location_array       [${longitude['host']},${latitude['host']}]
  </record>
  tag                    geoip.${tag_parts[1]}
</match>

提供するプレースホルダ

lookup_fieldにはgeoip_lookup_keyで指定したフィールドを指定します。
例えばhostに対してのGeoIP判定結果を参照するには、${city['host']}と指定します。

  • ${city[lookup_field]}
  • ${latitude[lookup_field]}
  • ${longitude[lookup_field]}
  • ${country_code3[lookup_field]}
  • ${country_code[lookup_field]}
  • ${country_name[lookup_field]}
  • ${dma_code[lookup_field]}
  • ${area_code[lookup_field]}
  • ${region[lookup_field]}

あとがき

v0.1.0より設定記法の後方互換を維持しつつ、GeoIP判定結果を配列型やネスト構造データに対応することで、様々な要件に対応できるようになりました。
この実装は、プレースホルダ展開後にevalを呼び出せば簡単に実現できますが、それは'eval is evil'と言われる実装です。そのためこのプラグインでは、JSON(Yajl::Parser)を利用しております。

また、<record>...</record>ディレクティブ対応化の実装にはfluent-plugin-record-reformerを参考にしました。@sonotsさん、ありがとうございます。
現段階では互換レイヤーを挟む事で動作しますが、今後enable_key_*を使う設定は廃止予定のため、お手数ですが<record>...</record>ディレクティブへの乗り換えをお願いします。