Norikraも0.1になり、この内容もかなり古くなりました。
Norikra0.1にあわせて新しく書き直しているので下記内容をご参照ください!
Norikra 0.1を使ってみた
Norikraで遊んでみた。
RubyKaigiで@tagomorisさんが発表していたNorkraをとりあえず手元で動かしてみた。すごく簡単に説明するとFluentdみたいなデータストリームをSQLライクな言語でごにょごにょできるものである。
NorikraのスライドはSlideShareにあるので是非見ておこう。
この記事はおそらく一瞬で古くなると思うが、環境は次のような感じだ。
product | version |
---|---|
CRuby(MRI) | 2.0.0-p195 |
JRuby | 1.7.4 |
Norikra | v0.0.4 |
Norikra::Client | v0.0.3 |
CRuby、JRubyはrbenvとruby-buildを使ってインストールしている。
JRubyとNorikraをインストールする
$ rbenv install jruby-1.7.4
$ rbenv shell jruby-1.7.4 # このシェルだけJRubyに切り替える
$ ruby -v
jruby 1.7.4 (1.9.3p392) 2013-05-16 2390d3b on Java HotSpot(TM) 64-Bit Server VM 1.6.0_45-b06-451-11M4406 [darwin-x86_64]
$ gem install norikra
# …snip…
Successfully installed norikra-client-jruby-0.0.3-java
Successfully installed norikra-0.0.4-java
15 gems installed
こんなかんじでインストールできた。JRubyはいっこいっこのコマンドがすごくもっさりなので注意だ。
とりあえず起動する
$ rbenv rehash # 一旦rehashを叩く
$ norikra start
log4j:WARN No appenders could be found for logger (com.espertech.esper.core.service.EPServiceProviderImpl).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
"Norikra server started."
norikra-clientを使ってみる
起動したようなので別のシェルからnorikra-clientを叩いてみる。
JRubyだとうまく動かなかったけど、requireが異なるから起こってただけだったのでさくっと書き換えた。
--- .rbenv/versions/jruby-1.7.4/lib/ruby/gems/shared/gems/norikra-client-jruby-0.0.3-java/lib/norikra/client.rb.original 2013-06-04 10:22:08.000000000 +0900
+++ .rbenv/versions/jruby-1.7.4/lib/ruby/gems/shared/gems/norikra-client-jruby-0.0.3-java/lib/norikra/client.rb 2013-06-04 10:12:44.000000000 +0900
@@ -1,6 +1,6 @@
require "norikra/client/version"
-require 'msgpack-rpc-over-http'
+require 'msgpack-rpc-over-http-jruby'
これで動くようになった。CRubyだとこの問題起こらないし、動作さくさくなので普通にCRubyにnorikra-client入れた方が良い。
$ norikra-client
Commands:
norikra-client event CMD ...ARGS # send/fetch events
norikra-client field CMD ...ARGS # manage target field/datatype definitions
norikra-client help [COMMAND] # Describe available commands or one specific command
norikra-client query CMD ...ARGS # manage queries
norikra-client target CMD ...ARGS # manage targets
Options:
[--host=HOST]
# Default: localhost
[--port=N]
# Default: 26571
Norikraでは所謂テーブルの事をtarget、テーブルのカラムのことをfield、クエリのことをquery、入力するログや出力される結果のことをeventと呼ぶ。
とりあえずnorikra-clientで、適当なtargetを作ってみる。
$ norikra-client target open access user:string path:string
$ norikra-client target list
TARGET
access
1 targets found.
で、適当なqueryを書いて登録する。NorikraのクエリはEsperのEPLというSQLライクな言語を使って書く。
$ norikra-client query add access_count "SELECT user, count(*) AS access_count FROM access.win:time_batch(10 sec) GROUP BY user"
あとは適当なeventを流す。
$ echo '{"user":"kame", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"kame", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"kame", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | norikra-client event send access
で、てきとうに結果のeventを見てみる。
$ norikra-client event fetch access_count
{"time":"2013/06/04 10:50:20","user":"kame","access_count":3}
{"time":"2013/06/04 10:50:20","user":"usagi","access_count":4}
$ norikra-client event fetch access_count
{"time":"2013/06/04 10:50:30","user":"kame","access_count":0}
{"time":"2013/06/04 10:50:30","user":"usagi","access_count":0}
こんな感じで結果が返ってくるのがわかる。こんなかんじでSQLライクなクエリでGROUP BYとかが簡単に行えるのである。
Fluentdからログを流したい
実際に使うのであればFluentdからログを流したい。Norikraはfluent-plugin-norikra
を使うことでFluentdとメッセージのやりとりができる。
$ gem install fluent-plugin-norikra
fluent.confに直接Norikraのクエリを記述することもできるが、直接クエリを書いてしまうと変更する度にFluentdを再起動しなくてはいけなくなる。できるのであればFluentdの設定には、データをNorikraに流して結果を受け取ることだけを書きたい。
これを実現できる機能がEvent sweepingのようだ。<event>
セクションを記述することでこれが実現できる。
<source>
type forward # listen port 24224
</source>
<match input.*>
type copy
<store>
type stdout # 標準出力で確認できるように
</store>
<store>
type norikra
norikra localhost:26571 # デフォルト設定
target_map_tag yes # tagをtarget名に使う
remove_tag_prefix input # tagのprefixを除去する
<event>
method sweep
tag query_name # query名をタグにする
tag_prefix norikra.event # tag: norikra.event.QUERYNAME
sweep_interval 5s # 出力間隔
</event>
</store>
</match>
<match norikra.**>
type stdout # 結果も標準出力で確認する
</match>
fluent-plugin-norikraにはNorikraを自動起動する設定とかも書けるが、裏側でエラーが出てないか確認したかったので、とりあえず最低限の設定だけ書いている。Norikraは起動したままでFluentdを起動する。
$ fluentd -c fluent.conf
# …snip…
2013-06-04 10:55:22 +0900 [info]: adding source type="forward"
2013-06-04 10:55:22 +0900 [info]: adding match pattern="input.*" type="copy"
2013-06-04 10:55:22 +0900 [info]: adding match pattern="norikra.**" type="stdout"
2013-06-04 10:55:22 +0900 [info]: listening fluent socket on 0.0.0.0:24224
起動したら別のシェルを開いて、fluent-catからデータを流してみる。流すデータは先程と同じだ。
$ echo '{"user":"kame", "path":"http://example.com/"}' | fluent-cat input.access
$ echo '{"user":"kame", "path":"http://example.com/"}' | fluent-cat input.access
$ echo '{"user":"kame", "path":"http://example.com/"}' | fluent-cat input.access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | fluent-cat input.access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | fluent-cat input.access
2013-06-05 10:58:42 +0900 input.access: {"user":"kame","path":"http://example.com/"}
2013-06-05 10:58:46 +0900 input.access: {"user":"kame","path":"http://example.com/"}
2013-06-05 10:58:51 +0900 input.access: {"user":"kame","path":"http://example.com/"}
2013-06-05 10:58:53 +0900 norikra.event.access_count: {"user":"kame","access_count":3}
2013-06-05 10:58:55 +0900 input.access: {"user":"usagi","path":"http://example.com/"}
2013-06-05 10:58:56 +0900 input.access: {"user":"usagi","path":"http://example.com/"}
2013-06-05 10:59:03 +0900 norikra.event.access_count: {"user":"kame","access_count":0}
2013-06-05 10:59:03 +0900 norikra.event.access_count: {"user":"usagi","access_count":2}
こんなかんじで結果セットをFluentdに流すことができた!
まとめ
ということで、出たばかりのNorikraを使ってみた。Norikra使うとSQLライクな感じでログをフィルタできて楽しいし、なにより動的にクエリを追加したり削除したりできるのが嬉しい。
まだまだ、登録したqueryの削除が実装されてないとか、上記以外の動作だと結構エラー出たりとか実用するにはちょっと足りてなさそうだけど、今後に期待である。