tl;dr
logstash を理解するあたってプラグイン作ってみることにした。
参考
雑なうんちく
logstash プラグインの種類は?
実装は?
雛形生成
プラグイン作成にあたって雛形を生成するコマンドが用意されている。
/opt/logstash/bin/logstash-plugin generate --type input --name oreno_input --path /path/to/plugins/ /opt/logstash/bin/logstash-plugin generate --type output --name oreno_output --path /path/to/plugins/ /opt/logstash/bin/logstash-plugin generate --type filter --name oreno_filter --path /path/to/plugins/ /opt/logstash/bin/logstash-plugin generate --type codec --name oreno_codec --path /path/to/plugins/
アウトプットプラグインチュートリアル
何を作るか
Mackerel にデータを飛ばすプラグインを作ってみる。
実装、検証の環境
$ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xenial DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS" $ java -version openjdk version "1.8.0_91" OpenJDK Runtime Environment (build 1.8.0_91-8u91-b14-3ubuntu1~16.04.1-b14) OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode) $ /opt/logstash/bin/logstash --version logstash 2.4.0
雛形作成
/opt/logstash/bin/logstash-plugin generate --type output --name mackerel --path ./ Creating ./logstash-output-mackerel create logstash-output-mackerel/logstash-output-mackerel.gemspec create logstash-output-mackerel/Rakefile create logstash-output-mackerel/DEVELOPER.md create logstash-output-mackerel/CONTRIBUTORS create logstash-output-mackerel/CHANGELOG.md create logstash-output-mackerel/LICENSE create logstash-output-mackerel/spec/outputs/mackerel_spec.rb create logstash-output-mackerel/lib/logstash/outputs/mackerel.rb create logstash-output-mackerel/Gemfile create logstash-output-mackerel/README.md
logstash-output-mackerel.gemspec を修正
プラグインの詳細や依存する Gem を記載する。
--- /tmp/logstash-output-mackerel/logstash-output-mackerel.gemspec 2016-10-23 08:34:50.927361142 +0900 +++ logstash-output-mackerel.gemspec 2016-10-23 08:37:28.224957272 +0900 @@ -1,24 +1,25 @@ Gem::Specification.new do |s| - s.name = 'logstash-output-mackerel' - s.version = '0.1.0' - s.licenses = ['Apache License (2.0)'] - s.summary = 'TODO: Write a short summary, because Rubygems requires one.' - s.description = 'TODO: Write a longer description or delete this line.' - s.homepage = 'TODO: Put your plugin''s website or public repo URL here.' - s.authors = [''] - s.email = 'inokara@gmail.com' - s.require_paths = ['lib'] + s.name = 'logstash-output-mackerel' + s.version = "0.0.1" + s.licenses = ["Apache License (2.0)"] + s.summary = "foo." + s.description = "bar." + s.authors = ["kappa"] + s.email = "inokara@example.com" + s.homepage = "http://example.com" + s.require_paths = ["lib"] (snip) # Gem dependencies - s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99" - s.add_runtime_dependency "logstash-codec-plain" + s.add_runtime_dependency "logstash-core", ">= 2.0.0", "< 3.0.0" + s.add_runtime_dependency "mackerel-client" s.add_development_dependency "logstash-devutils" + s.add_development_dependency "mackerel-client"
lib/logstash/outputs/mackerel.rb に処理を書く
エラー処理等はひとまず無し。
# encoding: utf-8 require "logstash/outputs/base" require "logstash/namespace" class LogStash::Outputs::Mackerel < LogStash::Outputs::Base config_name "mackerel" config :api_key, :validate => :string, :required => true config :service_name, :validate => :string, :required => true public def register require 'mackerel/client' @mackerel = Mackerel::Client.new(:mackerel_api_key => @api_key) end public def receive(event) metrics = [{'name' => event.get('host'), 'time' => event.get('timestamp').to_i, 'value' => event.get('value')}] @mackerel.post_service_metrics(@service_name, metrics) end end
config_name
にはプラグイン名を定義config
には logstash の設定ファイル内に記載するパラメータやパラメータのタイプを記載(今回はapi_key
とservice_name
を定義)register
メソッドはinitialize
メソッドのように利用する(今回は Mackerel への接続クライアントを作成している)receive
メソッドはevent
に含まれているデータを次の処理に渡す(今回は mackerel-client-ruby のpost_service_metrics
メソッドを利用して Mackerel にデータをポストする)
尚、receive
メソッドに渡される引数 event
は LogStash::Event
というクラスとなっているので、各要素については以下のように get
メソッドを利用した。
metrics = [{'name' => event.get('host'), 'time' => event.get('timestamp').to_i, 'value' => event.get('value')}]
Gem をビルドする
cd logstash-output-mackerel
gem build logstash-output-mackerel.gemspec
カレントディレクトリに gem ファイルが生成される。
$ ls -l *.gem -rw-rw-r-- 1 kappa kappa 7680 10月 23 08:54 logstash-output-mackerel-0.0.1.gem
ビルドした Gem をインストール
cd logstash-output-mackerel
sudo /opt/logstash/bin/plugin install logstash-output-mackerel-0.0.1.gem
動かしてみる
logstash 設定
input
プラグインにexec
プラグインを利用する(exec
プラグインはcommand
で指定したコマンドを実行して結果をルーティングする)filter
プラグインにgrok
プラグインを利用してinput
プラグインから渡されたデータを整形する(詳細は → https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html)output
プラグインにデバッグ用にstdout
プラグインと今回作成した Mackerel プラグインを指定する
input { exec { # # /tmp/test.sh # echo $(date +%s) ${RANDOM} # # 60 秒毎に /tmp/test.sh を実行する # command => "bash /tmp/test.sh" interval => 60 } } filter { grok { # match => [ "message", "%{NUMBER:timestamp}\s*%{NUMBER:value:int}"] } date { match => [ "timestamp", "UNIX" ] } } output { stdout { codec => rubydebug } mackerel { api_key => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' service_name => 'hogehoge' } }
今回は設定ファイル名を demo.conf として保存しておく。
実行
以下のように logstash を実行する。
/opt/logstash/bin/logstash -f demo.conf
以下のように出力される。
Settings: Default pipeline workers: 4 Pipeline main started { "message" => "1477181478 7945\n", "@version" => "1", "@timestamp" => "2016-10-23T00:11:18.000Z", "host" => "tpX1-Carbon", "command" => "bash /tmp/test.sh", "timestamp" => "1477181478", "value" => 7945 } { "message" => "1477181538 23429\n", "@version" => "1", "@timestamp" => "2016-10-23T00:12:18.000Z", "host" => "tpX1-Carbon", "command" => "bash /tmp/test.sh", "timestamp" => "1477181538", "value" => 23429 }
しばらく放置しておくと...
よし。
以上
- 若干だけど logstash の挙動を理解することが出来た
- 思ったりよりも簡単にプラグインを実装することが出来た