1Fieldに複数datatypeが存在する場合の対処

こんにちは、現在下記の1フィールドに入っている、数値型と文字列型を含むデータを取り込もうとしています。
image
image
・データの例
[数値型] 99.338053
[文字列型] jenkins-test

データ型を数値型に指定すると、下記のエラーが発生します。

[2019-09-23T14:23:53,594][WARN ][logstash.outputs.elasticsearch] Could not index event to Elasticsearch. {:status=>400, :action=>["index", {:_id=>nil, :_index=>"zabbix-history02-2019.09", :_type=>"_doc", :routing=>nil}, #LogStash::Event:0x5acf45aa], :response=>{"index"=>{"_index"=>"zabbix-history02-2019.09", "_type"=>"_doc", "_id"=>"3FCTXG0BzLVwUw45gDUb", "status"=>400, "error"=>{"type"=>"mapper_parsing_exception", "reason"=>"failed to parse field [value] of type [float] in document with id '3FCTXG0BzLVwUw45gDUb'. Preview of field's value: 'HotSpot 64-Bit Tiered Compilers'", "caused_by"=>{"type"=>"number_format_exception", "reason"=>"For input string: "HotSpot 64-Bit Tiered Compilers""}}}}}

また、データ型を文字列型に指定すると、数値データを集計(avg等)することが出来ません。

この問題を解決するためのヒント等をご存じの方がいましたら、アドバイス頂けないでしょうか。
(例)
・Index templateの設定方法
・Logstash側でデータ型を判断して、1フィールドを複数フィールドに分ける等。

よろしくお願いします。

こんにちわ

1つのフィールドには1つの意味を持つデータを入れる方が良いと考えております。
そのため、集計したい数値が入る項目と、文字列で入るjenkins-testと入るような項目は、意味が違う、用途も違うものになるかと思いますので、それぞれ別のフィールドとして定義しまうのが良いのではないかと思います。

Logstashで思いつく対応を書いてみます。

数値・文字列の中身の区別が他フィールドで判断できるとき

たとえば、既にhoge_fieldが数値型フィールドであり、文字列が入ったsome_fieldを持つデータソースのときは、リネームして混在を避けることができるかと思います。

Mutateのrenameを参照してください。
https://www.elastic.co/guide/en/logstash/current/plugins-filters-mutate.html

if [some_field] == "何か判定できる値" {
    mutate {
       # hoge_fieldをhoge_text_fieldに変名し、数値型フィールドと混在しないようにする
        rename => ["hoge_field", "hoge_text_field"]
    }
}

フィールド名を変名することで、同じフィールド名で定義が異なるようなデータが存在しなくなります。

他に識別するフィールドがなさそうなとき

入っている値に応じて、他のフィールドに値を書く、ということをrubyで書くことで対応できるかと思います。

例)数値だったら、hoge_field_numberにセット、文字列だったら、hoge_text_fieldにセットする

https://www.elastic.co/guide/en/logstash/current/plugins-filters-ruby.html

こちらの方が「Logstash側でデータ型を判断して、1フィールドを複数フィールドに分ける等」で求めている内容に近いかもしれません。

ご参考になれば幸いです。

1 Like

対応方法を教えて頂き、ありがとうございます。
https://www.elastic.co/guide/en/logstash/current/event-dependent-configuration.html

regexp: =~ , !~ (checks a pattern on the right against a string value on the left)

アドバイス頂いたif文と上記の正規表現判定を使って下記のように書く事で、概ね「1フィールド内の数値と文字を、複数フィールドに分割」することが出来ました。

数値以外(文字列)の場合、フィールド名を変更(value→textvalue)
if [value] !~ /^[0-9.]+$/ {
mutate{
rename => { "value" => "textvalue" }
}
}

とても参考になりました。アドバイスありがとうございます。

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.