2019年10月4日金曜日

Kibana でフィールドを分割して新しいフィールドとして登録する方法

概要

普通にやろうとすれば td-agent 側の format を使ってフィールドに分割すると思います
何らかの理由で td-agent 側が操作できない場合は Kibana 側だけでも解決することができます
Kibana の Scripted field という機能を使います

環境

  • macOS 10.14.6
  • Kibana 7.4.0

Scripted field とは

簡単に言えば特定のフィールに対して Groovy を使って値を抽出する方法です
文字列を分割したり数値のフィールド同士を計算した結果を新しいフィールドとして登録することができます

fielddata=true にする

今回は Scripted field でテキストのフィールドを扱おうと思います
実は ElasticSearch はデフォルトだとテキストのフィールドに対して Scripted field を使うことができます
なので ElasticSearch のマッピングに fielddata=true フラグを設定する必要があります

例えば fluentd という名前のインデックスのマッピングで log というテキストフィールドがある場合にこのフィールドに対して fielddata=true を設定する場合は以下のようなクエリを ElasticSearch に対して投げます

curl -X PUT "localhost:9200/fluentd/_mapping?pretty" -H 'Content-Type: application/json' -d'
{
  "properties": {
    "log": { 
      "type":     "text",
      "fielddata": true
    }
  }
}
'

インデックス名やフィールド名を適宜変更して fielddata=true にしましょう

Scripted field の作成

まずは Kibana の Index Patterns にアクセスします
そして該当のインデックスを選択し「Scripted fields」タブを選択します
そして右側にある「Add scripted field」 を選択します

スクリプトで解析したあとの新しいフィールドの情報を登録します
以下のように登録しましょう

  • Name・・・status
  • Language・・・painless
  • Type・・・number
  • Format・・・Default
  • Popularity・・・0

今回は文字列からステータスコードを取得してみます
なので結果としては数値が返却されるスクリプトを作成します

スクリプトをコーディング

その下にスクリプトを登録するテキストフィールドがあるので登録します
今回は以下のようなスクリプトになります

def log = doc['log.keyword'].value;
if (log != null) {
    // Debug.explain(log);
    def splited = log.splitOnToken(' ');
    try {
        return Integer.parseInt(splited[8]);
    } catch (Exception e) {
    }
}
return 0;

スクリプトを実行できる環境も備わっておりコーディングしながらデバッグすることができます
「Get help with the syntax and preview the results of your script.」をクリックすると右ペインにスクリプトを実行する環境が表示されます
シンタックスエラーやコンパイルエラーの場合はその旨が右ペインに表示されます

エラーが出なければ「Create field」を選択して完了です

スクリプト解説

少し解説します
スクリプトは Kibana が独自で作成している painless という言語になりますがほぼ Groovy っぽく書けます
Groovy なので Java の API も使えます
また painless として独自で作成している関数などもあるようです (splitOnToken はおそらくそれ)
詳しくは参考サイトにもある API リファレンスを参照してください

既存のフィールドを参照するには doc['hoge'].value という感じで参照します
テキストフィールドの場合には .keyword を付与しないとテキスト情報を取得できないので注意してください

あとは状況に応じて数値の情報を return すれば OK です

注意事項

このページの一番下にもあるのですが Scripted field を追加した瞬間にすべてのデータに対してスクリプトが適用されるため負荷が高まる可能性があります
そのせいで ElasticSearch がダウンする可能性もあるので追加する場合は慎重に追加してください

最後に

Scripted field を使って既存のフィールドをパースして新たなフィールドを追加してみました
td-agent などのロガーサイドに手を加える必要がなく Kibana だけで完結できるのは嬉しい点かなと思います
フィールドを使う場合には最初に fielddata=true を投入する必要があるのでそこは注意が必要です

参考サイト

0 件のコメント:

コメントを投稿