はじめに
Logstashを使ってElasticsearchにデータを入れるときにIndexと9時間ズレることで困ったことないですか??
中身のデータの時刻情報と合わせる方法を備忘録として書いてみました。
利用バージョン
Elasticsearch 6.6.1
Logstash 6.6.1
タイムゾーン問題とは
ElasticsearchのタイムゾーンはUTCで保持していて、ローカルのタイムゾーンに出来ない仕様になっています。
主に以下の2点で困ります。
① Alerting(旧Watcher)で時間範囲指定でアラートを飛ばす時に9時間マイナスしてクエリを書く必要がある。
② Index名をYYYY.MM.dd
とするとIndexが翌日AM9時に切り替わってしまい、ズレてしまう。
※CuratorでIndexのBackup/Deleteする時にズレてしまい運用が複雑になってしまう。
output {
elasticsearch {
hosts => [ "ElasticsearchのIPアドレス:9200" ]
index => "logstash-%{+YYYY.MM.dd}"
}
}
解決策
この問題はlogstashのruby filterを使えば解決することが出来ます。
ruby filterは他filterでどうにも出来ない場合の最終手段というのがElastic社のスタンスみたいです。。
利用シーンが多いですがw
【参考】
・ruby filter plugin
・Moving Custom Ruby Code out of the Logstash Pipeline
以下のようにfilter句でruby filterを利用して日本のタイムゾーンで時刻を取得し
output句でElasticsearchのIndex名に利用することで回避することが可能になります。
filter {
ruby {
code => "event.set('[@metadata][local_time]',event.get('[@timestamp]').time.localtime.strftime('%Y-%m-%d'))"
}
}
output {
elasticsearch {
hosts => [ "ElasticsearchのIPアドレス:9200" ]
index => "logstash-%{[@metadata][local_time]}"
}
}
- ruby filterの
event.set
で(field,value)を作成しています。(rubyのputs的な処理) - field nameは
[@metadata][local_time]
としていますが、[@metadata]を付与することでElasticsearchにIndexingされないfieldにすることができます。 - ruby filterの
event.get
で[@timestamp]のfield nameを指定して、現時刻情報を拾っています。 -
.time.localtime
で[@timestamp]で取得した時刻をローカル時刻に変換しています。 -
.strftime('%Y-%m-%d')
で取得した時刻を文字列に変換しています。
【参考】
・Event API
・ruby localtime(time class)
・ruby strftime(string from time)
まとめ
地味ですが、意外と役に立つのではないでしょうか^^