Logstashのフィルタプラグインを作ってみる (開発環境編)

#はじめに
[Elastic Logstash](https://www.elastic.co/jp/logstash)フィルタプラグインの開発環境を構築するための備忘録。詳細についてはこちらの[公式サイト](https://www.elastic.co/guide/en/logstash/current/filter-new-plugin.html)が非常に参考になります。

#利用するソフトウェア
- OS: Ubuntu 18.04
- Elasticsearch (7.3.2) 
- Kibana (7.3.2)
- Logstash (7.5.2)
- openjdk (11.0.6)
- jruby (9.2.8.0)
- rbenv (1.1.2-20-g143b2c9)
- ruby-build (20200115-8-g73b926b)

#Logstash実行環境の準備
まず通常通りLogstashを[インストール](https://www.elastic.co/guide/en/logstash/current/installing-logstash.html)します。

### JDKのインストール

```bash
$ sudo apt search openjdk-\(\.\)\+-jdk$
openjdk-11-jdk/bionic-updates,bionic-security 11.0.6+10-1ubuntu1~18.04.1 amd64
  OpenJDK Development Kit (JDK)
...

$ sudo apt install openjdk-11-jdk

$ java --version
openjdk 11.0.6 2020-01-14
OpenJDK Runtime Environment (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1)
OpenJDK 64-Bit Server VM (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1, mixed mode, sharing)
```

###Logstashのインストール

```bash
$ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
OK

$ sudo apt-get install apt-transport-https

$ echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list
deb https://artifacts.elastic.co/packages/7.x/apt stable main

$ sudo apt-get update && sudo apt-get install logstash

```

#JRuby実行環境のインストール
開発のRuby実行環境として[JRuby](https://www.jruby.org/)を利用します。

###rbenvとruby-buildのインストール
rbenvとruby-buildをインストールします。

```bash
$ sudo apt-get install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm5 libgdbm-dev git
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l
$ source .bash_profile
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

```

###利用可能なjrubyバージョンをリストアップしてみる

```bash
$ rbenv install -l |grep jruby
jruby-1.5.6
...
jruby-9.2.8.0 ★★★
jruby-9.2.9.0

```
ここでは以下のようにLogstash 7.5.2へ同梱されているデフォルト実行環境に合わせてjruby-9.2.8.0を利用します。


```bash
$ cd /usr/share/logstash/vendor/jruby/bin
$ ./jruby --version
jruby 9.2.8.0 (2.5.3) 2019-08-12 a1ac7ff OpenJDK 64-Bit Server VM 11.0.6+10-post-Ubuntu-1ubuntu118.04.1 on 11.0.6+10-post-Ubuntu-1ubuntu118.04.1 +jit [linux-x86_64]
```

```bash
$ rbenv install jruby-9.2.8.0
```

#フィルタプラグインのテンプレートを生成

Logstashにはプラグインのテンプレートを作成する[**logstash-plugin**ツール](https://www.elastic.co/guide/en/logstash/current/plugin-generator.html)が同梱されていますのでこれを使わせてもらいます。

```bash
$ /usr/share/logstash/bin/logstash-plugin generate --type filter --name helloworld --path ~/logstash-dev/
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
...
 Creating /home/xxxxx/logstash-dev/logstash-filter-helloworld
	 create logstash-filter-helloworld/CONTRIBUTORS
	 create logstash-filter-helloworld/DEVELOPER.md
	 create logstash-filter-helloworld/spec/spec_helper.rb
	 create logstash-filter-helloworld/spec/filters/helloworld_spec.rb
	 create logstash-filter-helloworld/lib/logstash/filters/helloworld.rb
	 create logstash-filter-helloworld/Gemfile
	 create logstash-filter-helloworld/docs/index.asciidoc
	 create logstash-filter-helloworld/LICENSE
	 create logstash-filter-helloworld/Rakefile
	 create logstash-filter-helloworld/README.md
	 create logstash-filter-helloworld/logstash-filter-helloworld.gemspec
	 create logstash-filter-helloworld/CHANGELOG.md

```

ツールへ指定する引数は以下の通り。

|引数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|説明|
|---|---|
|--type|今回はフィルタプラグインを作成するので**filter**を指定|
|--name|**helloworld**とします|
|--path|プラグインを作成するディレクトリ。今回は**~/logstash-dev/**へ作成|

以下のようなディレクトリ構成が生成されます。

```bash:/home/xxxx/logstash-dev/
tree logstash-filter-helloworld
logstash-filter-helloworld
├── CHANGELOG.md
├── CONTRIBUTORS
├── DEVELOPER.md
├── docs
│   └── index.asciidoc
├── Gemfile
├── lib
│   └── logstash
│       └── filters
│           └── helloworld.rb ★★★
├── LICENSE
├── logstash-filter-helloworld.gemspec
├── Rakefile
├── README.md
└── spec
    ├── filters
    │   └── helloworld_spec.rb
    └── spec_helper.rb

6 directories, 12 files

※ 「lib/logstash/filters/helloworld.rb」というファイルがプラグインの本体です。
```

このテンプレートから作成されるプラグインは***"message" => "Hello World!"***というフィールドをイベントへ追加するだけのものです。

```json:Logstashの出力イベント例
{
  "@version": "1",
  "message": "Hello World!", ★★★
  "host": "logstash-dev",
  "@timestamp": "2020-01-04T16:48:14.003Z"
}
```


#プラグイン開発環境のコンフィグレーション

Logstashのfilter pluginを作成するディレクトリに移動します。

```bash
$ cd ~/logstash-dev/logstash-filter-helloworld/

$ pwd
/home/xxxx/logstash-dev/logstash-filter-helloworld

$ rbenv local jruby-9.2.8.0

$ cat .ruby-version 
jruby-9.2.8.0

$ ruby --version
jruby 9.2.8.0 (2.5.7) 2019-10-30 458ad3e OpenJDK 64-Bit Server VM 11.0.6+10-post-Ubuntu-1ubuntu118.04.1 on 11.0.6+10-post-Ubuntu-1ubuntu118.04.1 +jit [linux-x86_64]
```

###テンプレートをビルド

```bash
$ pwd
/home/xxxx/logstash-dev/logstash-filter-helloworld

$ gem install bundler
...
$ gem build logstash-filter-example.gemspec 
...
You have one or more invalid gemspecs that need to be fixed.
The gemspec at
/home/xxxxx/logstash-dev/logstash-filter-helloworld/logstash-filter-helloworld.gemspec
is not valid. Please fix this gemspec.
The validation error was '"FIXME" or "TODO" is not a description'

```

エラーメッセージに従ってテキストエディタで**logstash-filter-helloworld.gemspec**の**TODO**(★★★部分)を修正します。

```ruby:logstash-filter-helloworld.gemspec
Gem::Specification.new do |s|
  s.name          = 'logstash-filter-helloworld'
  s.version       = '0.1.0'
  s.licenses      = ['Apache-2.0']
  s.summary       = 'Hello world plugin' ★★★
  s.description   = 'Add a hellowrld field to event' ★★★
  s.homepage      = 'http://xxx.example.com/helloworld' ★★★
  s.authors       = ['']
  s.email         = ''
  s.require_paths = ['lib']

```

再度ビルドします。

```bash
$ pwd
/home/xxxx/logstash-dev/logstash-filter-helloworld

$ gem build logstash-filter-example.gemspec 
...
$ ls
CHANGELOG.md  Gemfile       logstash-filter-helloworld-0.1.0.gem  spec
CONTRIBUTORS  Gemfile.lock  logstash-filter-helloworld.gemspec
DEVELOPER.md  lib           Rakefile
docs          LICENSE       README.md

```
無事に***logstash-filter-helloworld-0.1.0.gem***が生成されていればOKです。

#プラグインをインストール

```bash
$ cd /usr/share/logstash/

$ sudo bin/logstash-plugin install ~/logstash-dev/logstash-filter-helloworld/logstash-filter-helloworld-0.1.0.gem
...
Validating /home/xxxx/logstash-dev/logstash-filter-helloworld/logstash-filter-helloworld-0.1.0.gem
Installing logstash-filter-helloworld
Installation successful

```

#インストールしたhelloworldプラグインを実行してみる

```bash
$ sudo bin/logstash -e 'input { stdin{} } filter { helloworld {} } output {stdout { codec => json_lines}}'
...
Thread.exclusive is deprecated, use Thread::Mutex
...
[INFO ] 2020-01-04 01:38:03.121 [LogStash::Runner] runner - Starting Logstash {"logstash.version"=>"7.5.2"}
...
[INFO ] 2020-01-04 01:38:05.485 [Converge PipelineAction::Create<main>] helloworld - Using version 0.1.x filter plugin 'helloworld'. This plugin isn't well supported by the community and likely has no maintainer.
...
The stdin plugin is now waiting for input:
...
test <= 何か入力
{
  "@version": "1",
  "message": "Hello World!",
  "host": "logstash-dev",
  "@timestamp": "2020-01-04T16:48:14.003Z"
}

```
**message: "Hello World!"**というフィールドが追加されています。


#まとめ

テンプレートによる開発環境が構築できました。次回は実際にプラグイン本体（「lib/logstash/filters/helloworld.rb」）を実装してみます。