logstashのRuby filterでJAVAを呼び出す
logstashではRuby filterで色々できそうですが、業務ではJAVAがメインのため、なんとかJAVAでfilterを制御できないか模索してみました。
なんとか動いたので、こういう方法もあるんだという感じで見れもらえれば。
構成
podman version 3.0.0
elasticsearch 7.10.1
Kibana 7.10.1
logstash 7.11.1
20190524_log.csv
JRubyTest.jar
sample.conf
sample_ruby_filter.rb
logstash実行方法
動作検証中は以下のように-rを付与すると、sample.confが変わるたびにLogstashが設定を自動的にリロードし、再度動いてくれるため検証が楽です。
/usr/share/logstash/bin/logstash -r -f ./sample.conf
logstashの設定ファイル
input {
file {
path => ["/opt/20190524_log.csv"]
sincedb_path => "/dev/null"
start_position => "beginning"
}
}
filter {
ruby {
path => "/opt/sample_ruby_filter.rb"
script_params => {
"source_field" => "1234567890"
}
}
}
output {
stdout {
codec => rubydebug
}
}
filterのpathでrubyスクリプトを記載したファイルパスを設定します。
script_params部分はrubyスクリプトへのパラメータを渡せるようなので記載しましたが、今回は特に使いません。
Rubyスクリプト JAVA呼び出し
require 'java'
require './JRubyTest.jar'
import 'logstash_jruby.JRubyTest'
def register(params)
#ここはlogstash起動時に1度しか呼ばれない模様。
#なのでJAVAの初期化系とか1回だけ実施したい場合に使えると思われる
end
#eventはLogStash::Eventというクラスだった
def filter(event)
#ここは確認用に記載しているだけで記載不要
puts event.class
test = JRubyTest.new
test.exe(event)
return [event]
end
puts event.classでeventのクラスを確認したところ、LogStash::Eventというクラスでした。これを後でJAVAのほうで使います。
たったこれだけの記載で、logstashのイベントをJAVAのほうで制御できるようになります。JAVAをメインに使っているので、Rubyを覚えなくてよくて助かります。
コンパイル時にlogstash-core.jarが必要なため、logstash環境から
/usr/share/logstash/logstash-core/lib/jars/logstash-core.jar
を持ってきて、クラスパスへ追加してください。
JAVAでlogstashのイベントを制御
package logstash_jruby;
import org.logstash.Event;
import org.logstash.ext.JrubyEventExtLibrary.RubyEvent;
public class JRubyTest {
public JRubyTest() {
System.out.println("--JRubyTest constructor--");
}
public void exe(RubyEvent rbe) {
Event event = rbe.getEvent();
System.out.println(event.getField("message").toString());
event.setField("message", "testtest");
}
}
JAVA側で
public void exe(RubyEvent rbe) {
にてlogstashのイベントを受け取ることができます。
System.out.println(event.getField(“message”).toString());
にてイベントの中身messageも取得でき、
event.setField(“message”, “testtest”);
のようにすることでmessageの中身を書き換えることができます。
inputで読み込むファイルの中身
Date,Level,ErrorMessage,UserId
2019-05-24 10:00:00,INFO,Success,1
2019-05-24 11:00:00,WARN,xxxxxxxx,3
logstashの実行結果
LogStash::Event
--JRubyTest constructor--
Date,Level,ErrorMessage,UserId
LogStash::Event
--JRubyTest constructor--
2019-05-24 10:00:00,INFO,Success,1
LogStash::Event
--JRubyTest constructor--
2019-05-24 11:00:00,WARN,xxxxxxxx,3
{
"path" => "/opt/20190524_log.csv",
"@version" => "1",
"message" => "testtest",
"@timestamp" => 2021-02-23T09:26:02.010Z,
"host" => "1777439e2c63"
}
{
"path" => "/opt/20190524_log.csv",
"@version" => "1",
"message" => "testtest",
"@timestamp" => 2021-02-23T09:26:02.012Z,
"host" => "1777439e2c63"
}
{
"path" => "/opt/20190524_log.csv",
"@version" => "1",
"message" => "testtest",
"@timestamp" => 2021-02-23T09:26:02.012Z,
"host" => "1777439e2c63"
}
JAVAのJRubyTestクラスでmessageの中身を書き換えましたが、logstash側でもtesttestになっていることが確認できました。